Office 365 Service Communications API

Auch wenn Microsoft mit der Graph API eine universelle Schnittstelle weiter entwickelt, gibt es immer noch andere Schnittstellen wie EWS aber auch manage.office.com, die zumindest einige Zeit weiter parallel betrieben werden. Auf der Seite Office 365 Status habe ich verschiedene Wege zur Statusabfragen vorgestellt, auf deren Basis ich hier ein Skript für die neue API beschreibe.

Vorgeschichte

Auf der Seite Office 365 Status finden Sie noch einen Code, mit dem ich den Status von Office 365 Diensten früher abgefragt habe. Diese alte API ist aber abgekündigt. Anfang 2016 hat Microsoft die "Office 365 Service Communications API V2 " als "Preview" veröffentlicht, und schreibt zugleicht, dass der Wechsel schnell gehen kann.

...New features will only be added to the new version of the API, encouraging early adoption by legacy customers. When the General Announcement of Office 365 Service Communications API is made, the older version of the Service Communications API will begin a period of deprecation.
Quelle: https://msdn.microsoft.com/en-us/library/dn707385.aspx

Auch die Office 365 Service Communications API ist eine REST-API und damit von Graph API nicht weit entfernt. Vielleicht wird sie ja in naher Zukunft in Graph eingebunden. Bis dahin ist die URL noch "https://manage.office.com"

Berechtigungen und Authentifizierung

Wie viele weiteren APIs können Sie sich an "manage.office.com" meines Wissens nicht mehr einfach durch Benutzername/Kennwort anmelden. Ihre Lösung muss sich als Applikation ausweisen und damit direkte die Berechtigungen erhalten oder als Applikation dann mit den Berechtigungen des Anwender arbeiten (Delegated Permission).

Da mein Beispiel ganz ohne Mithilfe eines Anwenders agieren soll, nutze ich bei der weiteren Beschreibung den Weg einer Application Permission

Wir brauchen eine App

Für den Zugriff auf die neue API muss der Administrator im Azure AD erst die Application registrieren und mit Berechtigungen versehen. Dazu gehen Sie einfach in das Azure Portal und legen eine neue Applikation unter "App Registrations" an . Den Namen können Sie frei auswählen, aber sie müssen noch eine Authentifizierung (z.B. per Client Secret oder Zertifikat) hinterlegen.

Für die Anmeldung im PowerShell-Script brauchen Sie dann nur noch die Client-ID und eben den Secret aus dem AzurePortal. Diese Applikation hat nun also drei Komponenten

  • Tenantname
  • ClientID
  • ClientSecret

Diese drei Informationen brauchen wir später im Code. ich habe die daher einfach mal als Variablen definiert

$tenantname = "msxfaq.onmicrosoft.com",
$ClientID = '<ihre cliend id hier',
$ClientSecret = '<ihr secret hier>'

Die Credentials sollten sie später aber auslagern (Siehe z.B. PS Passwort / Kennwort

Rechte für die App

Allein mit Zugangsdaten für eine Applikation ist es natürlich nicht getan. Ich muss dem Skript natürlich noch die entsprechenden Berechtigungen vergeben.

All API requests require an Authorization HTTP header that has a valid OAuth2 JWT access token obtained from Azure AD that contains the ServiceHealth.Read claim; and the tenant identifier must match the tenant identifier in the root URL.
Quelle: https://docs.microsoft.com/en-us/office/office-365-management-api/office-365-service-communications-api-reference 

In dem Beispiel gebe ich der Applikation das Recht "ServiceHealthRead"

Vergessen Sie danach nicht die Berechtigung für den gesamten Tenant über "Admin Consent" zu geben.

Token anfordern

Jeder Zugriff auf die Office 365 Service Communications API erfolgt authentifiziert durch ein Token. Also holen wir uns zuerst ein Token als Applikation. Dazu müssen wir einen HTTP-Request vorbereiten, bei dem wir im Body die Anmeldedaten als JSON-Request mitliefern. Wir bauen also zuerst den Body:

$body = @{
   grant_type = "client_credentials"
   client_id = $ClientID
   client_secret = $ClientSecret
   resource = "https://manage.office.com"
}

Und dann starten wir den Aufruf

$Token = Invoke-RestMethod `
            -Uri "https://login.microsoftonline.com/$($tenantname)/oauth2/token" `
            -Method Post `
            -Body $body

In der Variable "$token" steht nun eine Struktur, die auch das Token enthält.

Wenn Sie das Token kontrollieren, wollen, dann sollten Sie sich das Token mit "$Token.access_token" ausgeben lassen, z.B. in die Zwischenablage

# Exemplarische Ausgabe
$Token.access_token | clip

Über Webseiten wie https://jwt.ms  oder https://jwt.io können Sie das Token dann decodieren lassen.

Sie sollten hier ein gültiges Token sehen, in dem auch die Berechtigungsrolle sichtbar ist.

Achtung: ein Token ist einige Zeit gültig und sie sollten nicht für jeden Request immer wieder ein neues Token anfordern sondern ein noch gültiges Token solange nutzen, solange es nicht abgelaufen ist. Ihre Applikation ist schneller und der evoSTS-Server wird entlastet.

Office 365 Status anfordern

Mit diesem Token bauen wir nun den nächsten Request und senden ihn an die Cloud. Dazu nutzen wir das Token und bilden daraus einen Authorization-Header für den dann folgenden HTTP-Request:

$header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$header["authorization"] = "Bearer $($Token.access_token)"
Write-host "Invoke " -nonewline
$o365status = Invoke-RestMethod `
               -Uri "https://manage.office.com/api/v1.0/$($tenantname)/ServiceComms/CurrentStatus" `
               -Method GET `
               -Header $header

Wenn Sie hier keine Fehlermeldung bekommen, dann sollte in $o365status

Status Antwort auswerten

Die zurückgegebene Information kann recht umfangreich sein. Werten Sie dazu einfach den Inhalt von "$request" aus.

$o365status.value | ft id,status,statustime,incidentids -AutoSize

Id                       Status             StatusTime          IncidentIds
--                       ------             ----------          -----------
DynamicsAX               ServiceOperational 08.12.2019 13:08:13 {}
DynamicsCRM              ServiceOperational 08.12.2019 13:08:13 {}
Exchange                 ServiceOperational 08.12.2019 13:08:13 {}
Forms                    ServiceOperational 08.12.2019 13:08:13 {}
Intune                   ServiceOperational 08.12.2019 13:08:13 {}
kaizalamessagingservices ServiceOperational 08.12.2019 13:08:13 {}
Lync                     ServiceDegradation 08.12.2019 13:08:13 {LY197383}
MDATP                    ServiceOperational 08.12.2019 13:08:13 {}
MicrosoftFlow            ServiceOperational 08.12.2019 13:08:13 {}
MicrosoftFlowM365        ServiceOperational 08.12.2019 13:08:13 {}
microsoftteams           ServiceOperational 08.12.2019 13:08:13 {}
MobileDeviceManagement   ServiceOperational 08.12.2019 13:08:13 {}
O365Client               ServiceOperational 08.12.2019 13:08:13 {}
officeonline             ServiceOperational 08.12.2019 13:08:13 {}
OneDriveForBusiness      ServiceDegradation 08.12.2019 13:08:13 {OD197264, OD197692}
OrgLiveID                ServiceOperational 08.12.2019 13:08:13 {}
OSDPPlatform             ServiceOperational 08.12.2019 13:08:13 {}
OSub                     ServiceOperational 08.12.2019 13:08:13 {}
Planner                  ServiceOperational 08.12.2019 13:08:13 {}
PowerApps                ServiceOperational 08.12.2019 13:08:13 {}
PowerAppsM365            ServiceOperational 08.12.2019 13:08:13 {}
PowerBIcom               ServiceOperational 08.12.2019 13:08:13 {}
RMS                      ServiceOperational 08.12.2019 13:08:13 {}
SharePoint               ServiceDegradation 08.12.2019 13:08:13 {SP197263, SP197691}
SocialEngagement         ServiceOperational 08.12.2019 13:08:13 {}
StaffHub                 ServiceOperational 08.12.2019 13:08:13 {}
yammer                   ServiceOperational 08.12.2019 13:08:13 {}

Ich habe hier nur mal ein Teil der Properties ausgegeben. Je nach ihren Lizenzen kann die Liste variieren. Interessant sind hier natürlich die Objekte mit einem Status ungleich "ServiceOperatoinal" und dann sind die dazugehörigen IncidentIds interessant.

Messages holen

Die Statusübersicht ist aber nur ein erster Einblick. Interessant sind hier die "IncidentIDs", welche weitere Details liefert. Der Abruf ist wie folgt möglich. Den Header mit dem Token haben wir ja noch.

Auf der Seite https://docs.microsoft.com/en-us/office/office-365-management-api/office-365-service-communications-api-reference ist schön beschrieben, wie ein Aufruf mit Filtern möglich sein sollte. Alle Varianten, von denen ich hier nur mal zwei wiedergebe, haben aber alle entweder einen Fehler geworfen, dass der Filter nicht erlaubt ist oder ohne Fehler einfach alle Meldungen geliefert..

$requestmsg = Invoke-RestMethod `
                 -Uri "https://manage.office.com/api/v1.0/$($tenantname)/ServiceComms/Messages?`$filter=ID%20eq%20'SP197263'" `
                 -Method Get `
                 -Header $header
$requestmsg = Invoke-RestMethod `
                 -Uri "https://manage.office.com/api/v1.0/$($tenantname)/ServiceComms/Messages?top%20eq%2010" `
                 -Method Get `
                 -Header $header

Dann kann ich mir die Filter auch sparen und alle Daten abfragen:

$messages = Invoke-RestMethod `
                 -Uri "https://manage.office.com/api/v1.0/$($tenantname)/ServiceComms/Messages" `
                 -Method Get `
                 -Header $header

# bei mir sind es eine ganze Menge an Meldungen
$messages.value.Count
196

# Exemplarisch habe ich eine Meldung extrahiert
$messages.value[0] | gm

   TypeName: System.Management.Automation.PSCustomObject
Name                         MemberType   Definition
----                         ----------   ----------
Equals                       Method       bool Equals(System.Object obj)
GetHashCode                  Method       int GetHashCode()
GetType                      Method       type GetType()
ToString                     Method       string ToString()
ActionType                   NoteProperty object ActionType=null
AdditionalDetails            NoteProperty Object[] AdditionalDetails=System.Object[]
AffectedTenantCount          NoteProperty long AffectedTenantCount=0
AffectedUserCount            NoteProperty object AffectedUserCount=null
AffectedWorkloadDisplayNames NoteProperty Object[] AffectedWorkloadDisplayNames=System.Object[]
AffectedWorkloadNames        NoteProperty Object[] AffectedWorkloadNames=System.Object[]
Classification               NoteProperty string Classification=Advisory
EndTime                      NoteProperty datetime EndTime=21.11.2019 18:13:45
Feature                      NoteProperty string Feature=crmcomponents
FeatureDisplayName           NoteProperty string FeatureDisplayName=Components/Features
Id                           NoteProperty string Id=CR196351
ImpactDescription            NoteProperty string ImpactDescription=Users may be unable to select specific search optio…
LastUpdatedTime              NoteProperty datetime LastUpdatedTime=21.11.2019 18:13:57
Messages                     NoteProperty Object[] Messages=System.Object[]
MessageType                  NoteProperty string MessageType=Incident
PostIncidentDocumentUrl      NoteProperty object PostIncidentDocumentUrl=null
Severity                     NoteProperty string Severity=Sev2
StartTime                    NoteProperty datetime StartTime=21.11.2019 14:54:00
Status                       NoteProperty string Status=False positive
Title                        NoteProperty string Title=Search options unavailable in Advanced Find
UserFunctionalImpact         NoteProperty string UserFunctionalImpact=
Workload                     NoteProperty string Workload=DynamicsCRM
WorkloadDisplayName          NoteProperty string WorkloadDisplayName=Dynamics 365

# Ausgabe nach Severity. nicht alle meldungen sind relevant
$messages.value | group severity -NoElement

Count Name
----- ----
7 High
134 Normal
1 Sev0
11 Sev1
43 Sev2

Relevante Messages

Eine Filterung nach den relevanten Einträgen erfolgt dann auf dem Client. Aus der Liste aller Statusmeldungen lassen sich die aktiven Incidents ermitteln

$o365status.value | where {$_.IncidentIds} | select IncidentIds -ExpandProperty IncidentIds
LY197383
OD197264
OD197692
SP197263
SP197691

Mit der Liste können dann die Messages extrahiert werden, die aber ganz schön umfangreich sein können:

$messages.value | ?{$_.id -eq "LY197383"}

AffectedWorkloadDisplayNames : {}
AffectedWorkloadNames        : {}
Status                       : Service degradation
Workload                     : Lync
WorkloadDisplayName          : Skype for Business
ActionType                   :
AdditionalDetails            : {}
AffectedTenantCount          : 0
AffectedUserCount            :
Classification               : Incident
EndTime                      :
Feature                      : Federation
FeatureDisplayName           : Federation
UserFunctionalImpact         :
Id                           : LY197383
ImpactDescription            : Users may be unable to initiate chat messages, audio calls, or video calls to specific
                               external federated users.
LastUpdatedTime              : 07.12.2019 20:25:17
MessageType                  : Incident
Messages                     : {@{MessageText=Title: Can't send messages or make calls to specific federated users

                               User Impact: Users may be unable to initiate chat messages, audio calls, or video calls
                               to specific external federated users.

                               More info: This event affects tenants who have users hosted in Skype for Business and
                               on-premises with the same domain, with name space set to False, and are making
                               federation calls to federated users on-premises. This does not affect tenants who are
                               strictly hosted in Skype for Business, nor users who have domain name space set to True.

                               Current status: We've developed and applied a temporary fix to a small group of users
                               as a validation measure. We're reaching out to those users to verify that the fix was
                               successful. Meanwhile, we're working on the permanent code change for the remaining
                               users.

                               Scope of impact: This issue may potentially affect a subset of your on-premises users
                               attempting to call federated on-premises users only.

                               Start time: Sunday, December 1, 2019, at 4:00 AM UTC

                               Root cause: A recent code update intended to address federation routing issues resulted
                               in impact to users in a specific federation configuration.

                               Next update by: Thursday, December 5, 2019, at 8:00 PMUTC; PublishedTime=05.12.2019
                               04:30:18}, @{MessageText=Title: Can't send messages or make calls to specific federated
                               users

                               User Impact: Users may be unable to initiate chat messages, audio calls, or video calls
                               to specific external federated users.

                               More info: This event affects tenants who have users hosted in Skype for Business and
                               on-premises with the same domain, with name space set to False, and are making
                               federation calls to federated users on-premises. This does not affect tenants who are
                               strictly hosted in Skype for Business, nor users who have domain name space set to True.

                               Current status: We've validated that the short term fix has alleviated impact and we've
                               started deploying this temporary fix to the entirety of the affected environment. We
                               suspect that this temporary fix will be fully saturated by the end of the day. In
                               parallel, we're working on a permanent code fix for this problem and suspect that it
                               will start deploying within the next three days.

                               Scope of impact: This issue may potentially affect a subset of your on-premises users
                               attempting to call federated on-premises users only.

                               Start time: Sunday, December 1, 2019, at 4:00 AM UTC

                               Root cause: A recent code update intended to address federation routing issues resulted
                               in impact to users in a specific federation configuration.

                               Next update by: Friday, December 6, 2019, at 1:00 AMUTC; PublishedTime=05.12.2019
                               19:30:25}, @{MessageText=Title: Can't send messages or make calls to specific federated
                               users

                               User Impact: Users may be unable to initiate chat messages, audio calls, or video calls
                               to specific external federated users.

                               More info: This event affects tenants who have users hosted in Skype for Business and
                               on-premises with the same domain, with name space set to False, and are making
                               federation calls to federated users on-premises. This does not affect tenants who are
                               strictly hosted in Skype for Business, nor users who have domain name space set to
                               True.

                               Current status: We've completed deployment of the short term fix and the issue has been
                               mitigated for all users. We're in the process of developing the permanent fix to
                               prevent this issue from happening again and expect to begin internal testing by Friday,
                               December 6, 2019.

                               Scope of impact: This issue may potentially affect a limited number of your on-premises
                               users attempting to call federated on-premises users only.

                               Start time: Sunday, December 1, 2019, at 4:00 AM UTC

                               Root cause: A recent code update intended to address federation routing issues resulted
                               in impact to users in a specific federation configuration.

                               Next update by: Friday, December 6, 2019, at 8:30 PMUTC ; PublishedTime=05.12.2019
                               23:48:50}, @{MessageText=Title: Can't send messages or make calls to specific federated
                               users

                               User Impact: Users may be unable to initiate chat messages, audio calls, or video calls
                               to specific external federated users.

                               More info: This event affects tenants who have users hosted in Skype for Business and
                               on-premises with the same domain, with name space set to False, and are making
                               federation calls to federated users on-premises. This does not affect tenants who are
                               strictly hosted in Skype for Business, nor users who have domain name space set to True.

                               Current status: We've completed development of the permanent fix for this issue and are
                               deploying to an internal test environment to verify it fully resolves the problem. Once
                               confirmed, we'll provide a timeline for deployment to all affected environments.

                               Scope of impact: This issue may potentially affect a limited number of your on-premises
                               users attempting to call federated on-premises users only.

                               Start time: Sunday, December 1, 2019, at 4:00 AM UTC

                               Root cause: A recent code update intended to address federation routing issues resulted
                               in impact to users in a specific federation configuration.

                               Next update by: Friday, December 6, 2019, at 10:30 PMUTC; PublishedTime=06.12.2019
                               20:35:19}…}
PostIncidentDocumentUrl      :
Severity                     : Sev2
StartTime                    : 01.12.2019 04:00:00
Title                        : Can't send messages or make calls to specific federated users

Einer weiteren Verarbeitung als RSS-Feed, interne Publikation o.ä. steht aber nichts im Wege.

Weitere Links