Private/EntraMonitor/Detections/Test-EntraCAPolicyChange.ps1
|
# PSGuerrilla - Jim Tyler, Microsoft MVP - CC BY 4.0 # https://github.com/jimrtyler/PSGuerrilla | https://creativecommons.org/licenses/by/4.0/ # AI/LLM use: see AI-USAGE.md for required attribution function Test-EntraCAPolicyChange { [CmdletBinding()] param( [hashtable[]]$AuditEvents = @() ) $results = [System.Collections.Generic.List[PSCustomObject]]::new() # Conditional Access policy activities $caActivities = @( 'Add conditional access policy' 'Update conditional access policy' 'Delete conditional access policy' 'Add named location' 'Update named location' 'Delete named location' 'Add authentication context' 'Update authentication context' 'Delete authentication context' ) foreach ($event in $AuditEvents) { $activity = $event.ActivityDisplayName $isCA = $false foreach ($ca in $caActivities) { if ($activity -match [regex]::Escape($ca)) { $isCA = $true break } } # Also catch by category if (-not $isCA -and $event.Category -eq 'Policy' -and $activity -match 'conditional|named location') { $isCA = $true } if (-not $isCA) { continue } # Extract policy details from target resources $policyName = '' $policyState = '' foreach ($resource in $event.TargetResources) { if ($resource.DisplayName) { $policyName = $resource.DisplayName } foreach ($prop in $resource.ModifiedProperties) { if ($prop.DisplayName -eq 'State' -or $prop.DisplayName -eq 'IsEnabled') { $policyState = $prop.NewValue -replace '"', '' } } } $initiator = $event.InitiatedBy.UserPrincipalName if (-not $initiator) { $initiator = $event.InitiatedBy.AppDisplayName } $isDisabling = $activity -match 'Delete' -or $policyState -match 'disabled|false' $results.Add([PSCustomObject]@{ Timestamp = $event.Timestamp Activity = $activity Result = $event.Result InitiatedBy = $initiator PolicyName = $policyName PolicyState = $policyState IsDisabling = $isDisabling Category = $event.Category CorrelationId = $event.CorrelationId }) } return @($results) } |