Private/Get-NSPConditionalAccessDefinitionSummary.ps1

function Get-NSPConditionalAccessDefinitionSummary {
    <#
    .SYNOPSIS
        A policy definition in plain words, for the dashboard: who, which apps, where, on which devices, and what it requires.
    .DESCRIPTION
        Offline. Returns ordered label/text pairs. With -TenantProfile, group slots also name the
        tenant's bound groups. Nothing is resolved against Graph.
    #>

    [CmdletBinding()]
    [OutputType([System.Collections.Specialized.OrderedDictionary])]
    param(
        [Parameter(Mandatory)]$Definition,
        $TenantProfile
    )

    function Get-Value { param($Object, [string]$Key) Get-NSPConditionalAccessMapValue $Object $Key }
    $boundProfile = $TenantProfile
    $pattern = (Get-NSPConditionalAccessDefinitionSchema).ReferencePattern

    function Get-Phrase {
        param([string]$Value)
        switch -Regex ($Value) {
            '^All$' { return 'everyone' }
            '^None$' { return 'no one' }
            '^GuestsOrExternalUsers$' { return 'guests and external users' }
            '^AllTrusted$' { return 'trusted locations (the office)' }
            '^Office365$' { return 'Office 365' }
            '^MicrosoftAdminPortals$' { return 'Microsoft admin portals' }
            '^urn:user:registersecurityinfo$' { return 'registering security info (setting up MFA)' }
            '^urn:user:registerdevice$' { return 'registering or joining a device' }
        }
        if ($Value -notmatch $pattern) { return $Value }
        $kind = $Matches['kind']
        $name = $Matches['name']
        switch ($kind) {
            'BreakGlass' { 'breakglass accounts' }
            'ServiceAccounts' { 'service accounts' }
            'Group' {
                $bound = Get-Value (Get-Value (Get-Value $boundProfile 'Groups') $name) 'Labels'
                $label = if ($bound) { " ($(@($bound) -join ', '))" } else { '' }
                "group $name$label"
            }
            'TravelGroups' { if ($name -eq 'Enforced') { 'travel groups whose travel policy is On' } else { 'every active travel group' } }
            'TravelGroup' {
                $entry = Get-Value (Get-Value (Get-Value $boundProfile 'Travel') 'Entries') $name
                $label = @(Get-Value $entry 'Labels') + @(Get-Value $entry 'DefaultName') | Where-Object { $_ } | Select-Object -First 1
                if ($label) { "travel group $label" } else { "travel group $name" }
            }
            'Role' { "role $name" }
            'App' { $name }
            'Country' {
                if ($name -eq 'Home') { "the home country ($(Get-Value $boundProfile 'HomeCountry'))" }
                else {
                    $country = try { ([System.Globalization.RegionInfo]::new($name)).EnglishName } catch { $null }
                    if ($country) { "$name ($country)" } else { $name }
                }
            }
            'Location' { "location $name" }
            'Strength' { switch ($name) { 'TapOnly' { 'a Temporary Access Pass (one-time or multi-use)' } 'PhishingResistant' { 'phishing-resistant MFA (security key, Windows Hello, passkey)' } 'PasswordlessMfa' { 'passwordless MFA' } 'Mfa' { 'MFA' } default { "authentication strength $name" } } }
            default { $Value }
        }
    }
    function Join-Phrase {
        param([object[]]$Values, [int]$Max = 4)
        $phrases = @($Values | Where-Object { $_ } | ForEach-Object { Get-Phrase ([string]$_) })
        if ($phrases.Count -gt $Max) { return (($phrases[0..($Max - 1)]) -join ', ') + " and $($phrases.Count - $Max) more" }
        $phrases -join ', '
    }

    $out = [ordered]@{}
    $users = Get-Value $Definition 'Users'
    $roles = @(Get-Value $users 'IncludeRoles' | Where-Object { $_ })
    $who = @(@(Get-Value $users 'IncludeUsers') + @(Get-Value $users 'IncludeGroups') | Where-Object { $_ })
    $out['Who'] = Join-Phrase $who
    if ($roles.Count) {
        $names = @($roles | ForEach-Object { if ($_ -match $pattern) { $Matches['name'] } else { $_ } })
        $roleText = if ($names.Count -gt 3) { "$($names.Count) administrator roles ($(@($names | Where-Object { $_ -in 'GlobalAdministrator', 'SecurityAdministrator', 'UserAdministrator' }) -join ', '), ...)" } else { "role $($names -join ', role ')" }
        $out['Who'] = (@($out['Who'], $roleText) | Where-Object { $_ }) -join ', '
    }
    $except = @(@(Get-Value $users 'ExcludeUsers') + @(Get-Value $users 'ExcludeGroups') + @(Get-Value $users 'ExcludeRoles') | Where-Object { $_ })
    if ($except.Count) { $out['Except'] = Join-Phrase $except 6 }
    # Additions in the tenant profile (Add-NSPConditionalAccessPolicyTarget), by name.
    $added = Get-Value (Get-Value $TenantProfile 'PolicyTargets') ([string](Get-Value $Definition 'Id'))
    $alsoIn = @(foreach ($field in 'IncludeUsers', 'IncludeGroups') { @(Get-Value $added $field) | Where-Object { $_ } | ForEach-Object { Get-Value $_ 'Label' } })
    $alsoOut = @(foreach ($field in 'ExcludeUsers', 'ExcludeGroups') { @(Get-Value $added $field) | Where-Object { $_ } | ForEach-Object { Get-Value $_ 'Label' } })
    if ($alsoIn.Count) { $out['Also for'] = $alsoIn -join ', ' }
    if ($alsoOut.Count) { $out['Also except'] = $alsoOut -join ', ' }

    $apps = Get-Value $Definition 'Applications'
    $actions = @(Get-Value $apps 'UserActions' | Where-Object { $_ })
    if ($actions.Count) { $out['When'] = Join-Phrase $actions }
    else {
        $text = Join-Phrase @(Get-Value $apps 'Include')
        if ($text -eq 'everyone') { $text = 'every cloud app' }
        $notApps = @(Get-Value $apps 'Exclude' | Where-Object { $_ })
        if ($notApps.Count) { $text += " except $(Join-Phrase $notApps)" }
        $out['Apps'] = $text
    }

    $locations = Get-Value $Definition 'Locations'
    if ($locations) {
        $text = Join-Phrase @(Get-Value $locations 'Include')
        if ($text -eq 'everyone') { $text = 'anywhere' }
        $notHere = @(Get-Value $locations 'Exclude' | Where-Object { $_ })
        if ($notHere.Count) { $text += " except $(Join-Phrase $notHere)" }
        $out['Where'] = $text
    }
    $platforms = Get-Value $Definition 'Platforms'
    if ($platforms) { $out['Devices'] = (@(Get-Value $platforms 'Include') -join ', ') }

    $grant = Get-Value $Definition 'Grant'
    $controls = @(Get-Value $grant 'BuiltInControls' | Where-Object { $_ })
    $strength = Get-Value $grant 'AuthenticationStrength'
    $names = @{ block = 'BLOCKED'; mfa = 'MFA'; compliantDevice = 'a compliant device'; domainJoinedDevice = 'a hybrid-joined device'; approvedApplication = 'an approved app'; compliantApplication = 'an app-protection-policy app'; passwordChange = 'a password change' }
    $required = @($controls | ForEach-Object { if ($names.ContainsKey($_)) { $names[$_] } else { $_ } })
    if ($strength) { $required += Get-Phrase $strength }
    if ($controls -contains 'block') { $out['Result'] = 'Sign-in is BLOCKED' }
    elseif ($required.Count) {
        $joiner = if ((Get-Value $grant 'Operator') -eq 'AND') { ' and ' } else { ' or ' }
        $out['Requires'] = $required -join $joiner
    }
    $session = Get-Value $Definition 'Session'
    $frequency = Get-Value $session 'SignInFrequency'
    if ($frequency) { $out['Session'] = "sign in again every $(Get-Value $frequency 'Value') $(Get-Value $frequency 'Type')" }
    $option = Get-Value $Definition 'Option'
    if ($option) { $out['Used when'] = "the tenant option $(($option -replace '=', ' is ') -replace ',', ' or ')" }
    $out
}