Entra / Microsoft 365 · Compliance & audit
Report label changes audit records
Example of how to use Microsoft 365 audit records to track changes made in sensitivity labels and policies.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-ExchangeOnline -SkipLoadingCmdletHelpConnect-IPPSSession
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([int] $LookbackDays = 90)$Modules = Get-Module | Select-Object NameIf ("ExchangeOnlineManagement -notin $Modules") {Write-Host "Connecting to Exchange Online..."Connect-ExchangeOnline -SkipLoadingCmdletHelpConnect-IPPSSession}# Connect to the Graph to resolve service principalsConnect-MgGraph -Scopes Application.Read.All# It seems like only one service principal (75367c9a-9a5b-41be-840f-ee9ee448c1f5, "Microsoft Exchange Online Protection")# is ever found in the audit records found by this search. If this is the case, it would be possible to hard code the# check for the service principal identifier and avoid the overhead of running the Get-MgServicePrincipal cmdlet# Get sensitivity labels and build a hash table to lookup labels$Labels = Get-Label$LabelHash = @{}ForEach ($L in $Labels) {$LabelHash.Add($L.ImmutableId, $L.Name)}Write-Host "Looking for audit records..."# Find evidence that someone has been messing with sensitivity label and retention label policies[array]$Operations = "Set-RetentionCompliancePolicy", "Set-Label", "Set-LabelPolicy", `"Set-RetentionComplianceRule", "Update label."[array]$Records = Search-UnifiedAuditLog -StartDate (Get-date).AddDays(-$LookbackDays) -EndDate (Get-Date).AddDays(1) -ResultSize 1000 -Formatted -Operations $Operations -SessionCommand ReturnLargeSetIf (!($Records)) {Write-Host "No audit records found"; break} Else {$Records = $Records | Sort-Object Identity -Unique | Sort-Object {$_.CreationDate -as [datetime]} -DescendingWrite-Host ("{0} audit records found" -f $Records.Count)}$Report = [System.Collections.Generic.List[Object]]::new()Write-Host "Processing audit records..."ForEach ($Rec in $Records) {$Data = $null; $LabelName = $null$AuditData = $Rec.AuditData | ConvertFrom-JsonSwitch ($Rec.Operations) {"Set-RetentionCompliancePolicy" { # Update retention policy$Data = $AuditData.Parameters}"Set-RetentionComplianceRule" { # Update rule for retention policy$Data = $AuditData.Parameters}"Set-Label" { # Update sensitivity label$Data = $AuditData.Parameters$LabelName = $LabelHash[$AuditData.ObjectId]If ($null -eq $LabelName) {$LabelName = "Sensitivity label not found in tenant"}}"Set-LabelPolicy" { # Update sensitivity label policy$Data = $AuditData.Parameters}"Update label." { # Update retention label$LabelName = $AuditData.target.id[3]$Data = $AuditData.ObjectId}}If ($Rec.UserIds -like "*ServicePrincipal*") {$SPStart = $Rec.UserIds.IndexOf("_")+1$SPId = $Rec.UserIds.SubString(($SPStart), $Rec.UserIds.Length - ($SPStart))$User = (Get-MgServicePrincipal -ServicePrincipalId $SPId).displayName} Else {$User = $Rec.UserIds}$ReportLine = [PSCustomObject] @{User = $UserOperation = $Rec.OperationsTimestamp = (Get-Date $Rec.CreationDate -format 'dd-MMM-yyyy HH:mm:ss')Data = $DataLabel = $LabelName}$Report.Add($ReportLine)}$Report | Out-Gridview -Title 'Audit Records for Label Changes'
Parameters
ParameterDefaultNotes
-LookbackDays90Number of days back to search the unified audit log for label change events.Attribution
Author
Office365itpros