public/maester/entra/Test-MtCaEmergencyAccessExists.ps1
|
<# .Synopsis Checks if the tenant has at least one emergency/break glass account or account group excluded from all conditional access policies .Description It is recommended to have at least one emergency/break glass account or account group excluded from all conditional access policies. This allows for emergency access to the tenant in case of a misconfiguration or other issues. Learn more: https://learn.microsoft.com/entra/identity/role-based-access-control/security-emergency-access .Example Test-MtCaEmergencyAccessExists .LINK https://maester.dev/docs/commands/Test-MtCaEmergencyAccessExists #> function Test-MtCaEmergencyAccessExists { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Exists is not a plural.')] [CmdletBinding()] [OutputType([bool])] param () if ( ( Get-MtLicenseInformation EntraID ) -eq 'Free' ) { Add-MtTestResultDetail -SkippedBecause NotLicensedEntraIDP1 return $null } try { # Only check policies that are not related to authentication context (the state of policy does not have to be enabled) $policies = Get-MtConditionalAccessPolicy | Where-Object { -not $_.conditions.applications.includeAuthenticationContextClassReferences } # Remove policies that are scoped to service principals $policies = $policies | Where-Object { -not $_.conditions.clientApplications.includeServicePrincipals } $result = $false $PolicyCount = $policies | Measure-Object | Select-Object -ExpandProperty Count $ExcludedUserObjectGUID = $policies.conditions.users.excludeUsers | Group-Object -NoElement | Sort-Object -Property Count -Descending | Select-Object -First 1 -ExpandProperty Name $ExcludedUsers = $policies.conditions.users.excludeUsers | Group-Object -NoElement | Sort-Object -Property Count -Descending | Select-Object -First 1 | Select-Object -ExpandProperty Count $ExcludedGroupObjectGUID = $policies.conditions.users.excludeGroups | Group-Object -NoElement | Sort-Object -Property Count -Descending | Select-Object -First 1 -ExpandProperty Name $ExcludedGroups = $policies.conditions.users.excludeGroups | Group-Object -NoElement | Sort-Object -Property Count -Descending | Select-Object -First 1 | Select-Object -ExpandProperty Count # If the number of enabled policies is not the same as the number of excluded users or groups, there is no emergency access if ($PolicyCount -eq $ExcludedUsers -or $PolicyCount -eq $ExcludedGroups) { $result = $true } else { # If the number of excluded users is higher than the number of excluded groups, check the user object GUID $CheckId = $ExcludedGroupObjectGUID $EmergencyAccessUUIDType = 'group' if ($ExcludedUsers -gt $ExcludedGroups) { $EmergencyAccessUUIDType = 'user' $CheckId = $ExcludedUserObjectGUID } # Get displayName of the emergency access account or group if ($CheckId) { try { if ($EmergencyAccessUUIDType -eq 'user') { $DisplayName = Invoke-MtGraphRequest -RelativeUri "users/$CheckId" -Select displayName | Select-Object -ExpandProperty displayName } else { $DisplayName = Invoke-MtGraphRequest -RelativeUri "groups/$CheckId" -Select displayName | Select-Object -ExpandProperty displayName } } catch { Throw "Unable to resolve display name ${EmergencyAccessUUIDType} with GUID: ${CheckId}`n`nThis could indicate that the automatically detected emergency access ${EmergencyAccessUUIDType} does not exist." } Write-Verbose "Emergency access account or group: $CheckId" $testResult = "Automatically detected emergency access $($EmergencyAccessUUIDType): $DisplayName ($CheckId)`n`n" } $policiesWithoutEmergency = $policies | Where-Object { $CheckId -notin $_.conditions.users.excludeUsers -and $CheckId -notin $_.conditions.users.excludeGroups } $policiesWithoutEmergency | Select-Object -ExpandProperty displayName | Sort-Object | ForEach-Object { Write-Verbose "Conditional Access policy $_ does not exclude emergency access $EmergencyAccessUUIDType" } } $testResult += "These conditional access policies don't have the emergency access $EmergencyAccessUUIDType excluded:`n`n%TestResult%" Add-MtTestResultDetail -GraphObjects $policiesWithoutEmergency -GraphObjectType ConditionalAccess -Result $testResult return $result } catch { Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ return $null } } |