Public/Save-CIEMScanResult.ps1
|
function Save-CIEMScanResult { <# .SYNOPSIS Saves CIEM scan results to persistent storage. .DESCRIPTION Persists scan results to PSU cache for retrieval by the Dashboard and Findings pages. Maintains scan history (last 10 scans) and stores both current and historical results. .PARAMETER Results Array of scan result objects returned from Invoke-CIEMScan. .PARAMETER Provider The cloud provider that was scanned (e.g., 'Azure'). .PARAMETER Services Array of services that were scanned (e.g., @('Entra', 'IAM')). .PARAMETER Duration Duration string of the scan (e.g., '45s' or '2m 30s'). .PARAMETER IncludePassed Whether passed checks were included in the scan results. .PARAMETER Timestamp The timestamp when the scan completed. Defaults to current time. .EXAMPLE $results = Invoke-CIEMScan -Provider Azure -Service Entra, IAM Save-CIEMScanResult -Results $results -Provider Azure -Services @('Entra', 'IAM') -Duration '45s' .OUTPUTS PSCustomObject with ScanId and summary statistics. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [AllowEmptyCollection()] [object[]]$Results, [Parameter(Mandatory)] [ValidateSet('Azure', 'AWS')] [string]$Provider, [Parameter(Mandatory)] [string[]]$Services, [Parameter(Mandatory)] [string]$Duration, [Parameter()] [bool]$IncludePassed = $false, [Parameter()] [datetime]$Timestamp = (Get-Date) ) begin { $allResults = [System.Collections.ArrayList]::new() } process { foreach ($result in $Results) { [void]$allResults.Add($result) } } end { # Generate scan ID $scanId = [guid]::NewGuid().ToString() # Categorize results by status $failedResults = @($allResults | Where-Object { $_.Status -eq 'FAIL' }) $passedResults = @($allResults | Where-Object { $_.Status -eq 'PASS' }) $skippedResults = @($allResults | Where-Object { $_.Status -eq 'SKIPPED' }) $manualResults = @($allResults | Where-Object { $_.Status -eq 'MANUAL' }) # Create scan record for history $scanRecord = @{ Id = $scanId Date = $Timestamp.ToString('o') Provider = $Provider Services = $Services TotalResults = $allResults.Count FailedResults = $failedResults.Count PassedResults = $passedResults.Count SkippedResults = $skippedResults.Count ManualResults = $manualResults.Count Duration = $Duration IncludePassed = $IncludePassed } # Check if PSU cache is available $psuCacheAvailable = Get-Command -Name 'Set-PSUCache' -ErrorAction SilentlyContinue if ($psuCacheAvailable) { try { # Update scan history (keep last 10) $scanHistoryKey = 'CIEM:ScanHistory' $existingHistory = Get-PSUCache -Key $scanHistoryKey -ErrorAction SilentlyContinue if (-not $existingHistory) { $existingHistory = @() } $existingHistory = @($scanRecord) + @($existingHistory) | Select-Object -First 10 Set-PSUCache -Key $scanHistoryKey -Value $existingHistory -Persist -ErrorAction Stop # Store results by scan ID (for historical viewing) $resultsKey = "CIEM:ScanResults:$scanId" Set-PSUCache -Key $resultsKey -Value @($allResults) -Persist -ErrorAction Stop # Store as current results (for Dashboard/Findings pages) Set-PSUCache -Key 'CIEM:CurrentScanResults' -Value @{ ScanId = $scanId Timestamp = $Timestamp.ToString('o') Results = @($allResults) IncludePassed = $IncludePassed } -Persist -ErrorAction Stop Write-Verbose "Persisted $($allResults.Count) scan results to cache (ScanId: $scanId)" } catch { Write-Warning "Failed to save scan results to PSU cache: $($_.Exception.Message)" } } else { Write-Verbose "PSU cache not available - scan results not persisted" } # Return summary object [PSCustomObject]@{ ScanId = $scanId Timestamp = $Timestamp Provider = $Provider Services = $Services TotalResults = $allResults.Count FailedResults = $failedResults.Count PassedResults = $passedResults.Count SkippedResults = $skippedResults.Count ManualResults = $manualResults.Count Duration = $Duration } } } |