Upcoming changes to the Connect-IPPSSession cmdlet (the EnableSearchOnlySession switch)

A recent message center post, MC1131771, notified us about upcoming changes to PowerShell connectivity to the Security & Compliance endpoint. In particular, starting Aug 31st, some cmdlets exposed via said endpoint will require you to leverage the -EnableSearchOnlySession parameter when running the Connect-IPPSSession cmdlet. The set of cmdlets includes:

  • New-ComplianceSearchAction
  • New-CaseHoldPolicy
  • Set-CaseHoldPolicy
  • Remove-CaseHoldPolicy
  • New-CaseHoldRule
  • Set-CaseHoldRule
  • Remove-CaseHoldRule
  • New-ComplianceSecurityFilter
  • Set-ComplianceSecurityFilter
  • Get-ComplianceSecurityFilter
  • Remove-ComplianceSecurityFilter

Since the -EnableSearchOnlySession switch parameter is only available in the latest (preview) version of the Exchange Online Management PowerShell module, this means that you will have to update the module by the end of this month. If you are using any of the aforementioned cmdlets that is, as the 3.9.0-Preview1 version doesn’t bring any other changes, it seems. And you probably don’t want to use a preview build, unless it is really necessary.

A look behind the covers reveals that the only thing the -EnableSearchOnlySession switch does is to update the audience of the access token used as part of the authentication process. As far as I can tell, there are no other differences, for the time being at least – the same number of cmdlets is available and the size of the downloaded module remains the same. All of the cmdlets listed above are still available, regardless of whether you established the session with or without the switch. Of course, things will likely change as we approach the deadline.

For now, the interesting thing is the new endpoint/access token. Good old Fiddler reveals that the request is still made using the same client id, fb78d390-0c51-40cd-8e17-fdbfab77341b (“Microsoft Exchange REST API Based Powershell”). However, a difference resource/audience value is used, namely https://dataservice.o365filtering.com. The requested scopes are more or less the same, but do reflect the new resource value:

https://dataservice.o365filtering.com/AdminApi.AccessAsUser.All
https://dataservice.o365filtering.com/FfoPowerShell.AccessAsUser.All
https://dataservice.o365filtering.com/RemotePowerShell.AccessAsUser.All
https://dataservice.o365filtering.com/.default

With that information at hand, we can obtain an access token ourselves, leveraging the standard OAuth flows. The example below uses MSAL’s AcquireTokenInteractive() method and will obtain an access token in the delegate context leveraging the standard auth code flow:

$appId = "fb78d390-0c51-40cd-8e17-fdbfab77341b"
$redirectURI = "https://login.microsoftonline.com/common/oauth2/nativeclient"

$app =  [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($appId).WithRedirectUri($redirectURI)
$app2 = $app.Build()

$Scopes = New-Object System.Collections.Generic.List[string]
#$Scope = "https://ps.compliance.protection.outlook.com/.default"
$Scope = "https://dataservice.o365filtering.com/.default"
$Scopes.Add($Scope)

$token = $app2.AcquireTokenInteractive($Scopes).WithLoginHint("vasil@michev.info").ExecuteAsync().Result

From here, you can pass the token to the Connect-IPPSSession cmdlet if you want:

Connect-IPPSSession -Organization tenant.onmicrosoft.com -AccessToken $token.AccessToken

More importantly, you can query the underlying Admin API endpoints directly, in particular the InvokeCommand one to “proxy” any cmdlet we want executed, much like we discussed in our previous article. Thus, if we want to replicate what the Get-ComplianceSecurityFilter cmdlet does, we issue the following request:

$authHeader1 = @{
   'Content-Type'='application/json'
   'Authorization'="Bearer $($token.AccessToken)"
   'X-ResponseFormat'= "json" #OR clixml
   'X-AnchorMailbox' = "UPN:$($token.Account.Username)" #optional but recommended
}

$body = @{
    CmdletInput = @{
        CmdletName="Get-ComplianceSecurityFilter"
        Parameters=@{}
    }
} | ConvertTo-Json

$uri = "https://eur02b.ps.compliance.protection.outlook.com/adminapi/beta/923712ba-352a-4eda-bece-09d0684d0cfb/InvokeCommand"
$res = Invoke-WebRequest -Method POST -Uri $uri -Headers $authHeader1 -Body $body
($res.Content | ConvertFrom-Json).Value | ft FilterName,Description,Actions,Users,Filters

FilterName                    Description Actions Users                         Filters                                                                                                                                                              
----------                    ----------- ------- -----                         -------                                                                                                                                                              
FOURTH COFFEE SECURITY FILTER                     {huku@michev.onmicrosoft.com} {Mailbox_Company -eq 'Fourth Coffee', Site_ComplianceAttribute -eq 'Fourth Coffee' -or Site_Path -like 'https://fourthcoffee.sharepoint.com/sites/FourthCoffeeTeam*'}
SALESUSERS                                        {shared@michev.info}          {Mailbox_Department  -eq 'Entertainment'}                                                                                                                            
SALESUSERS2                                       {pesho@michev.info}           {Mailbox_Department  -eq 'Sales' -and Mailbox_PrimarySmtpAddress -ne 'CSO@domain.com'}                                                                               
SHARED MAILBOXES ONLY         HuKu                {huku@michev.onmicrosoft.com} {Mailbox_RecipientTypeDetails -eq 'SharedMailbox'} 

Now, keep in mind that this is what is currently happening when we use the switch. Past the Aug 31st deadline, it is likely that the actual endpoint used to proxy the cmdlets mentioned in MC1131771 will change, so the code above will likely need an adjustment. We shall see.

Another important thing mentioned in the MC1131771 message center post is that “these cmdlets also remain incompatible with Certificate-Based Authentication (CBA).” Translating from Microsoft speak, this means that we will NOT be able to use the client credentials flow. This matches the current behavior for said cmdlets, as mentioned in the official documentation. A somewhat unfortunate limitation, but we cannot blame it on the incoming changes. In fact, you can use the method above to obtain an access token via the client credentials flow, but said token will not not contain the scp and wids claim, resulting in a 401 Unauthorized error with the Admin API endpoint.

Lastly, here are some interesting observations related to the access token obtained for this new resource. For some reason, it does contain the groups claim, listing all the groups the given user is a member of. Compared to the “regular” access token, two scopes are missing: User-OnPremisesSyncBehavior.ReadWrite.All.Sdp and VivaFeatureAccessPolicy.Manage.All. And, we are also missing the secaud claim, with the Graph API scopes:

"secaud": {
    "aud": "00000003-0000-0000-c000-000000000000",
    "scp": "User-OnPremisesSyncBehavior.ReadWrite.All Organization.Read.All User.Read.All"
}

The decoded access token is shown on the screenshot above, with some of the group ids removed for brevity:

MC1131771

And that in a nutshell is what the new -EnableSearchOnlySession switch and the changes mentioned in MC1131771 are all about. Once we hit the Aug 31st deadline, I will circle back to the post and update any relevant details as needed.

UPDATE: We now have a GA (officially supported) version of the Exchange Online PowerShell module with support for this: https://www.powershellgallery.com/packages/ExchangeOnlineManagement/3.9.0

10 thoughts on “Upcoming changes to the Connect-IPPSSession cmdlet (the EnableSearchOnlySession switch)

  1. Daniel Dimitrov's avatar
    Daniel Dimitrov says:

    Hi Vasil,
    Thank you for all the interesting and helpful articles you posted through the years!

    This recent change affects us too.
    We have a runbook which uses the following code to connect:
    ———————-
    # Connect to Azure
    Connect-AzAccount -Identity -Subscription ‘subscriptionID’

    # Obtain an Azure Access Token for EXO
    $tToken = Get-AzAccessToken -ResourceUrl ‘00000002-0000-0ff1-ce00-000000000000’

    # Connect to Security & Compliance PowerShell
    Connect-IPPSSession -AccessToken ($tToken.Token | ConvertFrom-SecureString -AsPlainText) -Organization ‘TenantName’
    ———————-

    The “connect” command fails if we add the new parameter “EnableSearchOnlySession”.

    What changes should we implement to be able to connect with the new parameter and still use the managed identity of our automation account.

    Regards,
    Daniel

    Reply
    1. Vasil Michev's avatar
      Vasil Michev says:

      You need to use a different resource/audience value as discussed above. Also, you cannot use any non-interactive flow (i.e. client credentials or managed identity), as this is not currently supported for this endpoint and the set of cmdlets it exposes.

      Reply
  2. Ildjarn is Dead's avatar
    Ildjarn is Dead says:

    I tried graph voor eDiscovery cases, but never got it working: For one customer it worked fine, for another I always got a 500 Internal Server error. My guess is that there’s some licensing requirement, because Graph uses advanced eDiscovery cases.

    Reply
    1. Vasil Michev's avatar
      Vasil Michev says:

      That is correct, currently only Premium eDiscovery is covered. They just added a roadmap item to cover standard eDiscovery, so it’s coming.

      Reply
  3. Ildjarn Is Dead's avatar
    Ildjarn Is Dead says:

    We get 3 weeks to rewrite something using a preview module….

    Reply
    1. Vasil Michev's avatar
      Vasil Michev says:

      Won’t be the first time Microsoft postpones a deadline 🙂
      But in all fairness, you only need to make changes if you are using any of the listed cmdlets…

      Reply
      1. Ildjarn is Dead's avatar
        Ildjarn is Dead says:

        I am using New-ComplianceSearchAction, so I need to change code. Unfortunately, I am not allowed to run preview versions, so I’m stuck waiting for the official release of 3.9.0.

        But as with last year’s deprecation of webhooks in Teams:
        – Very short period between announcement and proposed deadline
        – It’s holiday season, some people are out of office for a month.
        – In this case, the module required isn’t even released yet, making the transition period even shorter.

        At least the documentation of this change is better than the webhook deprecation documentation…

        Is common sense really dead within Microsoft?

        Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading