Private/Baseline/Merge-PolicyBaselines.ps1
|
function Merge-PolicyBaselines { <# .SYNOPSIS Merge ALZ and MCSB baselines with deduplication. .DESCRIPTION Combines multiple baseline sources, deduplicating by PolicyDefinitionId. Tracks sources in BaselineSources field (comma-separated). .PARAMETER AlzBaseline Array of ALZ baseline policies. .PARAMETER McsbBaseline Array of MCSB baseline policies. .EXAMPLE $mergedBaseline = Merge-PolicyBaselines -AlzBaseline $alz -McsbBaseline $mcsb .OUTPUTS Array of deduplicated baseline policy objects #> [CmdletBinding()] param( [object[]]$AlzBaseline = @(), [object[]]$McsbBaseline = @() ) $baselineIndex = @{} # Add MCSB first foreach ($b in $McsbBaseline) { $baselineIndex[$b.PolicyDefinitionId] = [pscustomobject]@{ PolicyDefinitionId = $b.PolicyDefinitionId PolicyDisplayName = $b.PolicyDisplayName PolicyType = $b.PolicyType Category = $b.Category Version = $b.Version BaselineSources = $b.BaselineSources Effect = if ($b.Effect) { $b.Effect } else { "N/A" } } } # Merge ALZ (deduplicate) foreach ($b in $AlzBaseline) { if ($baselineIndex.ContainsKey($b.PolicyDefinitionId)) { # Already exists - merge sources $existing = $baselineIndex[$b.PolicyDefinitionId] $sources = ($existing.BaselineSources -split ',\s*') + $b.BaselineSources $existing.BaselineSources = (($sources | Sort-Object -Unique) -join ', ') # Fill missing metadata from ALZ if (-not $existing.Version -and $b.Version) { $existing.Version = $b.Version } if (-not $existing.Effect -and $b.Effect) { $existing.Effect = $b.Effect } } else { # New policy from ALZ $baselineIndex[$b.PolicyDefinitionId] = [pscustomobject]@{ PolicyDefinitionId = $b.PolicyDefinitionId PolicyDisplayName = $b.PolicyDisplayName PolicyType = $b.PolicyType Category = $b.Category Version = $b.Version BaselineSources = $b.BaselineSources Effect = if ($b.Effect) { $b.Effect } else { "N/A" } } } } return $baselineIndex.Values } |