Modules/Outputs/Reports/30-JsonEvidence.ps1
|
function Write-RangerJsonEvidenceExport { <# .SYNOPSIS v2.0.0 (#229): export a resource-only JSON evidence payload. .DESCRIPTION Strips assessment, scoring, pipeline metadata, and schema validation fields from the manifest, leaving only the raw collected inventory plus a small `_metadata` envelope. Intended for downstream tools (Power BI, CMDBs, custom scripts) that shouldn't have to parse around findings / WAF scoring / run metadata. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [System.Collections.IDictionary]$Manifest, [Parameter(Mandatory = $true)] [string]$PackageRoot, [string]$FileName ) $target = $Manifest.target $run = $Manifest.run $runId = if ($run -and $run.runId) { [string]$run.runId } elseif ($run -and $run.startTimeUtc) { # Strip every character except digits so the id is filesystem-safe # regardless of the timestamp format (ISO-8601, compact, etc). $digits = ([string]$run.startTimeUtc) -replace '[^\d]','' if ($digits.Length -ge 14) { $digits.Substring(0,14) } else { $digits.PadRight(14, '0') } } else { (Get-Date).ToString('yyyyMMddHHmmss') } $getDomain = { param($name) try { return $Manifest.domains.$name } catch { return $null } } $ai = & $getDomain 'azureIntegration' $storage = & $getDomain 'storage' $networking = & $getDomain 'networking' $cluster = & $getDomain 'clusterNode' $vms = & $getDomain 'virtualMachines' $payload = [ordered]@{ _metadata = [ordered]@{ exportVersion = '1.0' generatedAt = (Get-Date).ToUniversalTime().ToString('o') rangerVersion = [string]$run.toolVersion clusterName = [string]$target.clusterName runId = $runId } nodes = if ($cluster) { @($cluster.nodes) } else { @() } storagePools = if ($storage) { @($storage.pools) } else { @() } volumes = if ($storage) { @($storage.volumes) } else { @() } logicalNetworks = if ($networking -and $networking.logicalNetworks) { @($networking.logicalNetworks) } else { @() } storagePaths = if ($storage -and $storage.storagePaths) { @($storage.storagePaths) } else { @() } virtualMachines = if ($vms) { @($vms.inventory) } else { @() } arcExtensions = if ($ai -and $ai.arcExtensionsDetail -and $ai.arcExtensionsDetail.byNode) { @($ai.arcExtensionsDetail.byNode) } else { @() } arcResourceBridges = if ($ai -and $ai.resourceBridgeDetail) { @($ai.resourceBridgeDetail) } else { @() } customLocations = if ($ai -and $ai.customLocationsDetail) { @($ai.customLocationsDetail) } else { @() } arcGateways = if ($ai -and $ai.arcGateways) { @($ai.arcGateways) } else { @() } marketplaceImages = if ($ai -and $ai.marketplaceImages) { @($ai.marketplaceImages) } else { @() } galleryImages = if ($ai -and $ai.galleryImages) { @($ai.galleryImages) } else { @() } costLicensing = if ($ai -and $ai.costLicensing) { $ai.costLicensing } else { $null } } $reportsDir = Join-Path $PackageRoot 'reports' if (-not (Test-Path $reportsDir)) { New-Item -ItemType Directory -Path $reportsDir -Force | Out-Null } $name = if ($FileName) { $FileName } else { "$runId-evidence.json" } $destPath = Join-Path $reportsDir $name $payload | ConvertTo-Json -Depth 30 | Set-Content -Path $destPath -Encoding UTF8 return [ordered]@{ type = 'json-evidence' relativePath = [System.IO.Path]::GetRelativePath($PackageRoot, $destPath) status = 'generated' audience = 'all' } } |