Private/Scanning/Add-PolicyToAssignmentIndex.ps1
|
function Add-PolicyToAssignmentIndex { <# .SYNOPSIS Indexes a policy assignment for fast baseline matching lookups. .DESCRIPTION Expands a policy assignment and adds all member policies to three index structures: - ById: Fast lookup by full policy definition ID - ByNormName: Fast lookup by normalized policy name - Effects: Stores resolved effect values per policy This function builds the indexes used to determine which baseline policies are assigned in the tenant. It handles both policy sets and individual policies, with exclusion support. .PARAMETER Assignment The policy assignment object to index. Must have PolicyDefinitionId property. .PARAMETER ByIdIndex Hashtable for ID-based lookups. Keys are policy definition IDs, values are $true. .PARAMETER ByNormNameIndex Hashtable for name-based lookups. Keys are normalized policy names, values are $true. .PARAMETER EffectsIndex Hashtable storing effect values. Keys are policy IDs or normalized names, values are effect strings. .PARAMETER PolicyDefinitionCache Hashtable cache for policy definitions (prevents redundant API calls). .PARAMETER PolicySetDefinitionCache Hashtable cache for policy set definitions (prevents redundant API calls). .PARAMETER ExcludeList Optional array of assignment names/IDs to exclude from indexing. .EXAMPLE Add-PolicyToAssignmentIndex -Assignment $assignment ` -ByIdIndex $assignedById ` -ByNormNameIndex $assignedByNormName ` -EffectsIndex $assignedEffects ` -PolicyDefinitionCache $script:policyDefinitionCache ` -PolicySetDefinitionCache $script:policySetDefinitionCache Indexes a policy assignment for baseline matching. .OUTPUTS None. Modifies the provided index hashtables in place. #> [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Assignment, [Parameter(Mandatory)] [hashtable]$ByIdIndex, [Parameter(Mandatory)] [hashtable]$ByNormNameIndex, [Parameter(Mandatory)] [hashtable]$EffectsIndex, [Parameter(Mandatory)] [hashtable]$PolicyDefinitionCache, [Parameter(Mandatory)] [hashtable]$PolicySetDefinitionCache, [Parameter()] [string[]]$ExcludeList = @() ) $isIndividualPolicy = $Assignment.PolicyDefinitionId -like "*/policyDefinitions/*" -and $Assignment.PolicyDefinitionId -notlike "*/policySetDefinitions/*" if ($isIndividualPolicy) { # Handle individual policy assignment try { $policy = Get-PolicyDefinitionCached -PolicyDefinitionId $Assignment.PolicyDefinitionId ` -Cache $PolicyDefinitionCache Write-Debug "Individual policy detected for index: $($policy.DisplayName)" # Add to ID index $ByIdIndex[$policy.Id] = $true # Add to normalized name index $normName = Normalize-PolicyName $policy.DisplayName if ($normName) { $ByNormNameIndex[$normName] = $true Write-Debug " └─ Added to index: $normName" } # Resolve and store effect try { $effectValue = Resolve-PolicyEffect -Ref $null ` -PolicyDefinition $policy ` -PolicyDisplayName $policy.DisplayName ` -PolicyDefinitionId $policy.Id $EffectsIndex[$policy.Id] = $effectValue if ($normName) { $EffectsIndex[$normName] = $effectValue } } catch { Write-Debug " └─ Cannot resolve effect for individual policy" $EffectsIndex[$policy.Id] = "N/A" if ($normName) { $EffectsIndex[$normName] = "N/A" } } } catch { Write-Debug "Cannot load individual policy: $($Assignment.PolicyDefinitionId)" } return } # Handle policy set (initiative) assignment try { $set = Get-PolicySetDefinitionCached -Id $Assignment.PolicyDefinitionId ` -Cache $PolicySetDefinitionCache } catch { Write-Debug "Cannot load policy set: $($Assignment.PolicyDefinitionId)" return } # Check exclusion list if (Test-AssignmentExcluded -Assignment $Assignment -PolicySet $set -ExcludeList $ExcludeList) { Write-Debug "Excluded assignment: $($set.DisplayName)" return } # Index all member policies foreach ($ref in $set.PolicyDefinition) { try { $p = Get-PolicyDefinitionCached -PolicyDefinitionId $ref.PolicyDefinitionId ` -Cache $PolicyDefinitionCache } catch { $p = $null } $policyId = if ($p) { $p.Id } else { $ref.PolicyDefinitionId } $policyName = if ($p) { $p.DisplayName } else { "[Unknown] $policyId" } # Resolve effect value (from ref parameters, policy parameters, or rule) $effectValue = $null if ($ref.parameters -and $ref.parameters.effect -and $ref.parameters.effect.value) { $effectValue = $ref.parameters.effect.value } if (-not $effectValue -and $p) { if ($p.Parameter.effect -and $p.Parameter.effect.defaultValue) { $effectValue = $p.Parameter.effect.defaultValue } } if (-not $effectValue -and $p -and $p.PolicyRule -and $p.PolicyRule.then -and $p.PolicyRule.then.effect) { $rawEffect = $p.PolicyRule.then.effect if ($rawEffect -match "\[parameters\('(\w+)'\)\]") { $paramName = $Matches[1] if ($p.Parameter.$paramName -and $p.Parameter.$paramName.defaultValue) { $effectValue = $p.Parameter.$paramName.defaultValue } else { $effectValue = "Parametrized" } } else { $effectValue = $rawEffect } } if (-not $effectValue) { $effectValue = "N/A" } # Add to ID index if ($policyId) { $ByIdIndex[$policyId] = $true $EffectsIndex[$policyId] = $effectValue } # Add to normalized name index $nk = Normalize-PolicyName $policyName if ($nk) { $ByNormNameIndex[$nk] = $true $EffectsIndex[$nk] = $effectValue } } } |