Public/Export-HardeningLensTrendReport.ps1
|
function Export-HardeningLensTrendReport { <# .SYNOPSIS Exports a posture trend over multiple scan results of one computer. .DESCRIPTION Reads two or more scan results of the same computer and baseline, orders them by collection time, and renders a self-contained trend report with per-scan score, evidence coverage, status counts, and score deltas. Accepts current schema 1.1 results and validated schema 1.0 legacy results. The report embeds no external scripts, styles, fonts, or images. .PARAMETER Path Two or more scan result JSON files, or one directory whose *.json files are read. .PARAMETER Format One or more output formats. The default is Html and Markdown. .PARAMETER OutputDirectory Destination directory. It is created when missing. .PARAMETER FileNamePrefix Optional file name prefix without an extension. .PARAMETER Force Overwrites existing report files. Without Force, existing files cause an error. .EXAMPLE Export-HardeningLensTrendReport -Path .\history -OutputDirectory .\reports .EXAMPLE Export-HardeningLensTrendReport -Path .\scan-june.json, .\scan-july.json -Format Markdown #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [ValidateNotNullOrEmpty()] [string[]]$Path, [ValidateSet('Html', 'Markdown')] [string[]]$Format = @('Html', 'Markdown'), [string]$OutputDirectory = (Get-Location).Path, [string]$FileNamePrefix, [switch]$Force ) $resultFiles = New-Object System.Collections.Generic.List[string] foreach ($inputPath in @($Path)) { $resolved = (Resolve-Path -LiteralPath $inputPath -ErrorAction Stop).Path if (Test-Path -LiteralPath $resolved -PathType Container) { foreach ($file in @(Get-ChildItem -LiteralPath $resolved -Filter '*.json' -File | Sort-Object Name)) { $resultFiles.Add($file.FullName) } } else { $resultFiles.Add($resolved) } } if ($resultFiles.Count -lt 2) { throw 'Export-HardeningLensTrendReport needs at least two scan result files.' } $scanResults = @($resultFiles | ForEach-Object { Read-HLScanResult -InputObject $_ }) $series = Get-HLTrendSeries -ScanResults $scanResults if (-not (Test-Path -LiteralPath $OutputDirectory -PathType Container)) { [void](New-Item -Path $OutputDirectory -ItemType Directory -Force) } $resolvedOutput = (Resolve-Path -LiteralPath $OutputDirectory -ErrorAction Stop).Path $basePrefix = if ([string]::IsNullOrWhiteSpace($FileNamePrefix)) { 'hardening-lens-trend-{0}' -f (ConvertTo-HLFileNamePart -Value $series.ComputerName) } else { ConvertTo-HLFileNamePart -Value $FileNamePrefix } if ([string]::IsNullOrWhiteSpace($basePrefix)) { throw 'FileNamePrefix does not contain any valid file-name characters.' } $written = New-Object System.Collections.Generic.List[object] foreach ($outputFormat in @($Format | Sort-Object -Unique)) { $extension = switch ($outputFormat) { 'Html' { '.html' } 'Markdown' { '.md' } } $outputPath = Join-Path -Path $resolvedOutput -ChildPath ($basePrefix + $extension) if (-not $Force -and (Test-Path -LiteralPath $outputPath)) { throw ("Output file already exists: '{0}'. Use -Force to overwrite existing report files." -f $outputPath) } $content = switch ($outputFormat) { 'Html' { ConvertTo-HLTrendHtmlReport -Series $series } 'Markdown' { (ConvertTo-HLTrendMarkdown -Series $series) + [Environment]::NewLine } } Write-HLReportFile -Path $outputPath -Content $content -Force:$Force $file = Get-Item -LiteralPath $outputPath $written.Add([pscustomobject][ordered]@{ Format = $outputFormat; Path = $file.FullName; Bytes = $file.Length }) } return $written.ToArray() } |