Private/ConvertFrom-CaBaselineEntry.ps1
|
function ConvertFrom-CaBaselineEntry { <# .SYNOPSIS Rehydrates a stored baseline entry into the shape Compare-CaEffectiveControl reads .DESCRIPTION The reason this exists rather than a second, baseline-specific comparison: drift between a stored run and a fresh one is the same question as the difference between two worlds, and answering it with the same code means the two can never disagree about what counts as a change. Rehydrating a stored entry into an outcome-shaped object is cheaper than maintaining a parallel diff, and it is what makes a baseline comparison report the same vocabulary - added requirements, changed session controls, newly blocked - as a promotion diff. A missing property comes back as an empty collection rather than null, because the comparison indexes into all of them. That also makes the function tolerant of a baseline written by an older version of this module: a field added later reads as empty, and the comparison then reports it as an addition, which is exactly what it is. .PARAMETER Entry A stored entry, as written by ConvertTo-CaBaselineEntry and read back from JSON. .OUTPUTS PSCustomObject with the properties Compare-CaEffectiveControl expects. .EXAMPLE $stored = ConvertFrom-CaBaselineEntry -Entry $baseline.scenarios.'standard/office365/managed'.current Compare-CaEffectiveControl -From $stored -To $fresh.Current .NOTES Author: Jeffrey Stuhr Version: 0.3.0 Last Updated: 2026-08-17 #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [AllowNull()] [object]$Entry ) $sessionControls = [ordered]@{} $stored = Get-CaProperty -InputObject $Entry -Name 'sessionControls' if ($null -ne $stored) { $names = @() if ($stored -is [System.Collections.IDictionary]) { $names = @($stored.Keys) } elseif ($stored.PSObject) { $names = @($stored.PSObject.Properties | Select-Object -ExpandProperty Name) } foreach ($name in ($names | Sort-Object)) { $sessionControls[$name] = Get-CaProperty -InputObject $stored -Name $name } } return [PSCustomObject]@{ PSTypeName = 'CaOutcome.EffectiveControl' World = 'Baseline' Access = [string](Get-CaProperty -InputObject $Entry -Name 'access') IsEffectivelyBlocked = [bool](Get-CaProperty -InputObject $Entry -Name 'isEffectivelyBlocked') RequiredControls = @(Get-CaProperty -InputObject $Entry -Name 'requiredControls') BlockedBy = @(@(Get-CaProperty -InputObject $Entry -Name 'blockedBy') | Where-Object { $null -ne $_ } | ForEach-Object { [PSCustomObject]@{ PolicyId = Get-CaProperty -InputObject $_ -Name 'policyId' PolicyName = Get-CaProperty -InputObject $_ -Name 'policyName' } }) OptionalChoices = @(@(Get-CaProperty -InputObject $Entry -Name 'optionalChoices') | Where-Object { $null -ne $_ } | ForEach-Object { [PSCustomObject]@{ PolicyId = Get-CaProperty -InputObject $_ -Name 'policyId' PolicyName = Get-CaProperty -InputObject $_ -Name 'policyName' AnyOf = @(Get-CaProperty -InputObject $_ -Name 'anyOf') } }) UnsatisfiableRequirements = @(@(Get-CaProperty -InputObject $Entry -Name 'unsatisfiable') | Where-Object { $null -ne $_ } | ForEach-Object { [PSCustomObject]@{ PolicyId = Get-CaProperty -InputObject $_ -Name 'policyId' PolicyName = Get-CaProperty -InputObject $_ -Name 'policyName' Operator = Get-CaProperty -InputObject $_ -Name 'operator' Controls = @(Get-CaProperty -InputObject $_ -Name 'controls') Blockers = @(Get-CaProperty -InputObject $_ -Name 'blockers') Reasons = @(Get-CaProperty -InputObject $_ -Name 'reasons') } }) AuthenticationStrengths = @(@(Get-CaProperty -InputObject $Entry -Name 'strengths') | Where-Object { $null -ne $_ } | ForEach-Object { [PSCustomObject]@{ Control = Get-CaProperty -InputObject $_ -Name 'control' Id = Get-CaProperty -InputObject $_ -Name 'id' DisplayName = Get-CaProperty -InputObject $_ -Name 'displayName' PolicyType = Get-CaProperty -InputObject $_ -Name 'policyType' AllowedCombinations = @(Get-CaProperty -InputObject $_ ` -Name 'allowedCombinations') CombinationConfigurationCount = [int](Get-CaProperty -InputObject $_ ` -Name 'combinationConfigurationCount') } }) SessionControls = [PSCustomObject]$sessionControls SessionConflicts = @() AppliedPolicies = @(@(Get-CaProperty -InputObject $Entry -Name 'appliedPolicies') | Where-Object { $null -ne $_ } | ForEach-Object { [PSCustomObject]@{ Id = Get-CaProperty -InputObject $_ -Name 'id' DisplayName = Get-CaProperty -InputObject $_ -Name 'displayName' State = Get-CaProperty -InputObject $_ -Name 'state' } }) } } |