SHELL/5.2.3.6.ps1

$CheckId = "5.2.3.6"
$Title = "Ensure system-preferred multifactor authentication is enabled"

function Get-NestedValue {
    param(
        [Parameter(Mandatory = $true)][object]$InputObject,
        [Parameter(Mandatory = $true)][string[]]$Path
    )

    $Current = $InputObject
    foreach ($Segment in $Path) {
        if ($null -eq $Current) {
            return $null
        }

        if ($Current -is [System.Collections.IDictionary]) {
            if ($Current.Contains($Segment)) {
                $Current = $Current[$Segment]
            }
            else {
                return $null
            }
        }
        else {
            $Prop = $Current.PSObject.Properties[$Segment]
            if ($null -eq $Prop) {
                return $null
            }
            $Current = $Prop.Value
        }
    }
    return $Current
}

$Uri = "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy"

try {
    $Policy = Invoke-MgGraphRequest -Method GET -Uri $Uri
    $SystemCredentialPreferences = Get-NestedValue -InputObject $Policy -Path @("systemCredentialPreferences")
    $State = [string](Get-NestedValue -InputObject $Policy -Path @("systemCredentialPreferences", "state"))
    $IncludeTargets = @(Get-NestedValue -InputObject $Policy -Path @("systemCredentialPreferences", "includeTargets"))

    if ([string]::IsNullOrWhiteSpace($State) -or @($IncludeTargets).Count -eq 0) {
        [pscustomobject]@{
            CheckId   = $CheckId
            Title     = $Title
            Status    = "MANUAL_REVIEW"
            Pass      = $null
            Evidence  = [pscustomobject]@{
                Uri                         = $Uri
                systemCredentialPreferences = $SystemCredentialPreferences
                ReviewAction                = "Verify state is enabled and includeTargets contains all_users."
            }
            Error     = "Could not determine systemCredentialPreferences state and includeTargets."
            Timestamp = Get-Date
        }
    }
    else {
        $StateNormalized = $State.Trim().ToLowerInvariant()
        $AllUsersIncluded = $false

        foreach ($Target in $IncludeTargets) {
            $TargetId = $null
            if ($Target -is [System.Collections.IDictionary]) {
                if ($Target.Contains("id")) {
                    $TargetId = [string]$Target["id"]
                }
            }
            elseif ($Target -and $Target.PSObject.Properties["id"]) {
                $TargetId = [string]$Target.id
            }

            if ($TargetId -and $TargetId.Trim().ToLowerInvariant() -eq "all_users") {
                $AllUsersIncluded = $true
                break
            }
        }

        $Pass = ($StateNormalized -eq "enabled") -and $AllUsersIncluded

        [pscustomobject]@{
            CheckId   = $CheckId
            Title     = $Title
            Status    = if ($Pass) { "PASS" } else { "FAIL" }
            Pass      = $Pass
            Evidence  = [pscustomobject]@{
                Uri                         = $Uri
                State                       = $State
                IncludeTargets              = @($IncludeTargets)
                AllUsersIncluded            = $AllUsersIncluded
                RecommendedState            = "state=enabled and includeTargets contains id=all_users"
            }
            Error     = $null
            Timestamp = Get-Date
        }
    }
}
catch {
    $Message = $_.Exception.Message
    $IsPermissionIssue = $Message -match "(?i)forbidden|insufficient|authorization|access denied"

    [pscustomobject]@{
        CheckId   = $CheckId
        Title     = $Title
        Status    = if ($IsPermissionIssue) { "MANUAL_REVIEW" } else { "ERROR" }
        Pass      = $null
        Evidence  = [pscustomobject]@{
            Uri                   = $Uri
            RequiredGraphScope    = "Policy.Read.AuthenticationMethod"
            ReviewAction          = "Verify state is enabled and includeTargets contains all_users."
        }
        Error     = $Message
        Timestamp = Get-Date
    }
}