[{"data":1,"prerenderedAt":3508},["ShallowReactive",2],{"post:\u002F2025\u002F08\u002F06\u002Fpowershell-entra-id-audit-conditional-access-policy-drift\u002F":3},{"post":4,"newer":3453,"older":3465,"related":3477,"series":3506},{"id":5,"title":6,"body":7,"canonical":3435,"categories":3436,"date":3439,"description":3440,"extension":3441,"featured":3442,"hero":3443,"image":3443,"meta":3444,"navigation":627,"path":3445,"readingTime":375,"seo":3446,"series":3443,"seriesOrder":3443,"sites":3447,"source":3443,"stem":3448,"tags":3449,"updated":3443,"url":3451,"__hash__":3452},"blog\u002Fblog\u002F2025\u002F08\u002F06\u002Fpowershell-entra-id-audit-conditional-access-policy-drift.md","PowerShell: Entra ID – Audit Conditional Access Policy Drift",{"type":8,"value":9,"toc":3427},"minimark",[10,19,28,33,72,76,184,188,191,228,231,264,270,334,337,345,349,3257,3261,3375,3379,3423],[11,12,13,14,18],"p",{},"Conditional Access policies drift more than most admins want to admit. Someone adds an emergency exclusion during an incident and forgets to remove it, a break-glass group quietly drops off a policy it should be excluded from, or a \"temporary\" pilot policy never gets reverted. None of this shows up unless you go looking. The audit log records each change, but Entra ID doesn't give you a diff between what a policy looks like today and what it looked like when it was last reviewed. I run this script on a schedule against a baseline snapshot so drift shows up as a report instead of an incident. It reports each changed setting by path (for example ",[15,16,17],"code",{},"conditions.users.excludeGroups",", value added), not a wall of JSON, and it can flag any enabled policy that doesn't exclude your emergency access group.",[11,20,21,22,27],{},"It's the audit half of ",[23,24,26],"a",{"href":25},"\u002F2026\u002F08\u002F05\u002Fintune-conditional-access-policies-that-don-t-lock-out-your-help-desk\u002F","Intune: Conditional Access Policies That Don't Lock Out Your Help Desk",": take the baseline right after those policies are rolled out and reviewed.",[29,30,32],"h2",{"id":31},"requirements","Requirements",[34,35,36,44,59,66,69],"ul",{},[37,38,39,40,43],"li",{},"PowerShell 7 or later (the script uses ",[15,41,42],{},"ConvertFrom-Json -AsHashtable",").",[37,45,46,47,50,51,54,55,58],{},"The ",[15,48,49],{},"Microsoft.Graph.Authentication"," module from the Microsoft Graph PowerShell SDK (",[15,52,53],{},"Install-Module Microsoft.Graph.Authentication -Scope CurrentUser","). The script calls the Graph REST endpoint through ",[15,56,57],{},"Invoke-MgGraphRequest",", so no other SDK module is needed.",[37,60,61,62,65],{},"Microsoft Graph permission ",[15,63,64],{},"Policy.Read.All",", the least-privileged permission for listing Conditional Access policies (delegated or application).",[37,67,68],{},"For delegated use, the signed-in account needs a role that can read Conditional Access policies: Security Reader, Global Reader, Security Administrator, Conditional Access Administrator, or Global Secure Access Administrator.",[37,70,71],{},"A writable path for the baseline JSON file and, optionally, the CSV drift report.",[29,73,75],{"id":74},"parameters","Parameters",[77,78,79,98],"table",{},[80,81,82],"thead",{},[83,84,85,89,92,95],"tr",{},[86,87,88],"th",{},"Name",[86,90,91],{},"Type",[86,93,94],{},"Required",[86,96,97],{},"Description",[99,100,101,122,137,152,170],"tbody",{},[83,102,103,109,112,115],{},[104,105,106],"td",{},[15,107,108],{},"BaselinePath",[104,110,111],{},"string",[104,113,114],{},"Yes",[104,116,117,118,121],{},"Path to the baseline JSON file. Created by a ",[15,119,120],{},"-Snapshot"," run, read by a comparison run.",[83,123,124,129,131,134],{},[104,125,126],{},[15,127,128],{},"OutputPath",[104,130,111],{},[104,132,133],{},"No",[104,135,136],{},"Path to write a CSV drift report. If omitted, drift is only written to the pipeline.",[83,138,139,144,147,149],{},[104,140,141],{},[15,142,143],{},"Snapshot",[104,145,146],{},"switch",[104,148,133],{},[104,150,151],{},"Captures the current policy state as the new baseline instead of comparing against one.",[83,153,154,159,161,163],{},[104,155,156],{},[15,157,158],{},"EmergencyAccessGroupId",[104,160,111],{},[104,162,133],{},[104,164,165,166,169],{},"Object ID of the emergency access group. When set, every enabled user-targeted policy that doesn't exclude it is reported as ",[15,167,168],{},"Missing exclusion",".",[83,171,172,177,179,181],{},[104,173,174],{},[15,175,176],{},"FailOnDrift",[104,178,146],{},[104,180,133],{},[104,182,183],{},"Exits with code 1 when any drift is found, so a scheduled task or pipeline can alert on it.",[29,185,187],{"id":186},"usage","Usage",[11,189,190],{},"Capture the first baseline (do this right after a policy review, not on an arbitrary day):",[192,193,198],"pre",{"className":194,"code":195,"language":196,"meta":197,"style":197},"language-powershell shiki shiki-themes github-dark",".\\Get-ConditionalAccessDrift.ps1 -BaselinePath \"C:\\Audits\\ca-baseline.json\" -Snapshot\n","powershell","",[15,199,200],{"__ignoreMap":197},[201,202,205,208,212,216,219,223,225],"span",{"class":203,"line":204},"line",1,[201,206,169],{"class":207},"s95oV",[201,209,211],{"class":210},"sDLfK","\\Get-ConditionalAccessDrift.ps1",[201,213,215],{"class":214},"snl16"," -",[201,217,218],{"class":207},"BaselinePath ",[201,220,222],{"class":221},"sU2Wk","\"C:\\Audits\\ca-baseline.json\"",[201,224,215],{"class":214},[201,226,227],{"class":207},"Snapshot\n",[11,229,230],{},"Compare the current tenant state against that baseline, check break-glass exclusions, and write a drift report:",[192,232,234],{"className":194,"code":233,"language":196,"meta":197,"style":197},".\\Get-ConditionalAccessDrift.ps1 -BaselinePath \"C:\\Audits\\ca-baseline.json\" -EmergencyAccessGroupId \"\u003Cemergency-access-group-object-id>\" -OutputPath \"C:\\Audits\\ca-drift-2025-08-06.csv\"\n",[15,235,236],{"__ignoreMap":197},[201,237,238,240,242,244,246,248,250,253,256,258,261],{"class":203,"line":204},[201,239,169],{"class":207},[201,241,211],{"class":210},[201,243,215],{"class":214},[201,245,218],{"class":207},[201,247,222],{"class":221},[201,249,215],{"class":214},[201,251,252],{"class":207},"EmergencyAccessGroupId ",[201,254,255],{"class":221},"\"\u003Cemergency-access-group-object-id>\"",[201,257,215],{"class":214},[201,259,260],{"class":207},"OutputPath ",[201,262,263],{"class":221},"\"C:\\Audits\\ca-drift-2025-08-06.csv\"\n",[11,265,266,267,269],{},"Run it unattended with an app registration and a certificate (grant ",[15,268,64],{}," as an application permission first), failing the job when anything changed:",[192,271,273],{"className":194,"code":272,"language":196,"meta":197,"style":197},"Connect-MgGraph -ClientId \"\u003Capp-client-id>\" -TenantId \"\u003Ctenant-id>\" -CertificateThumbprint \"\u003Cthumbprint>\" -NoWelcome\n.\\Get-ConditionalAccessDrift.ps1 -BaselinePath \"D:\\Audits\\ca-baseline.json\" -EmergencyAccessGroupId \"\u003Cemergency-access-group-object-id>\" -FailOnDrift\n",[15,274,275,309],{"__ignoreMap":197},[201,276,277,280,282,285,288,290,293,296,298,301,304,306],{"class":203,"line":204},[201,278,279],{"class":210},"Connect-MgGraph",[201,281,215],{"class":214},[201,283,284],{"class":207},"ClientId ",[201,286,287],{"class":221},"\"\u003Capp-client-id>\"",[201,289,215],{"class":214},[201,291,292],{"class":207},"TenantId ",[201,294,295],{"class":221},"\"\u003Ctenant-id>\"",[201,297,215],{"class":214},[201,299,300],{"class":207},"CertificateThumbprint ",[201,302,303],{"class":221},"\"\u003Cthumbprint>\"",[201,305,215],{"class":214},[201,307,308],{"class":207},"NoWelcome\n",[201,310,312,314,316,318,320,323,325,327,329,331],{"class":203,"line":311},2,[201,313,169],{"class":207},[201,315,211],{"class":210},[201,317,215],{"class":214},[201,319,218],{"class":207},[201,321,322],{"class":221},"\"D:\\Audits\\ca-baseline.json\"",[201,324,215],{"class":214},[201,326,252],{"class":207},[201,328,255],{"class":221},[201,330,215],{"class":214},[201,332,333],{"class":207},"FailOnDrift\n",[11,335,336],{},"Sample output when drift is found:",[192,338,343],{"className":339,"code":341,"language":342,"meta":197},[340],"language-text","Loaded 9 policies; baseline has 9.\nWARNING: 4 drift item(s) detected.\n\nPolicyName                                      Change            Setting                          Detail\n----------                                      ------            -------                          ------\nCA002 - All users - Block legacy authentication Setting changed   state                            Baseline: enabled | Current: enabledForReportingButNotEnforced\nCA003 - All users - Require MFA strength        Value added       conditions.users.excludeGroups   00000000-0000-0000-0000-000000000042\nCA006 - All users - Windows compliant or hybrid Value removed     grantControls.builtInControls    domainJoinedDevice\nCA004 - All users - Require MFA for Azure mana… Missing exclusion conditions.users.excludeGroups   Enabled policy does not exclude emergency access group \u003Cemergency-access-group-object-id>.\n","text",[15,344,341],{"__ignoreMap":197},[29,346,348],{"id":347},"script","Script",[192,350,352],{"className":194,"code":351,"language":196,"meta":197,"style":197},"\u003C#\n.SYNOPSIS\n    Snapshots Entra ID Conditional Access policies and reports drift against a baseline.\n.DESCRIPTION\n    Reads every Conditional Access policy from the Microsoft Graph v1.0 REST endpoint (following\n    paging), flattens each policy into sorted setting paths such as conditions.users.excludeGroups,\n    and either writes them as a new baseline (-Snapshot) or compares them with an existing baseline.\n    Drift is reported per setting: policy added or removed, setting changed, and values added to or\n    removed from a list. Optionally reports enabled policies that don't exclude the emergency access\n    group, and exports the report to CSV.\n.PARAMETER BaselinePath\n    Path to the baseline JSON file. Created by a -Snapshot run, read by a comparison run.\n.PARAMETER OutputPath\n    Path to write a CSV drift report. If omitted, drift is only written to the pipeline.\n.PARAMETER Snapshot\n    Captures the current policy state as the new baseline instead of comparing against one.\n.PARAMETER EmergencyAccessGroupId\n    Object ID of the emergency access group. When set, every enabled user-targeted policy that doesn't\n    exclude it is reported as Missing exclusion.\n.PARAMETER FailOnDrift\n    Exits with code 1 when any drift is found, so a scheduled task or pipeline can alert on it.\n.EXAMPLE\n    .\\Get-ConditionalAccessDrift.ps1 -BaselinePath \"C:\\Audits\\ca-baseline.json\" -Snapshot\n.EXAMPLE\n    .\\Get-ConditionalAccessDrift.ps1 -BaselinePath \"C:\\Audits\\ca-baseline.json\" -EmergencyAccessGroupId \"\u003Cgroup-object-id>\" -OutputPath \"C:\\Audits\\ca-drift.csv\"\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2025-08-06)\n    Requires: PowerShell 7+, Microsoft.Graph.Authentication module, Policy.Read.All\n#>\n[CmdletBinding()]\nparam (\n    [Parameter(Mandatory = $true)]\n    [string]$BaselinePath,\n\n    [string]$OutputPath,\n\n    [switch]$Snapshot,\n\n    [string]$EmergencyAccessGroupId,\n\n    [switch]$FailOnDrift\n)\n\n$ErrorActionPreference = 'Stop'\nImport-Module Microsoft.Graph.Authentication\n\n# Connect if there is no session, or if a delegated session lacks the required scope.\n$context = Get-MgContext\nif (-not $context -or ($context.AuthType -eq 'Delegated' -and $context.Scopes -notcontains 'Policy.Read.All')) {\n    Connect-MgGraph -Scopes 'Policy.Read.All' -NoWelcome\n}\n\n# Keys that change without anyone editing the policy (OData annotations are skipped by pattern).\n$ignoredKeys = @('createdDateTime', 'modifiedDateTime')\n\n# Flatten a policy into path = value pairs. Lists are sorted so reordering is not drift, and\n# empty lists and nulls are skipped because Graph returns both for \"not configured\".\nfunction ConvertTo-FlatSetting {\n    param (\n        $Value,\n        [string]$Path,\n        [System.Collections.IDictionary]$Result\n    )\n\n    if ($null -eq $Value) {\n        return\n    }\n\n    if ($Value -is [System.Collections.IDictionary]) {\n        # Keep only the identity of an authentication strength; Microsoft updates the built-in combinations.\n        if ($Path -like '*.authenticationStrength') {\n            $Result[\"$Path.id\"] = [string]$Value['id']\n            $Result[\"$Path.displayName\"] = [string]$Value['displayName']\n            return\n        }\n\n        foreach ($key in ($Value.Keys | Sort-Object)) {\n            if ($ignoredKeys -contains $key -or $key -like '*@odata.*') {\n                continue\n            }\n            $childPath = if ($Path) { \"$Path.$key\" } else { [string]$key }\n            ConvertTo-FlatSetting -Value $Value[$key] -Path $childPath -Result $Result\n        }\n        return\n    }\n\n    if ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string]) {\n        $items = @($Value)\n        if ($items.Count -eq 0) {\n            return\n        }\n\n        if (@($items | Where-Object { $_ -is [System.Collections.IDictionary] }).Count -gt 0) {\n            for ($i = 0; $i -lt $items.Count; $i++) {\n                ConvertTo-FlatSetting -Value $items[$i] -Path \"$($Path)[$i]\" -Result $Result\n            }\n            return\n        }\n\n        $Result[$Path] = @($items | ForEach-Object { [string]$_ } | Sort-Object)\n        return\n    }\n\n    $Result[$Path] = [string]$Value\n}\n\nfunction Get-CaPolicySetting {\n    $uri = 'https:\u002F\u002Fgraph.microsoft.com\u002Fv1.0\u002Fidentity\u002FconditionalAccess\u002Fpolicies'\n    while ($uri) {\n        $page = Invoke-MgGraphRequest -Method GET -Uri $uri\n        foreach ($policy in $page['value']) {\n            $settings = [ordered]@{}\n            ConvertTo-FlatSetting -Value $policy -Path '' -Result $settings\n            [PSCustomObject]@{\n                Id               = $policy['id']\n                DisplayName      = $policy['displayName']\n                State            = $policy['state']\n                ModifiedDateTime = [string]$policy['modifiedDateTime']\n                Settings         = $settings\n            }\n        }\n        $uri = $page['@odata.nextLink']\n    }\n}\n\n# Turn a possibly-null value into an array without wrapping $null as an item.\nfunction ConvertTo-ItemList {\n    param ($Value)\n\n    if ($null -eq $Value) {\n        return , @()\n    }\n    return , @($Value)\n}\n\n$current = @(Get-CaPolicySetting)\n\nif ($Snapshot) {\n    # -InputObject keeps a one-policy tenant serialized as an array.\n    ConvertTo-Json -InputObject $current -Depth 6 | Set-Content -Path $BaselinePath -Encoding utf8\n    Write-Host \"Baseline written to $BaselinePath ($($current.Count) policies).\"\n    return\n}\n\nif (-not (Test-Path -Path $BaselinePath)) {\n    throw \"Baseline file '$BaselinePath' not found. Run again with -Snapshot to create one.\"\n}\n\n$baseline = @(Get-Content -Path $BaselinePath -Raw | ConvertFrom-Json -AsHashtable)\nWrite-Host \"Loaded $($current.Count) policies; baseline has $($baseline.Count).\"\n\n$baselineById = @{}\nforeach ($item in $baseline) {\n    $baselineById[$item.Id] = $item\n}\n$currentById = @{}\nforeach ($item in $current) {\n    $currentById[$item.Id] = $item\n}\n\n$drift = [System.Collections.Generic.List[PSCustomObject]]::new()\n\nfunction Add-Drift {\n    param (\n        [string]$PolicyName,\n        [string]$Change,\n        [string]$Setting,\n        [string]$Detail\n    )\n\n    $drift.Add([PSCustomObject]@{\n        PolicyName = $PolicyName\n        Change     = $Change\n        Setting    = $Setting\n        Detail     = $Detail\n    })\n}\n\n# Policies that are new or changed since the baseline.\nforeach ($policy in $current) {\n    $match = $baselineById[$policy.Id]\n\n    if (-not $match) {\n        Add-Drift -PolicyName $policy.DisplayName -Change 'Added' -Setting '' -Detail \"Not in the baseline. Last modified $($policy.ModifiedDateTime).\"\n        continue\n    }\n\n    $paths = (@($policy.Settings.Keys) + @($match.Settings.Keys)) | Sort-Object -Unique\n\n    foreach ($path in $paths) {\n        $old = $match.Settings[$path]\n        $new = $policy.Settings[$path]\n        $isList = ($old -is [System.Collections.IEnumerable] -and $old -isnot [string]) -or\n            ($new -is [System.Collections.IEnumerable] -and $new -isnot [string])\n\n        if ($isList) {\n            $oldItems = ConvertTo-ItemList -Value $old\n            $newItems = ConvertTo-ItemList -Value $new\n            foreach ($value in ($newItems | Where-Object { $oldItems -notcontains $_ })) {\n                Add-Drift -PolicyName $policy.DisplayName -Change 'Value added' -Setting $path -Detail $value\n            }\n            foreach ($value in ($oldItems | Where-Object { $newItems -notcontains $_ })) {\n                Add-Drift -PolicyName $policy.DisplayName -Change 'Value removed' -Setting $path -Detail $value\n            }\n        } elseif ([string]$old -cne [string]$new) {\n            $oldText = if ($null -eq $old) { '(not set)' } else { $old }\n            $newText = if ($null -eq $new) { '(not set)' } else { $new }\n            Add-Drift -PolicyName $policy.DisplayName -Change 'Setting changed' -Setting $path -Detail \"Baseline: $oldText | Current: $newText\"\n        }\n    }\n}\n\n# Policies that were in the baseline but have since been removed.\nforeach ($item in $baseline) {\n    if (-not $currentById[$item.Id]) {\n        Add-Drift -PolicyName $item.DisplayName -Change 'Removed' -Setting '' -Detail 'In the baseline but no longer in the tenant.'\n    }\n}\n\n# Enabled, user-targeted policies that don't exclude the emergency access group.\nif ($EmergencyAccessGroupId) {\n    foreach ($policy in ($current | Where-Object { $_.State -eq 'enabled' })) {\n        $targetsUsers = @($policy.Settings.Keys | Where-Object { $_ -like 'conditions.users.include*' }).Count -gt 0\n        $excluded = ConvertTo-ItemList -Value $policy.Settings['conditions.users.excludeGroups']\n        if ($targetsUsers -and $excluded -notcontains $EmergencyAccessGroupId) {\n            Add-Drift -PolicyName $policy.DisplayName -Change 'Missing exclusion' -Setting 'conditions.users.excludeGroups' -Detail \"Enabled policy does not exclude emergency access group $EmergencyAccessGroupId.\"\n        }\n    }\n}\n\nif ($drift.Count -eq 0) {\n    Write-Host \"No drift detected across $($current.Count) Conditional Access policies.\"\n} else {\n    Write-Warning \"$($drift.Count) drift item(s) detected.\"\n    $drift\n\n    if ($OutputPath) {\n        $drift | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding utf8\n        Write-Host \"Drift report written to $OutputPath.\"\n    }\n\n    if ($FailOnDrift) {\n        exit 1\n    }\n}\n",[15,353,354,360,367,373,381,387,393,399,405,411,417,428,434,444,450,460,466,476,482,488,498,504,512,518,525,531,539,545,551,557,563,575,584,609,622,629,641,646,658,663,675,680,690,696,701,712,721,726,732,744,786,804,810,815,821,845,850,856,862,875,883,891,904,915,921,926,943,949,955,960,979,985,1003,1036,1063,1069,1075,1080,1103,1129,1135,1141,1180,1202,1207,1212,1217,1222,1253,1266,1281,1286,1291,1296,1337,1364,1404,1409,1414,1419,1424,1458,1463,1468,1473,1488,1493,1498,1508,1519,1528,1549,1567,1587,1609,1625,1640,1654,1669,1689,1700,1705,1710,1725,1730,1735,1740,1746,1756,1764,1769,1782,1796,1801,1813,1818,1823,1840,1845,1853,1859,1894,1920,1926,1931,1936,1955,1969,1974,1979,2013,2045,2050,2062,2076,2087,2092,2104,2116,2126,2131,2136,2156,2161,2171,2178,2190,2202,2214,2224,2229,2234,2248,2259,2270,2281,2292,2298,2303,2308,2314,2325,2336,2341,2353,2398,2404,2409,2414,2446,2451,2465,2476,2487,2523,2551,2556,2564,2579,2594,2623,2650,2655,2680,2704,2709,2736,2765,2793,2833,2838,2843,2848,2853,2859,2870,2882,2912,2917,2922,2927,2933,2941,2971,3006,3026,3044,3078,3083,3088,3093,3098,3112,3131,3141,3162,3168,3173,3181,3206,3220,3225,3230,3238,3247,3252],{"__ignoreMap":197},[201,355,356],{"class":203,"line":204},[201,357,359],{"class":358},"sAwPA","\u003C#\n",[201,361,362,364],{"class":203,"line":311},[201,363,169],{"class":210},[201,365,366],{"class":214},"SYNOPSIS\n",[201,368,370],{"class":203,"line":369},3,[201,371,372],{"class":358},"    Snapshots Entra ID Conditional Access policies and reports drift against a baseline.\n",[201,374,376,378],{"class":203,"line":375},4,[201,377,169],{"class":210},[201,379,380],{"class":214},"DESCRIPTION\n",[201,382,384],{"class":203,"line":383},5,[201,385,386],{"class":358},"    Reads every Conditional Access policy from the Microsoft Graph v1.0 REST endpoint (following\n",[201,388,390],{"class":203,"line":389},6,[201,391,392],{"class":358},"    paging), flattens each policy into sorted setting paths such as conditions.users.excludeGroups,\n",[201,394,396],{"class":203,"line":395},7,[201,397,398],{"class":358},"    and either writes them as a new baseline (-Snapshot) or compares them with an existing baseline.\n",[201,400,402],{"class":203,"line":401},8,[201,403,404],{"class":358},"    Drift is reported per setting: policy added or removed, setting changed, and values added to or\n",[201,406,408],{"class":203,"line":407},9,[201,409,410],{"class":358},"    removed from a list. Optionally reports enabled policies that don't exclude the emergency access\n",[201,412,414],{"class":203,"line":413},10,[201,415,416],{"class":358},"    group, and exports the report to CSV.\n",[201,418,420,422,425],{"class":203,"line":419},11,[201,421,169],{"class":210},[201,423,424],{"class":214},"PARAMETER",[201,426,427],{"class":214}," BaselinePath\n",[201,429,431],{"class":203,"line":430},12,[201,432,433],{"class":358},"    Path to the baseline JSON file. Created by a -Snapshot run, read by a comparison run.\n",[201,435,437,439,441],{"class":203,"line":436},13,[201,438,169],{"class":210},[201,440,424],{"class":214},[201,442,443],{"class":214}," OutputPath\n",[201,445,447],{"class":203,"line":446},14,[201,448,449],{"class":358},"    Path to write a CSV drift report. If omitted, drift is only written to the pipeline.\n",[201,451,453,455,457],{"class":203,"line":452},15,[201,454,169],{"class":210},[201,456,424],{"class":214},[201,458,459],{"class":214}," Snapshot\n",[201,461,463],{"class":203,"line":462},16,[201,464,465],{"class":358},"    Captures the current policy state as the new baseline instead of comparing against one.\n",[201,467,469,471,473],{"class":203,"line":468},17,[201,470,169],{"class":210},[201,472,424],{"class":214},[201,474,475],{"class":214}," EmergencyAccessGroupId\n",[201,477,479],{"class":203,"line":478},18,[201,480,481],{"class":358},"    Object ID of the emergency access group. When set, every enabled user-targeted policy that doesn't\n",[201,483,485],{"class":203,"line":484},19,[201,486,487],{"class":358},"    exclude it is reported as Missing exclusion.\n",[201,489,491,493,495],{"class":203,"line":490},20,[201,492,169],{"class":210},[201,494,424],{"class":214},[201,496,497],{"class":214}," FailOnDrift\n",[201,499,501],{"class":203,"line":500},21,[201,502,503],{"class":358},"    Exits with code 1 when any drift is found, so a scheduled task or pipeline can alert on it.\n",[201,505,507,509],{"class":203,"line":506},22,[201,508,169],{"class":210},[201,510,511],{"class":214},"EXAMPLE\n",[201,513,515],{"class":203,"line":514},23,[201,516,517],{"class":358},"    .\\Get-ConditionalAccessDrift.ps1 -BaselinePath \"C:\\Audits\\ca-baseline.json\" -Snapshot\n",[201,519,521,523],{"class":203,"line":520},24,[201,522,169],{"class":210},[201,524,511],{"class":214},[201,526,528],{"class":203,"line":527},25,[201,529,530],{"class":358},"    .\\Get-ConditionalAccessDrift.ps1 -BaselinePath \"C:\\Audits\\ca-baseline.json\" -EmergencyAccessGroupId \"\u003Cgroup-object-id>\" -OutputPath \"C:\\Audits\\ca-drift.csv\"\n",[201,532,534,536],{"class":203,"line":533},26,[201,535,169],{"class":210},[201,537,538],{"class":214},"NOTES\n",[201,540,542],{"class":203,"line":541},27,[201,543,544],{"class":358},"    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n",[201,546,548],{"class":203,"line":547},28,[201,549,550],{"class":358},"    Version : 1.0 (2025-08-06)\n",[201,552,554],{"class":203,"line":553},29,[201,555,556],{"class":358},"    Requires: PowerShell 7+, Microsoft.Graph.Authentication module, Policy.Read.All\n",[201,558,560],{"class":203,"line":559},30,[201,561,562],{"class":358},"#>\n",[201,564,566,569,572],{"class":203,"line":565},31,[201,567,568],{"class":207},"[",[201,570,571],{"class":210},"CmdletBinding",[201,573,574],{"class":207},"()]\n",[201,576,578,581],{"class":203,"line":577},32,[201,579,580],{"class":214},"param",[201,582,583],{"class":207}," (\n",[201,585,587,590,593,596,600,603,606],{"class":203,"line":586},33,[201,588,589],{"class":207},"    [",[201,591,592],{"class":210},"Parameter",[201,594,595],{"class":207},"(",[201,597,599],{"class":598},"s9osk","Mandatory",[201,601,602],{"class":214}," =",[201,604,605],{"class":210}," $true",[201,607,608],{"class":207},")]\n",[201,610,612,614,616,619],{"class":203,"line":611},34,[201,613,589],{"class":207},[201,615,111],{"class":214},[201,617,618],{"class":207},"]$BaselinePath",[201,620,621],{"class":214},",\n",[201,623,625],{"class":203,"line":624},35,[201,626,628],{"emptyLinePlaceholder":627},true,"\n",[201,630,632,634,636,639],{"class":203,"line":631},36,[201,633,589],{"class":207},[201,635,111],{"class":214},[201,637,638],{"class":207},"]$OutputPath",[201,640,621],{"class":214},[201,642,644],{"class":203,"line":643},37,[201,645,628],{"emptyLinePlaceholder":627},[201,647,649,651,653,656],{"class":203,"line":648},38,[201,650,589],{"class":207},[201,652,146],{"class":214},[201,654,655],{"class":207},"]$Snapshot",[201,657,621],{"class":214},[201,659,661],{"class":203,"line":660},39,[201,662,628],{"emptyLinePlaceholder":627},[201,664,666,668,670,673],{"class":203,"line":665},40,[201,667,589],{"class":207},[201,669,111],{"class":214},[201,671,672],{"class":207},"]$EmergencyAccessGroupId",[201,674,621],{"class":214},[201,676,678],{"class":203,"line":677},41,[201,679,628],{"emptyLinePlaceholder":627},[201,681,683,685,687],{"class":203,"line":682},42,[201,684,589],{"class":207},[201,686,146],{"class":214},[201,688,689],{"class":207},"]$FailOnDrift\n",[201,691,693],{"class":203,"line":692},43,[201,694,695],{"class":207},")\n",[201,697,699],{"class":203,"line":698},44,[201,700,628],{"emptyLinePlaceholder":627},[201,702,704,707,709],{"class":203,"line":703},45,[201,705,706],{"class":210},"$ErrorActionPreference",[201,708,602],{"class":214},[201,710,711],{"class":221}," 'Stop'\n",[201,713,715,718],{"class":203,"line":714},46,[201,716,717],{"class":210},"Import-Module",[201,719,720],{"class":207}," Microsoft.Graph.Authentication\n",[201,722,724],{"class":203,"line":723},47,[201,725,628],{"emptyLinePlaceholder":627},[201,727,729],{"class":203,"line":728},48,[201,730,731],{"class":358},"# Connect if there is no session, or if a delegated session lacks the required scope.\n",[201,733,735,738,741],{"class":203,"line":734},49,[201,736,737],{"class":207},"$context ",[201,739,740],{"class":214},"=",[201,742,743],{"class":210}," Get-MgContext\n",[201,745,747,750,753,756,759,762,765,768,771,774,777,780,783],{"class":203,"line":746},50,[201,748,749],{"class":214},"if",[201,751,752],{"class":207}," (",[201,754,755],{"class":214},"-not",[201,757,758],{"class":207}," $context ",[201,760,761],{"class":214},"-or",[201,763,764],{"class":207}," ($context.AuthType ",[201,766,767],{"class":214},"-eq",[201,769,770],{"class":221}," 'Delegated'",[201,772,773],{"class":214}," -and",[201,775,776],{"class":207}," $context.Scopes ",[201,778,779],{"class":214},"-notcontains",[201,781,782],{"class":221}," 'Policy.Read.All'",[201,784,785],{"class":207},")) {\n",[201,787,789,792,794,797,800,802],{"class":203,"line":788},51,[201,790,791],{"class":210},"    Connect-MgGraph",[201,793,215],{"class":214},[201,795,796],{"class":207},"Scopes ",[201,798,799],{"class":221},"'Policy.Read.All'",[201,801,215],{"class":214},[201,803,308],{"class":207},[201,805,807],{"class":203,"line":806},52,[201,808,809],{"class":207},"}\n",[201,811,813],{"class":203,"line":812},53,[201,814,628],{"emptyLinePlaceholder":627},[201,816,818],{"class":203,"line":817},54,[201,819,820],{"class":358},"# Keys that change without anyone editing the policy (OData annotations are skipped by pattern).\n",[201,822,824,827,829,832,834,837,840,843],{"class":203,"line":823},55,[201,825,826],{"class":207},"$ignoredKeys ",[201,828,740],{"class":214},[201,830,831],{"class":214}," @",[201,833,595],{"class":207},[201,835,836],{"class":221},"'createdDateTime'",[201,838,839],{"class":214},",",[201,841,842],{"class":221}," 'modifiedDateTime'",[201,844,695],{"class":207},[201,846,848],{"class":203,"line":847},56,[201,849,628],{"emptyLinePlaceholder":627},[201,851,853],{"class":203,"line":852},57,[201,854,855],{"class":358},"# Flatten a policy into path = value pairs. Lists are sorted so reordering is not drift, and\n",[201,857,859],{"class":203,"line":858},58,[201,860,861],{"class":358},"# empty lists and nulls are skipped because Graph returns both for \"not configured\".\n",[201,863,865,868,872],{"class":203,"line":864},59,[201,866,867],{"class":214},"function",[201,869,871],{"class":870},"svObZ"," ConvertTo-FlatSetting",[201,873,874],{"class":207}," {\n",[201,876,878,881],{"class":203,"line":877},60,[201,879,880],{"class":214},"    param",[201,882,583],{"class":207},[201,884,886,889],{"class":203,"line":885},61,[201,887,888],{"class":207},"        $Value",[201,890,621],{"class":214},[201,892,894,897,899,902],{"class":203,"line":893},62,[201,895,896],{"class":207},"        [",[201,898,111],{"class":214},[201,900,901],{"class":207},"]$Path",[201,903,621],{"class":214},[201,905,907,909,912],{"class":203,"line":906},63,[201,908,896],{"class":207},[201,910,911],{"class":214},"System.Collections.IDictionary",[201,913,914],{"class":207},"]$Result\n",[201,916,918],{"class":203,"line":917},64,[201,919,920],{"class":207},"    )\n",[201,922,924],{"class":203,"line":923},65,[201,925,628],{"emptyLinePlaceholder":627},[201,927,929,932,934,937,940],{"class":203,"line":928},66,[201,930,931],{"class":214},"    if",[201,933,752],{"class":207},[201,935,936],{"class":210},"$null",[201,938,939],{"class":214}," -eq",[201,941,942],{"class":207}," $Value) {\n",[201,944,946],{"class":203,"line":945},67,[201,947,948],{"class":214},"        return\n",[201,950,952],{"class":203,"line":951},68,[201,953,954],{"class":207},"    }\n",[201,956,958],{"class":203,"line":957},69,[201,959,628],{"emptyLinePlaceholder":627},[201,961,963,965,968,971,974,976],{"class":203,"line":962},70,[201,964,931],{"class":214},[201,966,967],{"class":207}," ($Value ",[201,969,970],{"class":214},"-is",[201,972,973],{"class":207}," [",[201,975,911],{"class":214},[201,977,978],{"class":207},"]) {\n",[201,980,982],{"class":203,"line":981},71,[201,983,984],{"class":358},"        # Keep only the identity of an authentication strength; Microsoft updates the built-in combinations.\n",[201,986,988,991,994,997,1000],{"class":203,"line":987},72,[201,989,990],{"class":214},"        if",[201,992,993],{"class":207}," ($Path ",[201,995,996],{"class":214},"-like",[201,998,999],{"class":221}," '*.authenticationStrength'",[201,1001,1002],{"class":207},") {\n",[201,1004,1006,1009,1012,1015,1018,1021,1023,1025,1027,1030,1033],{"class":203,"line":1005},73,[201,1007,1008],{"class":207},"            $Result[",[201,1010,1011],{"class":221},"\"",[201,1013,1014],{"class":207},"$Path",[201,1016,1017],{"class":221},".id\"",[201,1019,1020],{"class":207},"] ",[201,1022,740],{"class":214},[201,1024,973],{"class":207},[201,1026,111],{"class":214},[201,1028,1029],{"class":207},"]$Value[",[201,1031,1032],{"class":221},"'id'",[201,1034,1035],{"class":207},"]\n",[201,1037,1039,1041,1043,1045,1048,1050,1052,1054,1056,1058,1061],{"class":203,"line":1038},74,[201,1040,1008],{"class":207},[201,1042,1011],{"class":221},[201,1044,1014],{"class":207},[201,1046,1047],{"class":221},".displayName\"",[201,1049,1020],{"class":207},[201,1051,740],{"class":214},[201,1053,973],{"class":207},[201,1055,111],{"class":214},[201,1057,1029],{"class":207},[201,1059,1060],{"class":221},"'displayName'",[201,1062,1035],{"class":207},[201,1064,1066],{"class":203,"line":1065},75,[201,1067,1068],{"class":214},"            return\n",[201,1070,1072],{"class":203,"line":1071},76,[201,1073,1074],{"class":207},"        }\n",[201,1076,1078],{"class":203,"line":1077},77,[201,1079,628],{"emptyLinePlaceholder":627},[201,1081,1083,1086,1089,1092,1095,1098,1101],{"class":203,"line":1082},78,[201,1084,1085],{"class":214},"        foreach",[201,1087,1088],{"class":207}," ($key ",[201,1090,1091],{"class":214},"in",[201,1093,1094],{"class":207}," ($Value.Keys ",[201,1096,1097],{"class":214},"|",[201,1099,1100],{"class":210}," Sort-Object",[201,1102,785],{"class":207},[201,1104,1106,1109,1112,1115,1118,1120,1122,1124,1127],{"class":203,"line":1105},79,[201,1107,1108],{"class":214},"            if",[201,1110,1111],{"class":207}," ($ignoredKeys ",[201,1113,1114],{"class":214},"-contains",[201,1116,1117],{"class":207}," $key ",[201,1119,761],{"class":214},[201,1121,1117],{"class":207},[201,1123,996],{"class":214},[201,1125,1126],{"class":221}," '*@odata.*'",[201,1128,1002],{"class":207},[201,1130,1132],{"class":203,"line":1131},80,[201,1133,1134],{"class":214},"                continue\n",[201,1136,1138],{"class":203,"line":1137},81,[201,1139,1140],{"class":207},"            }\n",[201,1142,1144,1147,1149,1152,1155,1157,1159,1161,1164,1166,1169,1172,1175,1177],{"class":203,"line":1143},82,[201,1145,1146],{"class":207},"            $childPath ",[201,1148,740],{"class":214},[201,1150,1151],{"class":214}," if",[201,1153,1154],{"class":207}," ($Path) { ",[201,1156,1011],{"class":221},[201,1158,1014],{"class":207},[201,1160,169],{"class":221},[201,1162,1163],{"class":207},"$key",[201,1165,1011],{"class":221},[201,1167,1168],{"class":207}," } ",[201,1170,1171],{"class":214},"else",[201,1173,1174],{"class":207}," { [",[201,1176,111],{"class":214},[201,1178,1179],{"class":207},"]$key }\n",[201,1181,1183,1186,1188,1191,1194,1197,1199],{"class":203,"line":1182},83,[201,1184,1185],{"class":210},"            ConvertTo-FlatSetting",[201,1187,215],{"class":214},[201,1189,1190],{"class":207},"Value $Value[$key] ",[201,1192,1193],{"class":214},"-",[201,1195,1196],{"class":207},"Path $childPath ",[201,1198,1193],{"class":214},[201,1200,1201],{"class":207},"Result $Result\n",[201,1203,1205],{"class":203,"line":1204},84,[201,1206,1074],{"class":207},[201,1208,1210],{"class":203,"line":1209},85,[201,1211,948],{"class":214},[201,1213,1215],{"class":203,"line":1214},86,[201,1216,954],{"class":207},[201,1218,1220],{"class":203,"line":1219},87,[201,1221,628],{"emptyLinePlaceholder":627},[201,1223,1225,1227,1229,1231,1233,1236,1238,1241,1244,1247,1249,1251],{"class":203,"line":1224},88,[201,1226,931],{"class":214},[201,1228,967],{"class":207},[201,1230,970],{"class":214},[201,1232,973],{"class":207},[201,1234,1235],{"class":214},"System.Collections.IEnumerable",[201,1237,1020],{"class":207},[201,1239,1240],{"class":214},"-and",[201,1242,1243],{"class":207}," $Value ",[201,1245,1246],{"class":214},"-isnot",[201,1248,973],{"class":207},[201,1250,111],{"class":214},[201,1252,978],{"class":207},[201,1254,1256,1259,1261,1263],{"class":203,"line":1255},89,[201,1257,1258],{"class":207},"        $items ",[201,1260,740],{"class":214},[201,1262,831],{"class":214},[201,1264,1265],{"class":207},"($Value)\n",[201,1267,1269,1271,1274,1276,1279],{"class":203,"line":1268},90,[201,1270,990],{"class":214},[201,1272,1273],{"class":207}," ($items.Count ",[201,1275,767],{"class":214},[201,1277,1278],{"class":210}," 0",[201,1280,1002],{"class":207},[201,1282,1284],{"class":203,"line":1283},91,[201,1285,1068],{"class":214},[201,1287,1289],{"class":203,"line":1288},92,[201,1290,1074],{"class":207},[201,1292,1294],{"class":203,"line":1293},93,[201,1295,628],{"emptyLinePlaceholder":627},[201,1297,1299,1301,1303,1306,1309,1311,1314,1317,1320,1323,1325,1327,1330,1333,1335],{"class":203,"line":1298},94,[201,1300,990],{"class":214},[201,1302,752],{"class":207},[201,1304,1305],{"class":214},"@",[201,1307,1308],{"class":207},"($items ",[201,1310,1097],{"class":214},[201,1312,1313],{"class":210}," Where-Object",[201,1315,1316],{"class":207}," { ",[201,1318,1319],{"class":210},"$_",[201,1321,1322],{"class":214}," -is",[201,1324,973],{"class":207},[201,1326,911],{"class":214},[201,1328,1329],{"class":207},"] }).Count ",[201,1331,1332],{"class":214},"-gt",[201,1334,1278],{"class":210},[201,1336,1002],{"class":207},[201,1338,1340,1343,1346,1348,1350,1353,1356,1359,1362],{"class":203,"line":1339},95,[201,1341,1342],{"class":214},"            for",[201,1344,1345],{"class":207}," ($i ",[201,1347,740],{"class":214},[201,1349,1278],{"class":210},[201,1351,1352],{"class":207},"; $i ",[201,1354,1355],{"class":214},"-lt",[201,1357,1358],{"class":207}," $items.Count; $i",[201,1360,1361],{"class":214},"++",[201,1363,1002],{"class":207},[201,1365,1367,1370,1372,1375,1377,1380,1382,1385,1387,1389,1392,1394,1397,1400,1402],{"class":203,"line":1366},96,[201,1368,1369],{"class":210},"                ConvertTo-FlatSetting",[201,1371,215],{"class":214},[201,1373,1374],{"class":207},"Value $items[$i] ",[201,1376,1193],{"class":214},[201,1378,1379],{"class":207},"Path ",[201,1381,1011],{"class":221},[201,1383,1384],{"class":214},"$",[201,1386,595],{"class":221},[201,1388,1014],{"class":207},[201,1390,1391],{"class":221},")",[201,1393,568],{"class":221},[201,1395,1396],{"class":207},"$i",[201,1398,1399],{"class":221},"]\"",[201,1401,215],{"class":214},[201,1403,1201],{"class":207},[201,1405,1407],{"class":203,"line":1406},97,[201,1408,1140],{"class":207},[201,1410,1412],{"class":203,"line":1411},98,[201,1413,1068],{"class":214},[201,1415,1417],{"class":203,"line":1416},99,[201,1418,1074],{"class":207},[201,1420,1422],{"class":203,"line":1421},100,[201,1423,628],{"emptyLinePlaceholder":627},[201,1425,1427,1430,1432,1434,1436,1438,1441,1443,1445,1448,1450,1452,1454,1456],{"class":203,"line":1426},101,[201,1428,1429],{"class":207},"        $Result[$Path] ",[201,1431,740],{"class":214},[201,1433,831],{"class":214},[201,1435,1308],{"class":207},[201,1437,1097],{"class":214},[201,1439,1440],{"class":210}," ForEach-Object",[201,1442,1174],{"class":207},[201,1444,111],{"class":214},[201,1446,1447],{"class":207},"]",[201,1449,1319],{"class":210},[201,1451,1168],{"class":207},[201,1453,1097],{"class":214},[201,1455,1100],{"class":210},[201,1457,695],{"class":207},[201,1459,1461],{"class":203,"line":1460},102,[201,1462,948],{"class":214},[201,1464,1466],{"class":203,"line":1465},103,[201,1467,954],{"class":207},[201,1469,1471],{"class":203,"line":1470},104,[201,1472,628],{"emptyLinePlaceholder":627},[201,1474,1476,1479,1481,1483,1485],{"class":203,"line":1475},105,[201,1477,1478],{"class":207},"    $Result[$Path] ",[201,1480,740],{"class":214},[201,1482,973],{"class":207},[201,1484,111],{"class":214},[201,1486,1487],{"class":207},"]$Value\n",[201,1489,1491],{"class":203,"line":1490},106,[201,1492,809],{"class":207},[201,1494,1496],{"class":203,"line":1495},107,[201,1497,628],{"emptyLinePlaceholder":627},[201,1499,1501,1503,1506],{"class":203,"line":1500},108,[201,1502,867],{"class":214},[201,1504,1505],{"class":870}," Get-CaPolicySetting",[201,1507,874],{"class":207},[201,1509,1511,1514,1516],{"class":203,"line":1510},109,[201,1512,1513],{"class":207},"    $uri ",[201,1515,740],{"class":214},[201,1517,1518],{"class":221}," 'https:\u002F\u002Fgraph.microsoft.com\u002Fv1.0\u002Fidentity\u002FconditionalAccess\u002Fpolicies'\n",[201,1520,1522,1525],{"class":203,"line":1521},110,[201,1523,1524],{"class":214},"    while",[201,1526,1527],{"class":207}," ($uri) {\n",[201,1529,1531,1534,1536,1539,1541,1544,1546],{"class":203,"line":1530},111,[201,1532,1533],{"class":207},"        $page ",[201,1535,740],{"class":214},[201,1537,1538],{"class":210}," Invoke-MgGraphRequest",[201,1540,215],{"class":214},[201,1542,1543],{"class":207},"Method GET ",[201,1545,1193],{"class":214},[201,1547,1548],{"class":207},"Uri $uri\n",[201,1550,1552,1554,1557,1559,1562,1565],{"class":203,"line":1551},112,[201,1553,1085],{"class":214},[201,1555,1556],{"class":207}," ($policy ",[201,1558,1091],{"class":214},[201,1560,1561],{"class":207}," $page[",[201,1563,1564],{"class":221},"'value'",[201,1566,978],{"class":207},[201,1568,1570,1573,1575,1577,1580,1582,1584],{"class":203,"line":1569},113,[201,1571,1572],{"class":207},"            $settings ",[201,1574,740],{"class":214},[201,1576,973],{"class":207},[201,1578,1579],{"class":214},"ordered",[201,1581,1447],{"class":207},[201,1583,1305],{"class":214},[201,1585,1586],{"class":207},"{}\n",[201,1588,1590,1592,1594,1597,1599,1601,1604,1606],{"class":203,"line":1589},114,[201,1591,1185],{"class":210},[201,1593,215],{"class":214},[201,1595,1596],{"class":207},"Value $policy ",[201,1598,1193],{"class":214},[201,1600,1379],{"class":207},[201,1602,1603],{"class":221},"''",[201,1605,215],{"class":214},[201,1607,1608],{"class":207},"Result $settings\n",[201,1610,1612,1615,1618,1620,1622],{"class":203,"line":1611},115,[201,1613,1614],{"class":207},"            [",[201,1616,1617],{"class":214},"PSCustomObject",[201,1619,1447],{"class":207},[201,1621,1305],{"class":214},[201,1623,1624],{"class":207},"{\n",[201,1626,1628,1631,1633,1636,1638],{"class":203,"line":1627},116,[201,1629,1630],{"class":207},"                Id               ",[201,1632,740],{"class":214},[201,1634,1635],{"class":207}," $policy[",[201,1637,1032],{"class":221},[201,1639,1035],{"class":207},[201,1641,1643,1646,1648,1650,1652],{"class":203,"line":1642},117,[201,1644,1645],{"class":207},"                DisplayName      ",[201,1647,740],{"class":214},[201,1649,1635],{"class":207},[201,1651,1060],{"class":221},[201,1653,1035],{"class":207},[201,1655,1657,1660,1662,1664,1667],{"class":203,"line":1656},118,[201,1658,1659],{"class":207},"                State            ",[201,1661,740],{"class":214},[201,1663,1635],{"class":207},[201,1665,1666],{"class":221},"'state'",[201,1668,1035],{"class":207},[201,1670,1672,1675,1677,1679,1681,1684,1687],{"class":203,"line":1671},119,[201,1673,1674],{"class":207},"                ModifiedDateTime ",[201,1676,740],{"class":214},[201,1678,973],{"class":207},[201,1680,111],{"class":214},[201,1682,1683],{"class":207},"]$policy[",[201,1685,1686],{"class":221},"'modifiedDateTime'",[201,1688,1035],{"class":207},[201,1690,1692,1695,1697],{"class":203,"line":1691},120,[201,1693,1694],{"class":207},"                Settings         ",[201,1696,740],{"class":214},[201,1698,1699],{"class":207}," $settings\n",[201,1701,1703],{"class":203,"line":1702},121,[201,1704,1140],{"class":207},[201,1706,1708],{"class":203,"line":1707},122,[201,1709,1074],{"class":207},[201,1711,1713,1716,1718,1720,1723],{"class":203,"line":1712},123,[201,1714,1715],{"class":207},"        $uri ",[201,1717,740],{"class":214},[201,1719,1561],{"class":207},[201,1721,1722],{"class":221},"'@odata.nextLink'",[201,1724,1035],{"class":207},[201,1726,1728],{"class":203,"line":1727},124,[201,1729,954],{"class":207},[201,1731,1733],{"class":203,"line":1732},125,[201,1734,809],{"class":207},[201,1736,1738],{"class":203,"line":1737},126,[201,1739,628],{"emptyLinePlaceholder":627},[201,1741,1743],{"class":203,"line":1742},127,[201,1744,1745],{"class":358},"# Turn a possibly-null value into an array without wrapping $null as an item.\n",[201,1747,1749,1751,1754],{"class":203,"line":1748},128,[201,1750,867],{"class":214},[201,1752,1753],{"class":870}," ConvertTo-ItemList",[201,1755,874],{"class":207},[201,1757,1759,1761],{"class":203,"line":1758},129,[201,1760,880],{"class":214},[201,1762,1763],{"class":207}," ($Value)\n",[201,1765,1767],{"class":203,"line":1766},130,[201,1768,628],{"emptyLinePlaceholder":627},[201,1770,1772,1774,1776,1778,1780],{"class":203,"line":1771},131,[201,1773,931],{"class":214},[201,1775,752],{"class":207},[201,1777,936],{"class":210},[201,1779,939],{"class":214},[201,1781,942],{"class":207},[201,1783,1785,1788,1791,1793],{"class":203,"line":1784},132,[201,1786,1787],{"class":214},"        return",[201,1789,1790],{"class":214}," ,",[201,1792,831],{"class":214},[201,1794,1795],{"class":207},"()\n",[201,1797,1799],{"class":203,"line":1798},133,[201,1800,954],{"class":207},[201,1802,1804,1807,1809,1811],{"class":203,"line":1803},134,[201,1805,1806],{"class":214},"    return",[201,1808,1790],{"class":214},[201,1810,831],{"class":214},[201,1812,1265],{"class":207},[201,1814,1816],{"class":203,"line":1815},135,[201,1817,809],{"class":207},[201,1819,1821],{"class":203,"line":1820},136,[201,1822,628],{"emptyLinePlaceholder":627},[201,1824,1826,1829,1831,1833,1835,1838],{"class":203,"line":1825},137,[201,1827,1828],{"class":207},"$current ",[201,1830,740],{"class":214},[201,1832,831],{"class":214},[201,1834,595],{"class":207},[201,1836,1837],{"class":210},"Get-CaPolicySetting",[201,1839,695],{"class":207},[201,1841,1843],{"class":203,"line":1842},138,[201,1844,628],{"emptyLinePlaceholder":627},[201,1846,1848,1850],{"class":203,"line":1847},139,[201,1849,749],{"class":214},[201,1851,1852],{"class":207}," ($Snapshot) {\n",[201,1854,1856],{"class":203,"line":1855},140,[201,1857,1858],{"class":358},"    # -InputObject keeps a one-policy tenant serialized as an array.\n",[201,1860,1862,1865,1867,1870,1872,1875,1878,1881,1884,1886,1889,1891],{"class":203,"line":1861},141,[201,1863,1864],{"class":210},"    ConvertTo-Json",[201,1866,215],{"class":214},[201,1868,1869],{"class":207},"InputObject $current ",[201,1871,1193],{"class":214},[201,1873,1874],{"class":207},"Depth ",[201,1876,1877],{"class":210},"6",[201,1879,1880],{"class":214}," |",[201,1882,1883],{"class":210}," Set-Content",[201,1885,215],{"class":214},[201,1887,1888],{"class":207},"Path $BaselinePath ",[201,1890,1193],{"class":214},[201,1892,1893],{"class":207},"Encoding utf8\n",[201,1895,1897,1900,1903,1906,1908,1910,1912,1915,1917],{"class":203,"line":1896},142,[201,1898,1899],{"class":210},"    Write-Host",[201,1901,1902],{"class":221}," \"Baseline written to ",[201,1904,1905],{"class":207},"$BaselinePath",[201,1907,752],{"class":221},[201,1909,1384],{"class":214},[201,1911,595],{"class":221},[201,1913,1914],{"class":207},"$current.Count",[201,1916,1391],{"class":221},[201,1918,1919],{"class":221}," policies).\"\n",[201,1921,1923],{"class":203,"line":1922},143,[201,1924,1925],{"class":214},"    return\n",[201,1927,1929],{"class":203,"line":1928},144,[201,1930,809],{"class":207},[201,1932,1934],{"class":203,"line":1933},145,[201,1935,628],{"emptyLinePlaceholder":627},[201,1937,1939,1941,1943,1945,1947,1950,1952],{"class":203,"line":1938},146,[201,1940,749],{"class":214},[201,1942,752],{"class":207},[201,1944,755],{"class":214},[201,1946,752],{"class":207},[201,1948,1949],{"class":210},"Test-Path",[201,1951,215],{"class":214},[201,1953,1954],{"class":207},"Path $BaselinePath)) {\n",[201,1956,1958,1961,1964,1966],{"class":203,"line":1957},147,[201,1959,1960],{"class":214},"    throw",[201,1962,1963],{"class":221}," \"Baseline file '",[201,1965,1905],{"class":207},[201,1967,1968],{"class":221},"' not found. Run again with -Snapshot to create one.\"\n",[201,1970,1972],{"class":203,"line":1971},148,[201,1973,809],{"class":207},[201,1975,1977],{"class":203,"line":1976},149,[201,1978,628],{"emptyLinePlaceholder":627},[201,1980,1982,1985,1987,1989,1991,1994,1996,1998,2000,2003,2005,2008,2010],{"class":203,"line":1981},150,[201,1983,1984],{"class":207},"$baseline ",[201,1986,740],{"class":214},[201,1988,831],{"class":214},[201,1990,595],{"class":207},[201,1992,1993],{"class":210},"Get-Content",[201,1995,215],{"class":214},[201,1997,1888],{"class":207},[201,1999,1193],{"class":214},[201,2001,2002],{"class":207},"Raw ",[201,2004,1097],{"class":214},[201,2006,2007],{"class":210}," ConvertFrom-Json",[201,2009,215],{"class":214},[201,2011,2012],{"class":207},"AsHashtable)\n",[201,2014,2016,2019,2022,2024,2026,2028,2030,2033,2035,2037,2040,2042],{"class":203,"line":2015},151,[201,2017,2018],{"class":210},"Write-Host",[201,2020,2021],{"class":221}," \"Loaded ",[201,2023,1384],{"class":214},[201,2025,595],{"class":221},[201,2027,1914],{"class":207},[201,2029,1391],{"class":221},[201,2031,2032],{"class":221}," policies; baseline has ",[201,2034,1384],{"class":214},[201,2036,595],{"class":221},[201,2038,2039],{"class":207},"$baseline.Count",[201,2041,1391],{"class":221},[201,2043,2044],{"class":221},".\"\n",[201,2046,2048],{"class":203,"line":2047},152,[201,2049,628],{"emptyLinePlaceholder":627},[201,2051,2053,2056,2058,2060],{"class":203,"line":2052},153,[201,2054,2055],{"class":207},"$baselineById ",[201,2057,740],{"class":214},[201,2059,831],{"class":214},[201,2061,1586],{"class":207},[201,2063,2065,2068,2071,2073],{"class":203,"line":2064},154,[201,2066,2067],{"class":214},"foreach",[201,2069,2070],{"class":207}," ($item ",[201,2072,1091],{"class":214},[201,2074,2075],{"class":207}," $baseline) {\n",[201,2077,2079,2082,2084],{"class":203,"line":2078},155,[201,2080,2081],{"class":207},"    $baselineById[$item.Id] ",[201,2083,740],{"class":214},[201,2085,2086],{"class":207}," $item\n",[201,2088,2090],{"class":203,"line":2089},156,[201,2091,809],{"class":207},[201,2093,2095,2098,2100,2102],{"class":203,"line":2094},157,[201,2096,2097],{"class":207},"$currentById ",[201,2099,740],{"class":214},[201,2101,831],{"class":214},[201,2103,1586],{"class":207},[201,2105,2107,2109,2111,2113],{"class":203,"line":2106},158,[201,2108,2067],{"class":214},[201,2110,2070],{"class":207},[201,2112,1091],{"class":214},[201,2114,2115],{"class":207}," $current) {\n",[201,2117,2119,2122,2124],{"class":203,"line":2118},159,[201,2120,2121],{"class":207},"    $currentById[$item.Id] ",[201,2123,740],{"class":214},[201,2125,2086],{"class":207},[201,2127,2129],{"class":203,"line":2128},160,[201,2130,809],{"class":207},[201,2132,2134],{"class":203,"line":2133},161,[201,2135,628],{"emptyLinePlaceholder":627},[201,2137,2139,2142,2144,2146,2149,2151,2153],{"class":203,"line":2138},162,[201,2140,2141],{"class":207},"$drift ",[201,2143,740],{"class":214},[201,2145,973],{"class":207},[201,2147,2148],{"class":214},"System.Collections.Generic.List",[201,2150,568],{"class":207},[201,2152,1617],{"class":214},[201,2154,2155],{"class":207},"]]::new()\n",[201,2157,2159],{"class":203,"line":2158},163,[201,2160,628],{"emptyLinePlaceholder":627},[201,2162,2164,2166,2169],{"class":203,"line":2163},164,[201,2165,867],{"class":214},[201,2167,2168],{"class":870}," Add-Drift",[201,2170,874],{"class":207},[201,2172,2174,2176],{"class":203,"line":2173},165,[201,2175,880],{"class":214},[201,2177,583],{"class":207},[201,2179,2181,2183,2185,2188],{"class":203,"line":2180},166,[201,2182,896],{"class":207},[201,2184,111],{"class":214},[201,2186,2187],{"class":207},"]$PolicyName",[201,2189,621],{"class":214},[201,2191,2193,2195,2197,2200],{"class":203,"line":2192},167,[201,2194,896],{"class":207},[201,2196,111],{"class":214},[201,2198,2199],{"class":207},"]$Change",[201,2201,621],{"class":214},[201,2203,2205,2207,2209,2212],{"class":203,"line":2204},168,[201,2206,896],{"class":207},[201,2208,111],{"class":214},[201,2210,2211],{"class":207},"]$Setting",[201,2213,621],{"class":214},[201,2215,2217,2219,2221],{"class":203,"line":2216},169,[201,2218,896],{"class":207},[201,2220,111],{"class":214},[201,2222,2223],{"class":207},"]$Detail\n",[201,2225,2227],{"class":203,"line":2226},170,[201,2228,920],{"class":207},[201,2230,2232],{"class":203,"line":2231},171,[201,2233,628],{"emptyLinePlaceholder":627},[201,2235,2237,2240,2242,2244,2246],{"class":203,"line":2236},172,[201,2238,2239],{"class":207},"    $drift.Add([",[201,2241,1617],{"class":214},[201,2243,1447],{"class":207},[201,2245,1305],{"class":214},[201,2247,1624],{"class":207},[201,2249,2251,2254,2256],{"class":203,"line":2250},173,[201,2252,2253],{"class":207},"        PolicyName ",[201,2255,740],{"class":214},[201,2257,2258],{"class":207}," $PolicyName\n",[201,2260,2262,2265,2267],{"class":203,"line":2261},174,[201,2263,2264],{"class":207},"        Change     ",[201,2266,740],{"class":214},[201,2268,2269],{"class":207}," $Change\n",[201,2271,2273,2276,2278],{"class":203,"line":2272},175,[201,2274,2275],{"class":207},"        Setting    ",[201,2277,740],{"class":214},[201,2279,2280],{"class":207}," $Setting\n",[201,2282,2284,2287,2289],{"class":203,"line":2283},176,[201,2285,2286],{"class":207},"        Detail     ",[201,2288,740],{"class":214},[201,2290,2291],{"class":207}," $Detail\n",[201,2293,2295],{"class":203,"line":2294},177,[201,2296,2297],{"class":207},"    })\n",[201,2299,2301],{"class":203,"line":2300},178,[201,2302,809],{"class":207},[201,2304,2306],{"class":203,"line":2305},179,[201,2307,628],{"emptyLinePlaceholder":627},[201,2309,2311],{"class":203,"line":2310},180,[201,2312,2313],{"class":358},"# Policies that are new or changed since the baseline.\n",[201,2315,2317,2319,2321,2323],{"class":203,"line":2316},181,[201,2318,2067],{"class":214},[201,2320,1556],{"class":207},[201,2322,1091],{"class":214},[201,2324,2115],{"class":207},[201,2326,2328,2331,2333],{"class":203,"line":2327},182,[201,2329,2330],{"class":207},"    $match ",[201,2332,740],{"class":214},[201,2334,2335],{"class":207}," $baselineById[$policy.Id]\n",[201,2337,2339],{"class":203,"line":2338},183,[201,2340,628],{"emptyLinePlaceholder":627},[201,2342,2344,2346,2348,2350],{"class":203,"line":2343},184,[201,2345,931],{"class":214},[201,2347,752],{"class":207},[201,2349,755],{"class":214},[201,2351,2352],{"class":207}," $match) {\n",[201,2354,2356,2359,2361,2364,2366,2369,2372,2374,2377,2379,2381,2384,2387,2389,2391,2394,2396],{"class":203,"line":2355},185,[201,2357,2358],{"class":210},"        Add-Drift",[201,2360,215],{"class":214},[201,2362,2363],{"class":207},"PolicyName $policy.DisplayName ",[201,2365,1193],{"class":214},[201,2367,2368],{"class":207},"Change ",[201,2370,2371],{"class":221},"'Added'",[201,2373,215],{"class":214},[201,2375,2376],{"class":207},"Setting ",[201,2378,1603],{"class":221},[201,2380,215],{"class":214},[201,2382,2383],{"class":207},"Detail ",[201,2385,2386],{"class":221},"\"Not in the baseline. Last modified ",[201,2388,1384],{"class":214},[201,2390,595],{"class":221},[201,2392,2393],{"class":207},"$policy.ModifiedDateTime",[201,2395,1391],{"class":221},[201,2397,2044],{"class":221},[201,2399,2401],{"class":203,"line":2400},186,[201,2402,2403],{"class":214},"        continue\n",[201,2405,2407],{"class":203,"line":2406},187,[201,2408,954],{"class":207},[201,2410,2412],{"class":203,"line":2411},188,[201,2413,628],{"emptyLinePlaceholder":627},[201,2415,2417,2420,2422,2424,2426,2429,2432,2434,2437,2439,2441,2443],{"class":203,"line":2416},189,[201,2418,2419],{"class":207},"    $paths ",[201,2421,740],{"class":214},[201,2423,752],{"class":207},[201,2425,1305],{"class":214},[201,2427,2428],{"class":207},"($policy.Settings.Keys) ",[201,2430,2431],{"class":214},"+",[201,2433,831],{"class":214},[201,2435,2436],{"class":207},"($match.Settings.Keys)) ",[201,2438,1097],{"class":214},[201,2440,1100],{"class":210},[201,2442,215],{"class":214},[201,2444,2445],{"class":207},"Unique\n",[201,2447,2449],{"class":203,"line":2448},190,[201,2450,628],{"emptyLinePlaceholder":627},[201,2452,2454,2457,2460,2462],{"class":203,"line":2453},191,[201,2455,2456],{"class":214},"    foreach",[201,2458,2459],{"class":207}," ($path ",[201,2461,1091],{"class":214},[201,2463,2464],{"class":207}," $paths) {\n",[201,2466,2468,2471,2473],{"class":203,"line":2467},192,[201,2469,2470],{"class":207},"        $old ",[201,2472,740],{"class":214},[201,2474,2475],{"class":207}," $match.Settings[$path]\n",[201,2477,2479,2482,2484],{"class":203,"line":2478},193,[201,2480,2481],{"class":207},"        $new ",[201,2483,740],{"class":214},[201,2485,2486],{"class":207}," $policy.Settings[$path]\n",[201,2488,2490,2493,2495,2498,2500,2502,2504,2506,2508,2511,2513,2515,2517,2520],{"class":203,"line":2489},194,[201,2491,2492],{"class":207},"        $isList ",[201,2494,740],{"class":214},[201,2496,2497],{"class":207}," ($old ",[201,2499,970],{"class":214},[201,2501,973],{"class":207},[201,2503,1235],{"class":214},[201,2505,1020],{"class":207},[201,2507,1240],{"class":214},[201,2509,2510],{"class":207}," $old ",[201,2512,1246],{"class":214},[201,2514,973],{"class":207},[201,2516,111],{"class":214},[201,2518,2519],{"class":207},"]) ",[201,2521,2522],{"class":214},"-or\n",[201,2524,2526,2529,2531,2533,2535,2537,2539,2542,2544,2546,2548],{"class":203,"line":2525},195,[201,2527,2528],{"class":207},"            ($new ",[201,2530,970],{"class":214},[201,2532,973],{"class":207},[201,2534,1235],{"class":214},[201,2536,1020],{"class":207},[201,2538,1240],{"class":214},[201,2540,2541],{"class":207}," $new ",[201,2543,1246],{"class":214},[201,2545,973],{"class":207},[201,2547,111],{"class":214},[201,2549,2550],{"class":207},"])\n",[201,2552,2554],{"class":203,"line":2553},196,[201,2555,628],{"emptyLinePlaceholder":627},[201,2557,2559,2561],{"class":203,"line":2558},197,[201,2560,990],{"class":214},[201,2562,2563],{"class":207}," ($isList) {\n",[201,2565,2567,2570,2572,2574,2576],{"class":203,"line":2566},198,[201,2568,2569],{"class":207},"            $oldItems ",[201,2571,740],{"class":214},[201,2573,1753],{"class":210},[201,2575,215],{"class":214},[201,2577,2578],{"class":207},"Value $old\n",[201,2580,2582,2585,2587,2589,2591],{"class":203,"line":2581},199,[201,2583,2584],{"class":207},"            $newItems ",[201,2586,740],{"class":214},[201,2588,1753],{"class":210},[201,2590,215],{"class":214},[201,2592,2593],{"class":207},"Value $new\n",[201,2595,2597,2600,2603,2605,2608,2610,2612,2615,2617,2620],{"class":203,"line":2596},200,[201,2598,2599],{"class":214},"            foreach",[201,2601,2602],{"class":207}," ($value ",[201,2604,1091],{"class":214},[201,2606,2607],{"class":207}," ($newItems ",[201,2609,1097],{"class":214},[201,2611,1313],{"class":210},[201,2613,2614],{"class":207}," { $oldItems ",[201,2616,779],{"class":214},[201,2618,2619],{"class":210}," $_",[201,2621,2622],{"class":207}," })) {\n",[201,2624,2626,2629,2631,2633,2635,2637,2640,2642,2645,2647],{"class":203,"line":2625},201,[201,2627,2628],{"class":210},"                Add-Drift",[201,2630,215],{"class":214},[201,2632,2363],{"class":207},[201,2634,1193],{"class":214},[201,2636,2368],{"class":207},[201,2638,2639],{"class":221},"'Value added'",[201,2641,215],{"class":214},[201,2643,2644],{"class":207},"Setting $path ",[201,2646,1193],{"class":214},[201,2648,2649],{"class":207},"Detail $value\n",[201,2651,2653],{"class":203,"line":2652},202,[201,2654,1140],{"class":207},[201,2656,2658,2660,2662,2664,2667,2669,2671,2674,2676,2678],{"class":203,"line":2657},203,[201,2659,2599],{"class":214},[201,2661,2602],{"class":207},[201,2663,1091],{"class":214},[201,2665,2666],{"class":207}," ($oldItems ",[201,2668,1097],{"class":214},[201,2670,1313],{"class":210},[201,2672,2673],{"class":207}," { $newItems ",[201,2675,779],{"class":214},[201,2677,2619],{"class":210},[201,2679,2622],{"class":207},[201,2681,2683,2685,2687,2689,2691,2693,2696,2698,2700,2702],{"class":203,"line":2682},204,[201,2684,2628],{"class":210},[201,2686,215],{"class":214},[201,2688,2363],{"class":207},[201,2690,1193],{"class":214},[201,2692,2368],{"class":207},[201,2694,2695],{"class":221},"'Value removed'",[201,2697,215],{"class":214},[201,2699,2644],{"class":207},[201,2701,1193],{"class":214},[201,2703,2649],{"class":207},[201,2705,2707],{"class":203,"line":2706},205,[201,2708,1140],{"class":207},[201,2710,2712,2715,2718,2721,2723,2726,2729,2731,2733],{"class":203,"line":2711},206,[201,2713,2714],{"class":207},"        } ",[201,2716,2717],{"class":214},"elseif",[201,2719,2720],{"class":207}," ([",[201,2722,111],{"class":214},[201,2724,2725],{"class":207},"]$old ",[201,2727,2728],{"class":214},"-cne",[201,2730,973],{"class":207},[201,2732,111],{"class":214},[201,2734,2735],{"class":207},"]$new) {\n",[201,2737,2739,2742,2744,2746,2748,2750,2752,2755,2758,2760,2762],{"class":203,"line":2738},207,[201,2740,2741],{"class":207},"            $oldText ",[201,2743,740],{"class":214},[201,2745,1151],{"class":214},[201,2747,752],{"class":207},[201,2749,936],{"class":210},[201,2751,939],{"class":214},[201,2753,2754],{"class":207}," $old) { ",[201,2756,2757],{"class":221},"'(not set)'",[201,2759,1168],{"class":207},[201,2761,1171],{"class":214},[201,2763,2764],{"class":207}," { $old }\n",[201,2766,2768,2771,2773,2775,2777,2779,2781,2784,2786,2788,2790],{"class":203,"line":2767},208,[201,2769,2770],{"class":207},"            $newText ",[201,2772,740],{"class":214},[201,2774,1151],{"class":214},[201,2776,752],{"class":207},[201,2778,936],{"class":210},[201,2780,939],{"class":214},[201,2782,2783],{"class":207}," $new) { ",[201,2785,2757],{"class":221},[201,2787,1168],{"class":207},[201,2789,1171],{"class":214},[201,2791,2792],{"class":207}," { $new }\n",[201,2794,2796,2799,2801,2803,2805,2807,2810,2812,2814,2816,2818,2821,2824,2827,2830],{"class":203,"line":2795},209,[201,2797,2798],{"class":210},"            Add-Drift",[201,2800,215],{"class":214},[201,2802,2363],{"class":207},[201,2804,1193],{"class":214},[201,2806,2368],{"class":207},[201,2808,2809],{"class":221},"'Setting changed'",[201,2811,215],{"class":214},[201,2813,2644],{"class":207},[201,2815,1193],{"class":214},[201,2817,2383],{"class":207},[201,2819,2820],{"class":221},"\"Baseline: ",[201,2822,2823],{"class":207},"$oldText",[201,2825,2826],{"class":221}," | Current: ",[201,2828,2829],{"class":207},"$newText",[201,2831,2832],{"class":221},"\"\n",[201,2834,2836],{"class":203,"line":2835},210,[201,2837,1074],{"class":207},[201,2839,2841],{"class":203,"line":2840},211,[201,2842,954],{"class":207},[201,2844,2846],{"class":203,"line":2845},212,[201,2847,809],{"class":207},[201,2849,2851],{"class":203,"line":2850},213,[201,2852,628],{"emptyLinePlaceholder":627},[201,2854,2856],{"class":203,"line":2855},214,[201,2857,2858],{"class":358},"# Policies that were in the baseline but have since been removed.\n",[201,2860,2862,2864,2866,2868],{"class":203,"line":2861},215,[201,2863,2067],{"class":214},[201,2865,2070],{"class":207},[201,2867,1091],{"class":214},[201,2869,2075],{"class":207},[201,2871,2873,2875,2877,2879],{"class":203,"line":2872},216,[201,2874,931],{"class":214},[201,2876,752],{"class":207},[201,2878,755],{"class":214},[201,2880,2881],{"class":207}," $currentById[$item.Id]) {\n",[201,2883,2885,2887,2889,2892,2894,2896,2899,2901,2903,2905,2907,2909],{"class":203,"line":2884},217,[201,2886,2358],{"class":210},[201,2888,215],{"class":214},[201,2890,2891],{"class":207},"PolicyName $item.DisplayName ",[201,2893,1193],{"class":214},[201,2895,2368],{"class":207},[201,2897,2898],{"class":221},"'Removed'",[201,2900,215],{"class":214},[201,2902,2376],{"class":207},[201,2904,1603],{"class":221},[201,2906,215],{"class":214},[201,2908,2383],{"class":207},[201,2910,2911],{"class":221},"'In the baseline but no longer in the tenant.'\n",[201,2913,2915],{"class":203,"line":2914},218,[201,2916,954],{"class":207},[201,2918,2920],{"class":203,"line":2919},219,[201,2921,809],{"class":207},[201,2923,2925],{"class":203,"line":2924},220,[201,2926,628],{"emptyLinePlaceholder":627},[201,2928,2930],{"class":203,"line":2929},221,[201,2931,2932],{"class":358},"# Enabled, user-targeted policies that don't exclude the emergency access group.\n",[201,2934,2936,2938],{"class":203,"line":2935},222,[201,2937,749],{"class":214},[201,2939,2940],{"class":207}," ($EmergencyAccessGroupId) {\n",[201,2942,2944,2946,2948,2950,2953,2955,2957,2959,2961,2964,2966,2969],{"class":203,"line":2943},223,[201,2945,2456],{"class":214},[201,2947,1556],{"class":207},[201,2949,1091],{"class":214},[201,2951,2952],{"class":207}," ($current ",[201,2954,1097],{"class":214},[201,2956,1313],{"class":210},[201,2958,1316],{"class":207},[201,2960,1319],{"class":210},[201,2962,2963],{"class":207},".State ",[201,2965,767],{"class":214},[201,2967,2968],{"class":221}," 'enabled'",[201,2970,2622],{"class":207},[201,2972,2974,2977,2979,2981,2984,2986,2988,2990,2992,2995,2998,3001,3003],{"class":203,"line":2973},224,[201,2975,2976],{"class":207},"        $targetsUsers ",[201,2978,740],{"class":214},[201,2980,831],{"class":214},[201,2982,2983],{"class":207},"($policy.Settings.Keys ",[201,2985,1097],{"class":214},[201,2987,1313],{"class":210},[201,2989,1316],{"class":207},[201,2991,1319],{"class":210},[201,2993,2994],{"class":214}," -like",[201,2996,2997],{"class":221}," 'conditions.users.include*'",[201,2999,3000],{"class":207}," }).Count ",[201,3002,1332],{"class":214},[201,3004,3005],{"class":210}," 0\n",[201,3007,3009,3012,3014,3016,3018,3021,3024],{"class":203,"line":3008},225,[201,3010,3011],{"class":207},"        $excluded ",[201,3013,740],{"class":214},[201,3015,1753],{"class":210},[201,3017,215],{"class":214},[201,3019,3020],{"class":207},"Value $policy.Settings[",[201,3022,3023],{"class":221},"'conditions.users.excludeGroups'",[201,3025,1035],{"class":207},[201,3027,3029,3031,3034,3036,3039,3041],{"class":203,"line":3028},226,[201,3030,990],{"class":214},[201,3032,3033],{"class":207}," ($targetsUsers ",[201,3035,1240],{"class":214},[201,3037,3038],{"class":207}," $excluded ",[201,3040,779],{"class":214},[201,3042,3043],{"class":207}," $EmergencyAccessGroupId) {\n",[201,3045,3047,3049,3051,3053,3055,3057,3060,3062,3064,3066,3068,3070,3073,3076],{"class":203,"line":3046},227,[201,3048,2798],{"class":210},[201,3050,215],{"class":214},[201,3052,2363],{"class":207},[201,3054,1193],{"class":214},[201,3056,2368],{"class":207},[201,3058,3059],{"class":221},"'Missing exclusion'",[201,3061,215],{"class":214},[201,3063,2376],{"class":207},[201,3065,3023],{"class":221},[201,3067,215],{"class":214},[201,3069,2383],{"class":207},[201,3071,3072],{"class":221},"\"Enabled policy does not exclude emergency access group ",[201,3074,3075],{"class":207},"$EmergencyAccessGroupId",[201,3077,2044],{"class":221},[201,3079,3081],{"class":203,"line":3080},228,[201,3082,1074],{"class":207},[201,3084,3086],{"class":203,"line":3085},229,[201,3087,954],{"class":207},[201,3089,3091],{"class":203,"line":3090},230,[201,3092,809],{"class":207},[201,3094,3096],{"class":203,"line":3095},231,[201,3097,628],{"emptyLinePlaceholder":627},[201,3099,3101,3103,3106,3108,3110],{"class":203,"line":3100},232,[201,3102,749],{"class":214},[201,3104,3105],{"class":207}," ($drift.Count ",[201,3107,767],{"class":214},[201,3109,1278],{"class":210},[201,3111,1002],{"class":207},[201,3113,3115,3117,3120,3122,3124,3126,3128],{"class":203,"line":3114},233,[201,3116,1899],{"class":210},[201,3118,3119],{"class":221}," \"No drift detected across ",[201,3121,1384],{"class":214},[201,3123,595],{"class":221},[201,3125,1914],{"class":207},[201,3127,1391],{"class":221},[201,3129,3130],{"class":221}," Conditional Access policies.\"\n",[201,3132,3134,3137,3139],{"class":203,"line":3133},234,[201,3135,3136],{"class":207},"} ",[201,3138,1171],{"class":214},[201,3140,874],{"class":207},[201,3142,3144,3147,3150,3152,3154,3157,3159],{"class":203,"line":3143},235,[201,3145,3146],{"class":210},"    Write-Warning",[201,3148,3149],{"class":221}," \"",[201,3151,1384],{"class":214},[201,3153,595],{"class":221},[201,3155,3156],{"class":207},"$drift.Count",[201,3158,1391],{"class":221},[201,3160,3161],{"class":221}," drift item(s) detected.\"\n",[201,3163,3165],{"class":203,"line":3164},236,[201,3166,3167],{"class":207},"    $drift\n",[201,3169,3171],{"class":203,"line":3170},237,[201,3172,628],{"emptyLinePlaceholder":627},[201,3174,3176,3178],{"class":203,"line":3175},238,[201,3177,931],{"class":214},[201,3179,3180],{"class":207}," ($OutputPath) {\n",[201,3182,3184,3187,3189,3192,3194,3197,3199,3202,3204],{"class":203,"line":3183},239,[201,3185,3186],{"class":207},"        $drift ",[201,3188,1097],{"class":214},[201,3190,3191],{"class":210}," Export-Csv",[201,3193,215],{"class":214},[201,3195,3196],{"class":207},"Path $OutputPath ",[201,3198,1193],{"class":214},[201,3200,3201],{"class":207},"NoTypeInformation ",[201,3203,1193],{"class":214},[201,3205,1893],{"class":207},[201,3207,3209,3212,3215,3218],{"class":203,"line":3208},240,[201,3210,3211],{"class":210},"        Write-Host",[201,3213,3214],{"class":221}," \"Drift report written to ",[201,3216,3217],{"class":207},"$OutputPath",[201,3219,2044],{"class":221},[201,3221,3223],{"class":203,"line":3222},241,[201,3224,954],{"class":207},[201,3226,3228],{"class":203,"line":3227},242,[201,3229,628],{"emptyLinePlaceholder":627},[201,3231,3233,3235],{"class":203,"line":3232},243,[201,3234,931],{"class":214},[201,3236,3237],{"class":207}," ($FailOnDrift) {\n",[201,3239,3241,3244],{"class":203,"line":3240},244,[201,3242,3243],{"class":214},"        exit",[201,3245,3246],{"class":210}," 1\n",[201,3248,3250],{"class":203,"line":3249},245,[201,3251,954],{"class":207},[201,3253,3255],{"class":203,"line":3254},246,[201,3256,809],{"class":207},[29,3258,3260],{"id":3259},"notes","Notes",[34,3262,3263,3284,3294,3300,3317,3339,3349,3366,3372],{},[37,3264,3265,3272,3273,3276,3277,3280,3281,3283],{},[3266,3267,3268,3269,169],"strong",{},"Why raw REST instead of ",[15,3270,3271],{},"Get-MgIdentityConditionalAccessPolicy"," Serializing the SDK's model objects with ",[15,3274,3275],{},"ConvertTo-Json"," ties the baseline's shape to the SDK version (a module update can add or rename properties and show up as drift on every policy), and a single ",[15,3278,3279],{},"ConvertTo-Json -Depth"," value silently truncates anything nested deeper. The script reads the documented v1.0 JSON through ",[15,3282,57],{}," and compares flattened paths, so neither problem applies.",[37,3285,3286,3289,3290,3293],{},[3266,3287,3288],{},"Reordering is not drift."," Graph doesn't promise a stable order for lists such as ",[15,3291,3292],{},"excludeGroups",", so the script sorts every list before comparing, and reports list changes as individual values added or removed.",[37,3295,3296,3299],{},[3266,3297,3298],{},"Authentication strengths are reduced to their ID and name."," Microsoft updates the built-in authentication strengths when new methods become available, and the policy response can expand the strength's allowed combinations. Comparing those would report drift nobody made.",[37,3301,3302,3305,3306,3309,3310,3313,3314,169],{},[3266,3303,3304],{},"Microsoft-managed policies change on their own."," Microsoft creates and updates these policies (they show ",[3266,3307,3308],{},"Microsoft"," in the Created by column) and automatically adds newly eligible users, groups, or workloads to their scope, so expect them in the report. Microsoft documents an audit query for its own changes, which needs ",[15,3311,3312],{},"AuditLog.Read.All",": ",[15,3315,3316],{},"GET https:\u002F\u002Fgraph.microsoft.com\u002Fv1.0\u002FauditLogs\u002FdirectoryAudits?$filter=initiatedBy\u002Fapp\u002FdisplayName eq 'Microsoft Managed Policy Manager' and category eq 'Policy'",[37,3318,3319,3322,3323,3326,3327,3330,3331,3334,3335,3338],{},[3266,3320,3321],{},"Who made a change."," The script finds what changed; the audit log says who. In the Entra admin center, open ",[3266,3324,3325],{},"Monitoring & health"," > ",[3266,3328,3329],{},"Audit logs"," and set ",[3266,3332,3333],{},"Service"," to ",[3266,3336,3337],{},"Conditional Access"," (Reports Reader is enough there).",[37,3340,3341,3344,3345,3348],{},[3266,3342,3343],{},"The emergency access check."," Microsoft recommends excluding emergency access accounts from Conditional Access policies that block or restrict sign-in, and says report-only policies don't need the exclusion. That's why the check only looks at ",[15,3346,3347],{},"enabled"," policies, and skips workload-identity policies that don't target users.",[37,3350,3351,3354,3355,3357,3358,3361,3362,3365],{},[3266,3352,3353],{},"Scheduling."," Grant ",[15,3356,64],{}," as an application permission and authenticate with a certificate or a managed identity, not a client secret stored in a script. With ",[15,3359,3360],{},"-FailOnDrift",", ",[15,3363,3364],{},"pwsh -File"," returns exit code 1 on drift, which Task Scheduler, Azure Automation, or a CI pipeline can alert on.",[37,3367,3368,3371],{},[3266,3369,3370],{},"Treat the baseline like security configuration."," Store it in source control or a controlled share, and re-snapshot deliberately after a reviewed change, never automatically. A baseline that refreshes itself on every run hides exactly the drift you're looking for.",[37,3373,3374],{},"This audits policy configuration, not sign-in outcomes. Pair it with the sign-in logs or the What If tool when you need to know how a policy actually behaved for a given user.",[29,3376,3378],{"id":3377},"source","Source",[34,3380,3381,3386,3395,3402,3409,3416],{},[37,3382,3383,3385],{},[23,3384,26],{"href":25},": the policy baseline this script audits.",[37,3387,3388,3394],{},[23,3389,3393],{"href":3390,"rel":3391},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fgraph\u002Fapi\u002Fconditionalaccessroot-list-policies?view=graph-rest-1.0",[3392],"nofollow","List Conditional Access policies (Microsoft Graph v1.0)",": permissions and supported roles.",[37,3396,3397],{},[23,3398,3401],{"href":3399,"rel":3400},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fgraph\u002Fapi\u002Fresources\u002Fconditionalaccesspolicy?view=graph-rest-1.0",[3392],"conditionalAccessPolicy resource type",[37,3403,3404],{},[23,3405,3408],{"href":3406,"rel":3407},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fentra\u002Fidentity\u002Fauthentication\u002Fconcept-authentication-strengths",[3392],"Overview of Conditional Access authentication strengths",[37,3410,3411],{},[23,3412,3415],{"href":3413,"rel":3414},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fentra\u002Fidentity\u002Fconditional-access\u002Fmanaged-policies",[3392],"Microsoft-managed Conditional Access policies",[37,3417,3418],{},[23,3419,3422],{"href":3420,"rel":3421},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fentra\u002Fidentity\u002Frole-based-access-control\u002Fsecurity-emergency-access",[3392],"Manage emergency access admin accounts",[3424,3425,3426],"style",{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":197,"searchDepth":311,"depth":311,"links":3428},[3429,3430,3431,3432,3433,3434],{"id":31,"depth":311,"text":32},{"id":74,"depth":311,"text":75},{"id":186,"depth":311,"text":187},{"id":347,"depth":311,"text":348},{"id":3259,"depth":311,"text":3260},{"id":3377,"depth":311,"text":3378},"techcolumnist",[3437,3438],"ps","scripts","2025-08-06T14:00:00Z","A PowerShell script that snapshots Entra ID Conditional Access policies, reports setting-level drift against a baseline, and flags missing break-glass exclusions.","md",false,null,{},"\u002Fblog\u002F2025\u002F08\u002F06\u002Fpowershell-entra-id-audit-conditional-access-policy-drift",{"title":6,"description":3440},[3435],"blog\u002F2025\u002F08\u002F06\u002Fpowershell-entra-id-audit-conditional-access-policy-drift",[196,3450],"entra-id","\u002F2025\u002F08\u002F06\u002Fpowershell-entra-id-audit-conditional-access-policy-drift\u002F","PeNk_OWFcY_N-7sXFl5jKm5AkTWCHOSYLWmmZE32-H0",{"title":3454,"description":3455,"date":3456,"url":3457,"categories":3458,"tags":3460,"image":3443,"readingTime":375,"canonical":3435,"sites":3464,"series":3443,"seriesOrder":3443},"PowerShell: NetApp – Discover Every Volume Over 80 Percent Capacity","Sweep every ONTAP cluster you manage through the ONTAP REST API from PowerShell and report volumes above a capacity threshold, with a read-only login.","2025-08-13T14:00:00Z","\u002F2025\u002F08\u002F13\u002Fpowershell-netapp-discover-every-volume-over-80-percent-capacity\u002F",[3437,3438,3459],"dotps",[196,3461,3462,3463],"netapp","ontap","discovery",[3435],{"title":3466,"description":3467,"date":3468,"url":3469,"categories":3470,"tags":3472,"image":3473,"readingTime":401,"canonical":3474,"sites":3475,"series":3476,"seriesOrder":413},"Service Portfolios & Productization: Defining, marketing, and managing IT services","Ten weeks of rethinking IT not as a cost center, but as a strategic driver.","2025-07-28T23:49:15Z","\u002F2025\u002F07\u002F28\u002Fservice-portfolios-productization-defining-marketing-and-managing-it-services\u002F",[3471],"business",[],"\u002Fuploads\u002F2025\u002F07\u002FChatGPT-Image-Jul-28-2025-07_40_34-PM.png","lasswell",[3474,3435],"itsm-in-practice",[3478,3487,3497],{"title":3479,"description":3480,"date":3481,"url":3482,"categories":3483,"tags":3484,"image":3443,"readingTime":369,"canonical":3435,"sites":3486,"series":3443,"seriesOrder":3443},"PowerShell: Intune – Bulk Assign App Protection Policies by Group","A Microsoft Graph PowerShell script that adds Entra ID groups to an Intune App Protection Policy through the v1.0 assign action without dropping existing assignments.","2025-04-17T14:00:00Z","\u002F2025\u002F04\u002F17\u002Fpowershell-intune-bulk-assign-app-protection-policies-by-group\u002F",[3437,3438],[196,3485,3450],"intune",[3435],{"title":3488,"description":3489,"date":3490,"url":3491,"categories":3492,"tags":3493,"image":3443,"readingTime":383,"canonical":3435,"sites":3496,"series":3443,"seriesOrder":3443},"PowerShell: Active Directory – Report Group Membership Sprawl","Rank AD security groups by nesting depth, transitive member count, ownership and staleness for an access review, plus a per-user Kerberos token size estimate.","2025-12-03T14:00:00Z","\u002F2025\u002F12\u002F03\u002Fpowershell-active-directory-report-group-membership-sprawl\u002F",[3437,3438],[196,3494,3495],"active-directory","reporting",[3435],{"title":3498,"description":3499,"date":3500,"url":3501,"categories":3502,"tags":3503,"image":3443,"readingTime":375,"canonical":3435,"sites":3505,"series":3443,"seriesOrder":3443},"PowerShell: Windows Server – Disable SMBv1 Fleet-Wide and Verify","A script that audits SMBv1 access (event 3000), disables the SMBv1 server and optional feature across Windows servers, and reports which ones still need a restart.","2025-11-26T14:00:00Z","\u002F2025\u002F11\u002F26\u002Fpowershell-windows-server-disable-smbv1-fleet-wide-and-verify-it-stuck\u002F",[3437,3438],[196,3504],"windows",[3435],{"doc":3443,"posts":3507},[],1790052513101]