SHELL/5.1.2.1.ps1
|
$CheckId = "5.1.2.1" $Title = "Ensure 'Per-user MFA' is disabled" $Level = "L1" $BenchmarkType = "Automated" $AuditCommands = @( "Invoke-MgGraphRequest -Method GET -Uri 'https://graph.microsoft.com/beta/users?\$filter=perUserMfaState eq ''enforced'' or perUserMfaState eq ''enabled'''", "Invoke-MgGraphRequest -Method GET -Uri 'https://graph.microsoft.com/beta/users/{id}/authentication/requirements'" ) try { $PerUserMfaUsers = @() $BulkWorked = $false $SampleMode = $false try { $PerUserUri = "https://graph.microsoft.com/beta/users?`$count=true&`$filter=perUserMfaState eq 'enforced' or perUserMfaState eq 'enabled'&`$select=id,displayName,userPrincipalName" $PerUserResponse = Invoke-MgGraphRequest -Uri $PerUserUri -Method GET -Headers @{ "ConsistencyLevel" = "eventual" } -ErrorAction Stop $PerUserMfaUsers = @($PerUserResponse.value) while ($PerUserResponse.'@odata.nextLink') { $PerUserResponse = Invoke-MgGraphRequest -Uri $PerUserResponse.'@odata.nextLink' -Method GET -Headers @{ "ConsistencyLevel" = "eventual" } -ErrorAction Stop $PerUserMfaUsers += @($PerUserResponse.value) } $BulkWorked = $true } catch { try { $SampleMode = $true $UsersUri = "https://graph.microsoft.com/v1.0/users?`$select=id,userPrincipalName&`$top=50" $UsersResponse = Invoke-MgGraphRequest -Uri $UsersUri -Method GET -ErrorAction Stop $SampleUsers = @($UsersResponse.value) foreach ($User in $SampleUsers) { try { $Req = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/beta/users/$($User.id)/authentication/requirements" -ErrorAction Stop if ([string]$Req.perUserMfaState -in @("enforced", "enabled")) { $PerUserMfaUsers += [pscustomobject]@{ id = [string]$User.id userPrincipalName = [string]$User.userPrincipalName perUserMfaState = [string]$Req.perUserMfaState } } } catch { continue } } $BulkWorked = $true } catch { $BulkWorked = $false } } if ($BulkWorked) { $Pass = (@($PerUserMfaUsers).Count -eq 0) $Status = if ($Pass) { "PASS" } else { "FAIL" } $Sample = @($PerUserMfaUsers | Select-Object -First 5 | ForEach-Object { $_.userPrincipalName }) -join ", " [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = $Status Pass = $Pass Evidence = [pscustomobject]@{ AuditCommands = $AuditCommands DetectionMode = if ($SampleMode) { "SampledPerUserRequirements" } else { "BulkFilter" } UserCountWithPerUserMfa = @($PerUserMfaUsers).Count UsersWithPerUserMfaPreview = @($PerUserMfaUsers | Select-Object -First 50) SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" } Error = if ($Pass) { $null } else { "$(@($PerUserMfaUsers).Count) users have per-user MFA enabled (example: $Sample)." } Timestamp = Get-Date } return } [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = "MANUAL_REVIEW" Pass = $null Evidence = [pscustomobject]@{ AuditCommands = $AuditCommands SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" } Error = "Per-user MFA state could not be checked via Graph API. Verify manually in Entra admin center." Timestamp = Get-Date } } catch { [pscustomobject]@{ CheckId = $CheckId Title = $Title Level = $Level BenchmarkType = $BenchmarkType Status = "ERROR" Pass = $null Evidence = [pscustomobject]@{ AuditCommands = $AuditCommands SourceDocument = "CIS_Microsoft_365_Foundations_Benchmark_v6.0.1" } Error = $_.Exception.Message Timestamp = Get-Date } } |