Public/Get-NSPConditionalAccessPlanSummary.ps1
|
function Get-NSPConditionalAccessPlanSummary { <# .SYNOPSIS One reviewable row per plan item: action, decision, match, and which fields would change. .DESCRIPTION Accepts a plan object or the path of a saved plan. Changes lists the canonical fields that differ from the live policy. Details are on the plan item's Differences property. For a promotion plan, Changes shows the state change and Notes the gate warnings; for a blocked or conflicting item, Notes says why. .EXAMPLE Get-NSPConditionalAccessPlanSummary -Plan $plan.Path | Format-Table -Wrap #> [CmdletBinding()] param( [Parameter(Mandatory)]$Plan ) if ($Plan -is [string]) { $Plan = Get-Content -LiteralPath $Plan -Raw | ConvertFrom-Json } foreach ($item in $Plan.Items) { $match = if ($item.LiveDisplayName) { $how = if ($item.Confidence) { " ($($item.Confidence)$(if ($null -ne $item.Score -and $item.Confidence -eq 'Similar') { " $($item.Score)" }))" } else { '' } "$($item.LiveDisplayName) [$($item.LiveState)]$how" } else { $null } [pscustomobject]@{ ItemId = $item.ItemId Action = $item.Action Decision = $item.Decision Target = if ($item.DisplayName) { $item.DisplayName } else { $item.ItemId } Match = $match Changes = if ($item.Kind -eq 'Promotion' -and $item.Action -eq 'PromoteState') { "state: $($item.LiveState) -> $($item.DesiredBody.state)" } elseif ($item.Kind -eq 'TenantSetting') { "Security Defaults: $($item.LiveState) -> $(if ($item.DesiredBody.isEnabled) { 'enabled' } else { 'disabled' })" } else { (@($item.Differences | ForEach-Object { $_.Field }) -join ', ') } DependsOn = (@($item.DependsOn) -join ', ') # Why an item cannot run, and anything an approver should weigh first. Notes = (@(@($item.Warnings | Where-Object { $_ }) + @(if ($item.Action -in 'PromotionBlocked', 'Conflict', 'BlockedPrerequisite') { $item.Reason })) -join ' | ') } } } |