Private/Scanning/Expand-PolicySetMembers.ps1
|
function Expand-PolicySetMembers { <# .SYNOPSIS Expands a policy assignment into individual policy objects with resolved effects. .DESCRIPTION Takes a policy assignment and expands it into an array of individual policy definitions. Handles both policy sets (initiatives) and individual policy assignments. Resolves effect values from assignment parameters, policy parameters, or rule definitions. This function is critical for comparing assigned policies against baselines, as it normalizes all assignment types into individual policy objects. .PARAMETER Assignment The policy assignment object to expand. Must have PolicyDefinitionId property. .PARAMETER PolicyDefinitionCache Hashtable cache for policy definitions (prevents redundant API calls). .PARAMETER PolicySetDefinitionCache Hashtable cache for policy set definitions (prevents redundant API calls). .EXAMPLE $members = Expand-PolicySetMembers -Assignment $assignment ` -PolicyDefinitionCache $script:policyDefinitionCache ` -PolicySetDefinitionCache $script:policySetDefinitionCache Expands an assignment into individual policy objects with resolved effects. .OUTPUTS Array of PSCustomObject with properties: - PolicyDefinitionId: Full resource ID of the policy - PolicyDisplayName: Human-readable name of the policy - PolicyType: Type of policy (BuiltIn, Custom, etc.) - Version: Policy version from metadata - Effect: Resolved effect value (Audit, Deny, etc.) #> [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Assignment, [Parameter(Mandatory)] [hashtable]$PolicyDefinitionCache, [Parameter(Mandatory)] [hashtable]$PolicySetDefinitionCache ) $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 "Processing individual policy: $($policy.DisplayName)" $effectValue = Resolve-PolicyEffect -Ref $null ` -PolicyDefinition $policy ` -PolicyDisplayName $policy.DisplayName ` -PolicyDefinitionId $policy.Id return [PSCustomObject]@{ PolicyDefinitionId = $policy.Id PolicyDisplayName = $policy.DisplayName PolicyType = $policy.PolicyType Version = $policy.Metadata.version Effect = $effectValue Category = if ($policy.Metadata.category) { $policy.Metadata.category } else { "Uncategorized" } } } catch { Write-Warning "Failed to expand individual policy: $($Assignment.DisplayName) - $($_.Exception.Message)" return [PSCustomObject]@{ PolicyDefinitionId = $Assignment.PolicyDefinitionId PolicyDisplayName = "[Unresolved] $($Assignment.PolicyDefinitionId)" PolicyType = $null Version = $null Effect = "N/A" Category = "Uncategorized" } } } else { # Handle policy set (initiative) assignment try { $set = Get-PolicySetDefinitionCached -Id $Assignment.PolicyDefinitionId ` -Cache $PolicySetDefinitionCache Write-Debug "Expanding policy set: $($set.DisplayName) with $($set.PolicyDefinition.Count) members" } catch { Write-Warning "Cannot load policy set: $($Assignment.DisplayName) - $($_.Exception.Message)" return @() } # Expand all policy definitions in the set $members = foreach ($ref in $set.PolicyDefinition) { try { $pol = Get-PolicyDefinitionCached -PolicyDefinitionId $ref.PolicyDefinitionId ` -Cache $PolicyDefinitionCache $effectValue = Resolve-PolicyEffect -Ref $ref ` -PolicyDefinition $pol ` -PolicyDisplayName $pol.DisplayName ` -PolicyDefinitionId $pol.Id [PSCustomObject]@{ PolicyDefinitionId = $pol.Id PolicyDisplayName = $pol.DisplayName PolicyType = $pol.PolicyType Version = $pol.Metadata.version Effect = $effectValue Category = if ($pol.Metadata.category) { $pol.Metadata.category } else { "Uncategorized" } } } catch { Write-Warning "Failed to get policy definition: $($ref.PolicyDefinitionId) - $($_.Exception.Message)" [PSCustomObject]@{ PolicyDefinitionId = $ref.PolicyDefinitionId PolicyDisplayName = "[Unresolved] $($ref.PolicyDefinitionId)" PolicyType = $null Version = $null Effect = "N/A" Category = "Uncategorized" } } } return $members } } |