Overview
With this integration, Ocean can view and release Microsoft quarantined emails directly, streamlining the process and reducing the manual effort required to handle user release requests.
Prerequisites
-
Consent permissions have been granted, including the “Manage Exchange As Application” permission.
-
Ensure you have Exchange Online PowerShell installed and can connect (See Microsoft’s guide for setup details)
-
Have Ocean’s App ID:
xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx
Ocean provides this App ID. It is not something you generate yourself — reach out to your Ocean representative to obtain the App ID for your tenant before starting this setup.
NoteGranting Exchange.ManageAsApp unlocks the app-only authenticiation pathway to Exchange Online, but you still need to assign roles for what the app can do.
Process
Set up
Install-Module ExchangeOnlineManagement -Force -Scope CurrentUser
Install-Module Microsoft.Graph -Scope CurrentUser -Repository PSGallery
Import-Module ExchangeOnlineManagement
Import-Module Microsoft.Graph
Connect-ExchangeOnline
Create an Exchange service principal
$sp = Get-MgServicePrincipal -Filter "appId eq 'xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx'"
# Create Exchange's pointer object and capture integrate
New-ServicePrincipal -AppId $sp.AppId -ObjectId $sp.ObjectId -DisplayName "Ocean Quarantine App"
$oceanExchangeSP = Get-ServicePrincipal -Identity "Ocean Security"
Create a custom role that includes only quarantine cmdlets
- We create a custom role by duplicating the built-in Transport Hygeine role and removing all unnecessary cmdlets - keeping only those required to view and export quarantine data.
- This ensure the Ocean app has the minimum access necessary and cannot perform any unrelated actions, such as modifying mailboxes, chaning rules, or impersonating users.
$role = "Ocean-Quarantine-Automation-Role"
New-ManagementRole -Parent "Transport Hygiene" -Name $role
# Keep only the quarantine (read) cmdlets
$keep = @("Get-QuarantineMessage", "Preview-QuarantineMessage", "Export-QuarantineMessage", "Get-QuarantineMessageHeader")
Get-ManagementRoleEntry "$role\*" | Where-Object { $_.Name -notin $keep } | ForEach-Object { Remove-ManagementRoleEntry -Identity "$role\$($_.Name)" -Confirm:$false }
Creating a scope
You can scope the role to a subset of mailboxes or a distribution group to enforce least-privilege boundaries.# If scoping by a user list
$mailboxes = @("bob@acme.org","alice@acme.org")
$filter = ($mailboxes | ForEach-Object { "PrimarySmtpAddress -eq '$_'" }) -join " -or "
# If scoping with a distribution list
$group = Get-DistributionGroup -Identity "<GroupName>"
$filter = "MemberOfGroup -eq '$($group.DistinguishedName)'"
# Create the scope using one of the filters
New-ManagementScope -Name "Ocean-Quarantine-Scope" -RecipientRestrictionFilter $filter
Bind the role to the app
Using New-ManagementRoleAssignment, we attach the new custom role to the app’s service principal.# Assign the app to the role using our scope
New-ManagementRoleAssignment -Name "Ocean-Quarantine-App-Assignment" -Role $role -App $oceanExchangeSP.Id -CustomResourceScope "Ocean-Quarantine-Scope"
Verifying the app has permissions
You can test the app has permissions on one of your users that’s inside the scope.Test-ServicePrincipalAuthorization -Identity $oceanExchangeSp.Id -Resource bob@acme.org