Some time ago I spoke about monitoring mailbox rules with PowerShell and how we’ve always used the “Get-inboxrule” cmdlet as delegate administrator to retrieve the rules and alert on them. Its been brought to my attention that recently API-created rules are no longer showing up using get-inboxrule.
so to resolve this, I’ve decided to rewrite the monitoring script for this by using the audit log instead. This script grabs the last day of the unified audit log and alerts if a new rule has been found. It will also alert you if the unified audit log is not enabled.
All Tenants Script
$ApplicationId = 'YourApplicationID' $ApplicationSecret = 'YourApplicationSecret' | Convertto-SecureString -AsPlainText -Force $TenantID = 'YourTenantID' $ExchangeRefreshToken = 'YourExchangeToken' $RefreshToken = 'YourRefreshToken' $UPN = "UPN-Used-To-Generate-Token" ############################## $credential = New-Object System.Management.Automation.PSCredential($ApplicationId, $ApplicationSecret) $aadGraphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.windows.net/.default' -ServicePrincipal -Tenant $tenantID $graphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.microsoft.com/.default' -ServicePrincipal -Tenant $tenantID Connect-MsolService -AdGraphAccessToken $aadGraphToken.AccessToken -MsGraphAccessToken $graphToken.AccessToken $customers = Get-MsolPartnerContract -All $logs = foreach ($customer in $customers) { $startDate = (Get-Date).AddDays(-1) $endDate = (Get-Date) $token = New-PartnerAccessToken -ApplicationId 'a0c73c16-a7e3-4564-9a95-2bdf47383716'-RefreshToken $ExchangeRefreshToken -Scopes 'https://outlook.office365.com/.default' -Tenant $customer.TenantId $tokenValue = ConvertTo-SecureString "Bearer $($token.AccessToken)" -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($upn, $tokenValue) $customerId = $customer.DefaultDomainName $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell-liveid?DelegatedOrg=$($customerId)&BasicAuthToOAuthConversion=true" -Credential $credential -Authentication Basic -AllowRedirection $s = import-PSSession $session -AllowClobber -CommandName "Search-unifiedAuditLog", "Get-AdminAuditLogConfig" if((Get-AdminAuditLogConfig).UnifiedAuditLogIngestionEnabled -eq $false){ write-host "AuditLog is disabled for client $($customer.name)" } $LogsTenant = @() Write-Host "Retrieving logs for $($customer.name)" -ForegroundColor Blue do { $logsTenant += Search-unifiedAuditLog -SessionCommand ReturnLargeSet -SessionId $customer.name -ResultSize 5000 -StartDate $startDate -EndDate $endDate -Operations "New-InboxRule", "Set-InboxRule", "UpdateInboxRules" Write-Host "Retrieved $($logsTenant.count) logs" -ForegroundColor Yellow }while ($LogsTenant.count % 5000 -eq 0 -and $LogsTenant.count -ne 0) Write-Host "Finished Retrieving logs" -ForegroundColor Green $LogsTenant } foreach($log in $logs){ $AuditData = $log.AuditData | ConvertFrom-Json Write-Host "A new or changed rule has been found for user $($log.UserIds). The rule has the following info: $($Auditdata.Parameters | out-string)`n" } if(!$Logs){ write-host "Healthy." }
Single tenant script
$ApplicationId = 'YourApplicationID' $ApplicationSecret = 'YourApplicationSecret' | Convertto-SecureString -AsPlainText -Force $TenantID = 'YourTenantID' $ExchangeRefreshToken = 'YourExchangeToken' $RefreshToken = 'YourRefreshToken' $UPN = "UPN-Used-To-Generate-Token" $ClientTenantName = "bla.onmicrosoft.com" ############################## $credential = New-Object System.Management.Automation.PSCredential($ApplicationId, $ApplicationSecret) $customers = $ClientTenantName $logs = foreach ($customer in $customers) { $startDate = (Get-Date).AddDays(-1) $endDate = (Get-Date) $token = New-PartnerAccessToken -ApplicationId 'a0c73c16-a7e3-4564-9a95-2bdf47383716'-RefreshToken $ExchangeRefreshToken -Scopes 'https://outlook.office365.com/.default' -Tenant $ClientTenantName $tokenValue = ConvertTo-SecureString "Bearer $($token.AccessToken)" -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($upn, $tokenValue) $customerId = $customer.DefaultDomainName $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell-liveid?DelegatedOrg=$($customerId)&BasicAuthToOAuthConversion=true" -Credential $credential -Authentication Basic -AllowRedirection $s = import-PSSession $session -AllowClobber -CommandName "Search-unifiedAuditLog", "Get-AdminAuditLogConfig" if((Get-AdminAuditLogConfig).UnifiedAuditLogIngestionEnabled -eq $false){ write-host "AuditLog is disabled for client $ClientTenantName)" } $LogsTenant = @() Write-Host "Retrieving logs for $ClientTenantName)" -ForegroundColor Blue do { $logsTenant += Search-unifiedAuditLog -SessionCommand ReturnLargeSet -SessionId $customer.name -ResultSize 5000 -StartDate $startDate -EndDate $endDate -Operations "New-InboxRule", "Set-InboxRule", "UpdateInboxRules" Write-Host "Retrieved $($logsTenant.count) logs" -ForegroundColor Yellow }while ($LogsTenant.count % 5000 -eq 0 -and $LogsTenant.count -ne 0) Write-Host "Finished Retrieving logs" -ForegroundColor Green $LogsTenant } foreach($log in $logs){ $AuditData = $log.AuditData | ConvertFrom-Json Write-Host "A new or changed rule has been found for user $($log.UserIds). The rule has the following info: $($Auditdata.Parameters | out-string)`n" } if(!$Logs){ write-host "Healthy." }
So that’s it! this should get -all- rules that have been created, including the ones by the old EWS API. Happy PowerShelling!
Hello, I would like to utilize your script, but having issues with “New-PartnerAccessToken : AADSTS9002313: Invalid request. Request is malformed or invalid.” Any thoughts on what I’m doing incorrectly?
Thanks,
Hi Aaron,
Did you create the Secure Application Model via this blog? https://www.cyberdrain.com/connect-to-exchange-online-automated-when-mfa-is-enabled-using-the-secureapp-model/
Creating an app on your own isn’t enough, it needs some extra approvals. 🙂
I seem to be running into an issue where the “Search-unifiedAuditLog” command doesn’t import for some clients.
Have you ran into this before?
I don’t think so, Are you sure these clients are allowed to connect to the SCC via PowerShell? This requires a E license.
Nevermind, I’m an idiot. I was accidently trying to connect to my own tenant due to a left over test in my code and that account doesn’t have permission to access the command. 🙄
Also, I saw another blog today that used Graph to get the rules instead of the audit log or the get-inboxrule command.
https://blog.rothe.uk/risky-rules-in-office365/
Would getting these rules by Graph API be a better way to go about this now?
Or is the audit log still the way to go?