Private/Resolve-BsiMapping.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS BSI mapping management — load, query, validate, update. .DESCRIPTION Loads the bsi-azure-mapping.json, resolves controls against catalog, detects orphans, and provides lookup functions. #> function Get-BsiMapping { param([Parameter(Mandatory)][string]$Path) if (-not (Test-Path -LiteralPath $Path)) { throw "Mapping file not found: $Path" } return Get-Content -Raw -Path $Path | ConvertFrom-Json } function Get-BsiMappingControls { param([Parameter(Mandatory)]$Mapping) return $Mapping.mappings } function Get-BsiMappingControlById { param( [Parameter(Mandatory)]$Mapping, [Parameter(Mandatory)][string]$ControlId ) return $Mapping.mappings | Where-Object { $_.controlId -eq $ControlId } | Select-Object -First 1 } function Resolve-BsiOrphans { <# .SYNOPSIS Finds mapping entries whose control IDs are not in the catalog. .OUTPUTS Array of orphaned control IDs. #> param( [Parameter(Mandatory)]$Mapping, [Parameter(Mandatory)]$CatalogControls ) $catalogIds = $CatalogControls | ForEach-Object { $_.id } return @($Mapping.mappings | Where-Object { $_.controlId -notlike "AZURE.*" -and $catalogIds -notcontains $_.controlId } | ForEach-Object { $_.controlId }) } function Resolve-BsiUncoveredControls { <# .SYNOPSIS Finds catalog controls not covered by the mapping. .OUTPUTS Array of uncovered control IDs. #> param( [Parameter(Mandatory)]$Mapping, [Parameter(Mandatory)]$CatalogControls ) $mappedIds = $Mapping.mappings | ForEach-Object { $_.controlId } $catalogIds = $CatalogControls | ForEach-Object { $_.id } return @($catalogIds | Where-Object { $mappedIds -notcontains $_ }) } function Update-BsiMappingTimestamp { param([Parameter(Mandatory)][string]$Path) $mapping = Get-BsiMapping -Path $Path $mapping.lastSynced = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ") $mapping | ConvertTo-Json -Depth 10 | Set-Content -Path $Path -Encoding UTF8 } function Update-BsiSkillReadme { param( [Parameter(Mandatory)]$Mapping, [Parameter(Mandatory)][string]$OutputPath ) $lines = [System.Collections.ArrayList]::new() $null = $lines.Add("---") $null = $lines.Add("name: 'bsi-oscal-azure-compliance'") $null = $lines.Add("description: 'BSI IT-Grundschutz++ OSCAL compliance validator for Azure 3-tier deployments.'") $null = $lines.Add("metadata:") $null = $lines.Add(" generated_at: $(Get-Date -Format 'yyyy-MM-dd')") $null = $lines.Add(" generator: 'BSI.AzCompliance'") $null = $lines.Add(" source_repo: '$($Mapping.repository)'") $null = $lines.Add(" lastSynced: '$($Mapping.lastSynced)'") $null = $lines.Add("---") $null = $lines.Add("") $null = $lines.Add("# BSI OSCAL Azure Compliance Skill") $null = $lines.Add("") $null = $lines.Add("## Mapped Controls") $null = $lines.Add("") foreach ($entry in $Mapping.mappings) { $null = $lines.Add("- **$($entry.controlId)**: $($entry.title) [$($entry.category)]") } $null = $lines.Add("") $null = $lines.Add("## Usage") $null = $lines.Add('```powershell') $null = $lines.Add('Import-Module ./modules/BSI.AzCompliance') $null = $lines.Add('Invoke-BsiCompliance -Local -ScriptPath .\create_3-tier-webapp_VM_v2.ps1') $null = $lines.Add('Invoke-BsiCompliance -Remote -ConfigPath .\config.ps1') $null = $lines.Add('```') $lines | Set-Content -Path $OutputPath -Encoding UTF8 Write-Verbose "[Mapping] Updated skill readme: $OutputPath" } |