SHELL/1.1.2.ps1
|
$CheckId = "1.1.2" $Title = "Ensure two emergency access accounts have been defined" $Level = "L1" $BenchmarkType = "Manual" try { $GlobalAdminRole = Get-MgDirectoryRole -Filter "RoleTemplateId eq '62e90394-69f5-4237-9190-012177145e10'" -ErrorAction Stop | Select-Object -First 1 if (-not $GlobalAdminRole) { throw "Global Administrator directory role not found." } $GlobalAdminMembers = @(Get-MgDirectoryRoleMember -DirectoryRoleId $GlobalAdminRole.Id -All -ErrorAction Stop) $CAPolicies = @(Get-MgIdentityConditionalAccessPolicy -All -ErrorAction Stop) $EnabledPolicies = @($CAPolicies | Where-Object { $_.State -eq "enabled" }) $CAExcludedUsers = @{} foreach ($Policy in $EnabledPolicies) { $ExcludedUsers = @($Policy.Conditions.Users.ExcludeUsers) foreach ($UserId in $ExcludedUsers) { if (-not [string]::IsNullOrWhiteSpace([string]$UserId)) { if (-not $CAExcludedUsers.ContainsKey([string]$UserId)) { $CAExcludedUsers[[string]$UserId] = 0 } $CAExcludedUsers[[string]$UserId]++ } } } $EnabledPolicyCount = @($EnabledPolicies).Count $EmergencyAccounts = @() $EvaluatedUsers = @() foreach ($Member in $GlobalAdminMembers) { $ObjectType = [string]$Member.AdditionalProperties.'@odata.type' if ($ObjectType -and $ObjectType -ne "#microsoft.graph.user") { continue } $User = Get-MgUser -UserId $Member.Id -Property Id,UserPrincipalName,DisplayName,OnPremisesSyncEnabled,AccountEnabled -ErrorAction Stop if ($User.OnPremisesSyncEnabled -eq $true) { continue } if ($User.AccountEnabled -ne $true) { continue } $ExcludedCount = if ($CAExcludedUsers.ContainsKey([string]$User.Id)) { [int]$CAExcludedUsers[[string]$User.Id] } else { 0 } $ExcludeRatio = if ($EnabledPolicyCount -gt 0) { [math]::Round(($ExcludedCount / $EnabledPolicyCount), 4) } else { 0.0 } $IsEmergency = ($EnabledPolicyCount -gt 0 -and $ExcludeRatio -ge 0.5) $UserEvidence = [pscustomobject]@{ UserPrincipalName = [string]$User.UserPrincipalName DisplayName = [string]$User.DisplayName ExcludedFromEnabledCAPolicies = $ExcludedCount EnabledCAPolicyCount = $EnabledPolicyCount ExcludeRatio = $ExcludeRatio CloudOnly = ($User.OnPremisesSyncEnabled -ne $true) AccountEnabled = [bool]$User.AccountEnabled EmergencyHeuristicMatch = $IsEmergency } $EvaluatedUsers += $UserEvidence if ($IsEmergency) { $EmergencyAccounts += $UserEvidence } } if ($EnabledPolicyCount -eq 0) { [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = "FAIL" Pass = $false Evidence = [pscustomobject]@{ EnabledCAPolicyCount = 0 EvaluatedGlobalAdmins = @($EvaluatedUsers) SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" AuditHeuristic = "Emergency account = cloud-only enabled Global Admin excluded from >= 50% of enabled CA policies." } Error = "No enabled Conditional Access policies were found, so emergency account exclusion cannot be validated." Timestamp = Get-Date } return } $Pass = @($EmergencyAccounts).Count -ge 2 $Status = if ($Pass) { "PASS" } else { "FAIL" } $ErrorMessage = if ($Pass) { $null } elseif (@($EmergencyAccounts).Count -eq 1) { "Only one emergency access account matched the heuristic. At least two are required." } else { "No emergency access accounts matched the heuristic." } [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = $Status Pass = $Pass Evidence = [pscustomobject]@{ EnabledCAPolicyCount = $EnabledPolicyCount EmergencyAccessAccountCount = @($EmergencyAccounts).Count EmergencyAccessAccounts = @($EmergencyAccounts) EvaluatedGlobalAdmins = @($EvaluatedUsers) SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" AuditHeuristic = "Emergency account = cloud-only enabled Global Admin excluded from >= 50% of enabled CA policies." } Error = $ErrorMessage Timestamp = Get-Date } } catch { [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = "ERROR" Pass = $null Evidence = [pscustomobject]@{ SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" } Error = $_.Exception.Message Timestamp = Get-Date } } |