public/maester/entra/Test-MtPimAlertsExists.ps1
|
<# .Synopsis Checks if PIM alerts exists .Description GET /beta/privilegedAccess/aadRoles/resources/$tenantId/alerts .Example Test-MtPimAlertsExists -FilteredAccessLevel "ControlPlane" -AlertId "RolesAssignedOutsidePimAlert" .LINK https://maester.dev/docs/commands/Test-MtPimAlertsExists #> function Test-MtPimAlertsExists { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Exists is not a plurality')] [OutputType([object])] [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [ValidateSet('RedundantAssignmentAlert', 'RolesAssignedOutsidePimAlert', 'SequentialActivationRenewalsAlert', 'TooManyGlobalAdminsAssignedToTenantAlert', 'StaleSignInAlert')] # ID for the alert to test. [string[]]$AlertId, [Parameter(ValueFromPipelineByPropertyName = $true, Position = 1)] [ValidateSet('ControlPlane', 'ManagementPlane')] # Filter based on Enterprise Access Model Tiering. Can be 'ControlPlane' and/or 'ManagementPlane'. [string[]]$FilteredAccessLevel = $null, [Parameter(ValueFromPipelineByPropertyName = $true, Position = 2)] # Specify break glass accounts to exclude. Defaults to automatic detection based on conditional access policy exclusions. [object[]]$FilteredBreakGlass = (Get-MtUser -UserType EmergencyAccess) ) begin { $mgContext = Get-MgContext $tenantId = $mgContext.TenantId } process { try { # Get PIM Alerts and store as object to be used in the test Write-Verbose 'Getting PIM Alerts' $Alert = Invoke-MtGraphRequest -ApiVersion 'beta' -RelativeUri "privilegedAccess/aadRoles/resources/$($tenantId)/alerts" | Where-Object { $_.id -eq $AlertId } if ($Alert.Where({ $_.isActive -eq 'True' }).additionalData) { $AffectedRoleAssignments = $Alert.Where({ $_.isActive -eq 'True' }).additionalData | ForEach-Object { $CurrentItem = $_.item $result = New-Object psobject foreach ($entry in $CurrentItem.GetEnumerator()) { $result | Add-Member -MemberType NoteProperty -Name $entry.key -Value $entry.value -Force } $result } } # Filtering based on (EntraOps) Enterprise Access Model Tiering if ($null -ne $FilteredAccessLevel) { Write-Verbose 'Filtering based on Enterprise Access Model Tiering' $EamClassification = Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/Cloud-Architekt/AzurePrivilegedIAM/main/Classification/Classification_EntraIdDirectoryRoles.json' | ConvertFrom-Json -Depth 10 $FilteredClassification = ($EamClassification | Where-Object { $_.Classification.EAMTierLevelName -eq $FilteredAccessLevel }).RoleId $AffectedRoleAssignments = $AffectedRoleAssignments | Where-Object { $_.RoleTemplateId -in $FilteredClassification } } # Exclude Break Glass from Alerts if ($null -ne $FilteredBreakGlass -and $null -ne $AffectedRoleAssignments) { $AffectedRoleAssignments | Where-Object { $_.AssigneeId -in $($FilteredBreakGlass).Id } | ForEach-Object { Write-Verbose "$($_.AssigneeUserPrincipalName) has been defined as Break Glass and removed from $($Alert.id)" } $AffectedRoleAssignments = $AffectedRoleAssignments | Where-Object { $_.AssigneeId -notin $($FilteredBreakGlass).Id } } # Set number of affected Items to value of filtered items (for example, original alert has two affected items, but all of them are break glass and excluded from the test) $Alert.numberOfAffectedItems = $AffectedRoleAssignments.Count # Create test result and details $convertHtmlLinkToMD = '<a.*?href=["'']([^"'']*)["''][^>]*>([^<]*)<\/a>' # Regular expression to detect HTML links $testDescription = " **Security Impact**`n`n $($Alert.securityImpact -replace $convertHtmlLinkToMD, '[$2]($1)') **Mitigation steps**`n`n $($Alert.mitigationSteps -replace $convertHtmlLinkToMD, '[$2]($1)') **How to prevent**`n`n $($Alert.howToPrevent -replace $convertHtmlLinkToMD, '[$2]($1)') " $AffectedRoleAssignmentSummary = @() $AffectedRoleAssignmentSummary += foreach ($AffectedRoleAssignment in $AffectedRoleAssignments) { if ($null -ne $AffectedRoleAssignment.AssigneeDisplayName -or $null -ne $AffectedRoleAssignment.RoleDisplayName) { " - $($AffectedRoleAssignment.AssigneeDisplayName) with $($AffectedRoleAssignment.RoleDisplayName) by AssigneeId $($AffectedRoleAssignment.AssigneeId)`n" } else { " - $($AffectedRoleAssignment.AssigneeName) ($($AffectedRoleAssignment.AssigneeUserPrincipalName))`n" } } if ($Alert.Count -gt '0' -and $AffectedRoleAssignments.Count -gt 0) { $testResult = "$($Alert.alertDescription)`n`n $($AffectedRoleAssignmentSummary) Get more details from the PIM alert [$($Alert.alertName)](https://portal.azure.com/#view/Microsoft_Azure_PIMCommon/AlertDetail/providerId/aadroles/alertId/$($AlertId)/resourceId/$($tenantId)) in the Azure Portal. " } else { $testResult = 'All privileged role assignments are managed by PIM. Well done!' } Add-MtTestResultDetail -Description $testDescription -Result $testResult return $Alert } catch { Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ return $null } } # end process block } # end function |