Private/EntraMonitor/Detections/Test-EntraAdminUnitChange.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-EntraAdminUnitChange { [CmdletBinding()] param( [hashtable[]]$AuditEvents = @() ) $results = [System.Collections.Generic.List[PSCustomObject]]::new() # Administrative unit activities $auActivities = @( 'Add administrative unit' 'Update administrative unit' 'Delete administrative unit' 'Add member to administrative unit' 'Remove member from administrative unit' 'Add scoped-role member to administrative unit' 'Remove scoped-role member from administrative unit' ) foreach ($event in $AuditEvents) { $activity = $event.ActivityDisplayName $isAuChange = $false foreach ($aa in $auActivities) { if ($activity -match [regex]::Escape($aa)) { $isAuChange = $true break } } if (-not $isAuChange) { continue } # Extract admin unit and member details $adminUnitName = '' $memberName = '' $roleName = '' foreach ($resource in $event.TargetResources) { if ($resource.Type -eq 'AdministrativeUnit') { $adminUnitName = $resource.DisplayName } elseif ($resource.Type -eq 'User') { $memberName = $resource.UserPrincipalName if (-not $memberName) { $memberName = $resource.DisplayName } } elseif ($resource.Type -eq 'Role') { $roleName = $resource.DisplayName } # Fallback — first resource with a display name if (-not $adminUnitName -and $resource.DisplayName) { $adminUnitName = $resource.DisplayName } } $initiator = $event.InitiatedBy.UserPrincipalName if (-not $initiator) { $initiator = $event.InitiatedBy.AppDisplayName } $results.Add([PSCustomObject]@{ Timestamp = $event.Timestamp Activity = $activity Result = $event.Result InitiatedBy = $initiator AdminUnitName = $adminUnitName MemberName = $memberName RoleName = $roleName Category = $event.Category }) } return @($results) } |