Private/Resolve-AACPolicySetMember.ps1
|
function Resolve-AACPolicySetMember { <# .SYNOPSIS The member policies of an assigned initiative, each with the value every one of its parameters ends up with - through the initiative's parameters and the assignment's - and its effect. .DESCRIPTION -Member are the initiative's properties.policyDefinitions (policyDefinitionId, policyDefinitionReferenceId, parameters, groupNames). -SetParameter are the initiative's parameter definitions, -Assigned the assignment's parameters ({ name: { value } }), -Override the assignment's overrides. -Definition maps a definition's lower-case ID to its definition; parameters, rule, displayName, name, policyType and category (or metadata.category) are read from it whatever their case. A member's parameter takes, in this order: [parameters('x')] in the initiative the assignment's x (Assigned), else x's default in the initiative (Initiative default), else Not set another [expression] left as written (Expression) a value in the initiative that value (Initiative) nothing in the initiative the policy's default (Policy default), else Not set The effect is the rule's then.effect, its [parameters()] resolved the same way - or the assignment's policyEffect override that selects the member (Override). Returns one hashtable per member: ReferenceId, DefinitionId, Definition (or $null when it couldn't be read), Groups, Effect, EffectSource, Values (parameter name -> effective value, for Get-AACPolicyResourceType) and Parameters (Name, DisplayName, Type, DefaultValue, HasDefault, SetValue, SetParameter, Value, Source, AllowedValues). #> [CmdletBinding()] [OutputType([hashtable])] param( [AllowNull()] [AllowEmptyCollection()] [object[]] $Member, [AllowNull()] $SetParameter, [AllowNull()] $Assigned, [AllowNull()] [AllowEmptyCollection()] [object[]] $Override, [System.Collections.IDictionary] $Definition = @{} ) $get = { param($Map, [string] $Name) if ($Map -isnot [System.Collections.IDictionary]) { return } foreach ($k in $Map.Keys) { if ($k -eq $Name) { return $Map[$k] } } } $has = { param($Map, [string] $Name) if ($Map -isnot [System.Collections.IDictionary]) { return $false } foreach ($k in $Map.Keys) { if ($k -eq $Name) { return $true } } $false } $reference = "^\[parameters\('([^']+)'\)\]$" # The effect overrides: those with no selector apply to every member. $effectOverride = { param([string] $ReferenceId) foreach ($item in @($Override)) { if ([string](& $get $item 'kind') -ne 'policyEffect') { continue } $selectors = @(& $get $item 'selectors' | Where-Object { $_ -is [System.Collections.IDictionary] -and [string](& $get $_ 'kind') -eq 'policyDefinitionReferenceId' }) $selected = -not $selectors.Count foreach ($selector in $selectors) { if (& $has $selector 'in') { if (@(& $get $selector 'in') -contains $ReferenceId) { $selected = $true } } elseif (& $has $selector 'notIn') { if (@(& $get $selector 'notIn') -notcontains $ReferenceId) { $selected = $true } } } if ($selected) { return [string](& $get $item 'value') } } } foreach ($m in @($Member)) { if ($m -isnot [System.Collections.IDictionary]) { continue } $definitionId = [string](& $get $m 'policyDefinitionId') $referenceId = [string](& $get $m 'policyDefinitionReferenceId') $policy = $Definition[$definitionId.ToLowerInvariant()] $specs = & $get $policy 'parameters' $refs = & $get $m 'parameters' $values = [ordered]@{} $parameters = [System.Collections.Generic.List[object]]::new() $names = @(if ($specs -is [System.Collections.IDictionary]) { $specs.Keys } elseif ($refs -is [System.Collections.IDictionary]) { $refs.Keys }) foreach ($name in $names) { $spec = & $get $specs $name $entry = @{ Name = [string]$name; DisplayName = [string](& $get (& $get $spec 'metadata') 'displayName'); Type = [string](& $get $spec 'type') HasDefault = & $has $spec 'defaultValue'; DefaultValue = & $get $spec 'defaultValue'; AllowedValues = & $get $spec 'allowedValues' SetValue = $null; SetParameter = ''; Value = $null; Source = 'Not set' } if (& $has $refs $name) { $entry.SetValue = & $get (& $get $refs $name) 'value' if ($entry.SetValue -is [string] -and $entry.SetValue -match $reference) { $entry.SetParameter = $Matches[1] if (& $has $Assigned $entry.SetParameter) { $entry.Value = & $get (& $get $Assigned $entry.SetParameter) 'value'; $entry.Source = 'Assigned' } elseif (& $has (& $get $SetParameter $entry.SetParameter) 'defaultValue') { $entry.Value = & $get (& $get $SetParameter $entry.SetParameter) 'defaultValue'; $entry.Source = 'Initiative default' } } elseif ($entry.SetValue -is [string] -and $entry.SetValue.StartsWith('[') -and -not $entry.SetValue.StartsWith('[[')) { $entry.Value = $entry.SetValue; $entry.Source = 'Expression' } else { $entry.Value = $entry.SetValue; $entry.Source = 'Initiative' } } elseif ($entry.HasDefault) { $entry.Value = $entry.DefaultValue; $entry.Source = 'Policy default' } $values[[string]$name] = $entry.Value $parameters.Add($entry) } $effect = [string](& $get (& $get (& $get $policy 'rule') 'then') 'effect') $effectSource = 'Policy' if ($effect -match $reference) { $effectName = $Matches[1] $effect = [string](& $get $values $effectName) $effectSource = [string](@($parameters | Where-Object Name -EQ $effectName | ForEach-Object Source) | Select-Object -First 1) } $overridden = & $effectOverride $referenceId if ($overridden) { $effect = $overridden; $effectSource = 'Override' } @{ ReferenceId = $referenceId DefinitionId = $definitionId Definition = $policy Groups = @(& $get $m 'groupNames' | Where-Object { $_ }) Effect = $effect EffectSource = $effectSource Values = $values Parameters = $parameters.ToArray() } } } |