Forum Discussion

Michael Blumenthal's avatar
Apr 03, 2017

Using PowerShell to talk to the Office 365 Service Communications API

I want to use PowerShell to export the most recent week's worth of Admin Message Center Messages to a spreadsheet because I want to annotate each item with what I am planning to do about each announcement. #Governance

 

I have an account for this purpose that is a global tenant admin and that does not use MFA.

 

I believe I need to use the O365 Service Communication API (Preview) as described at https://msdn.microsoft.com/office-365/office-365-service-communications-api-reference, in particular with this REST URI:  https://manage.office.com/api/v1.0/contoso.com/ServiceComms/Messages

 

In PowerShell, there is the Invoke-RestMethod command.

I'm passing the above URI (except with contoso.com replaced) for the value of the -URI parameter.

However, for authentication, passing a Credential doesn't work.  I need to create an Authorization Header with a value of Bearer and an AAD_Bearer_JWT_Token.

I'm lost when it comes to creating that. 

 

Do I really need to set up an Application listing in Azure Ad for my PowerShell script, per https://msdn.microsoft.com/en-us/office-365/get-started-with-office-365-management-apis ?

If so, beside the UI of the management portal having been redone, I don't see the Service Communication APIs being listed as an option when I am supposed to grant the application permission to access them.

 

Can anyone shed some light on this?

paulschaeflein Dean_Gross Anna Chu Todd Klindt Anne Michels Peter Walke

 

 

 

 

 

19 Replies

  • Josh Biddle's avatar
    Josh Biddle
    Copper Contributor

    I created a script to query the old API (before I knew there was a new one).  It works for the most part.  I send 22 variables back to my RMM (N-Central) to use as an alerting tool.  I haven't turned alerting on for it yet because I've still been testing it for the most part.  The one thing I have noticed is that sometimes the messagetext does not always show what it should.  It should show messagetext[0] which would correspond to the last message posted for the service, but sometimes it get skewed.  I'm leaning towards this being an anomaly in the method Microsoft uses to post the messages.  I've spent all night tonight (8+ hours) and an equal amount of time other nights trying to figure out how to port this to the new API but I keep coming up short.  So far the closest I have come is by using the Exch-REST module and using the Get-EXRMSubscriptionContentBlob cmdlet.  See below.

     

    $tenantGUID = "YOURTENANTID"

    $test = Get-EXRMSubscriptionContentBlob -ContentURI "https://manage.office.com/api/v1.0/$tenantGUID/ServiceComms/Messages"
    # This will net you almost what $Events will from the O365ServiceCommunications module

    $test.value | ? {$_.WorkloadDisplayName -ne $null} | FT ID,WorkloadDisplayName,StartTime,EndTime,LastUpdatedTime,Status
    $test.value.messages.messagetext

     

    Here is the code for the script for the previous API.  Let's keep this thread going.  I'd really like to crack the mystery of API v2.  :)

     

    PS: To get the pertinent data from the script you'll want to return $service and $servicemsg for each of the services - these are the variables I am sending back to my RMM.

     

    Cheers,

    Josh

     

    PSS: Here are some notes on how to create the Azure App and obtain the oAuth token.

     

    https://docs.microsoft.com/en-us/office/office-365-management-api/

    Follow instructions here to create Azure App for Certificate Secret key: https://docs.microsoft.com/en-us/office/office-365-management-api/get-started-with-office-365-management-apis

    Here's a video outlining some of the process: https://www.youtube.com/watch?v=WygwzN9FfMQ

     

    # Create certificate, then Export .cer via MMC > Certificates Snap-In > My User Account

    $cert = New-SelfSignedCertificate -Type CodeSigningCert -KeySpec Signature `
    -Subject "E=my@email.com,CN=My Name" -KeyExportPolicy Exportable `
    -HashAlgorithm sha256 -KeyLength 2048 -NotAfter ((Get-Date).AddYears(10)) `
    -FriendlyName "Company Name Office 365 Service Communications API" `
    -CertStoreLocation "Cert:\CurrentUser\My" -KeyUsageProperty Sign -KeyUsage CertSign

     

    # Get values to create oAuth token
    $cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
    $cer.Import("C:\Users\xxxx\xxxx\O365CommAPI.cer")
    $bin = $cer.GetRawCertData()
    $base64Value = [System.Convert]::ToBase64String($bin)
    $bin = $cer.GetCertHash()
    $base64Thumbprint = [System.Convert]::ToBase64String($bin)
    $keyid = [System.Guid]::NewGuid().ToString()

    Error updating manifest?:
    "Failed to save manifest. Error details: KeyValueMustBeNull"
    https://social.msdn.microsoft.com/Forums/en-US/0e88e784-5e5b-496f-b554-0935ab34b440/cannot-update-keycredential-value-in-azure-application-manifest?forum=WindowsAzureAD
    "because the key is already stored. If you go to "Settings -> Keys" and remove the public key stored here it is possible to update it again."

    # Create app of type Web app / API in Azure AD, generate a Client Secret, and update the client id and client secret here
    $ClientID = "xxxx"
    $ClientSecret = "xxxx"
    $loginURL = "https://login.microsoftonline.com/"
    $tenantdomain = "xxxx"
    # Get the tenant GUID from Properties | Directory ID under the Azure Active Directory section
    # https://docs.microsoft.com/en-us/onedrive/find-your-office-365-tenant-id
    $TenantGUID = "xxxx"
    $resource = "https://manage.office.com"
    # auth
    $body = @{grant_type="client_credentials";resource=$resource;client_id=$ClientID;client_secret=$ClientSecret}
    $oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$tenantdomain/oauth2/token?api-version=1.0 -Body $body
    $headerParams = @{'Authorization'="$($oauth.token_type) $($oauth.access_token)"}

     

    I'm not exactly sure what to do once you have the token, but this is where I left off - also using the Exch-REST module I was able to somewhat replicate the data obtained from the O365ServiceCommunications module.  Was anyone able to make it any further?

  • Hi Michael,

    The v2 API (preview) requires that you register the script/app.  One immediate term option is to use the non-preview v1 API.  Sample code may be found here (download the zip file and look inside the Word document).  Also follow along with this blog series for additional code samples that are forthcoming.

    Thanks,

    Anne

    • Brian Teerlynck's avatar
      Brian Teerlynck
      Copper Contributor

      Hello Anne,

       

      I'm using powershell to contact the service communication API's (connecting via the azure app)

      Now i am able to get data from the API's but i want to set a filter that returns only data from a specific time. Do you have an idea how this filter should be built?

      Get Messages

      Description:

      Returns the messages about the service over a certain time range. Use the type filter to filter for "Service Incident", "Planned Maintenance", or "Message Center" messages.

        Service Description
      Path/Messages 
      FiltersStartTime
      Filter by Start Time (DateTimeOffset, default: ge CurrentTime - 7 days).
         

       

      I'm trying to create this uri with above filter: 

      "https://manage.office.com/api/v1.0/$tenant/ServiceComms/Messages?$filter=StartTime ge 'CurrentTime - 2 days'"

       

      Source:

      https://msdn.microsoft.com/en-us/office-365/office-365-service-communications-api-reference

       

      Thanks in advance!

      Brian

       

      • Dean_Gross's avatar
        Dean_Gross
        Silver Contributor

        Brian Teerlynckdid you ever figure out how to get this type of filter to work? or how to get just the messages from the Message Center?

    • Vasil, thanks for pointing me to that.  One thing that concerns me about that example is that it is using the old version of the API.  Note the command to get the cookie:

      $cookie = (invoke-restmethod -contenttype "application/json" -method Post -uri "https://api.admin.microsoftonline.com/shdtenantcommunications.svc/Register" -body $jsonPayload).RegistrationCookie

      It uses the old URI.  The documentation for the old API is at https://msdn.microsoft.com/en-us/library/office/dn776043(v=office.15).aspx and says "A new version of the Office 365 Service Communications API has been released in preview mode. It is recommended that new applications be built using this version. For more information, see Office 365 Service Communications API reference (preview)."

       

      How would I do the registration step with the new API?  I don't see a Register method listed for the new API.

      Michael

Resources