Private/ConvertTo-FylgyrLogAnalytics.ps1
|
function ConvertTo-FylgyrLogAnalytics { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'LogAnalytics matches Azure product naming.')] [CmdletBinding()] [OutputType([string], [void])] param( [Parameter(Mandatory)] [PSCustomObject[]]$Results, [Parameter(Mandatory)] [string]$ScanId, [Parameter(Mandatory)] [datetime]$ScanStartTime, [string]$OutputPath ) $module = Get-Module -Name Fylgyr -ErrorAction SilentlyContinue $version = if ($module -and $module.Version) { $module.Version.ToString() } else { '0.0.0' } $lines = [System.Collections.Generic.List[string]]::new() foreach ($result in $Results) { $mode = if ($result.PSObject.Properties['Mode'] -and $result.Mode) { [string]$result.Mode } else { 'Audit' } $eventSchema = if ($mode -eq 'Drift') { 'ChangeEvent' } else { 'AuditEvent' } $resource = [string]$result.Resource $target = if ($result.PSObject.Properties['Target'] -and -not [string]::IsNullOrWhiteSpace([string]$result.Target)) { [string]$result.Target } else { $resource } $owner = $null $repo = $null $identitySource = if (-not [string]::IsNullOrWhiteSpace($target)) { $target } else { $resource } if (-not [string]::IsNullOrWhiteSpace($identitySource) -and $identitySource -match '^(?<owner>[a-zA-Z0-9._-]+)/(?<repo>[a-zA-Z0-9._-]+)') { $owner = $Matches.owner $repo = $Matches.repo } $timeGenerated = $ScanStartTime.ToString('o') if ($result.PSObject.Properties['Evidence'] -and $result.Evidence) { if ($result.Evidence.PSObject.Properties['ChangedAt'] -and $result.Evidence.ChangedAt) { try { $timeGenerated = ([datetime]$result.Evidence.ChangedAt).ToString('o') } catch { $timeGenerated = $ScanStartTime.ToString('o') } } elseif ($result.Evidence.PSObject.Properties['ScanTime'] -and $result.Evidence.ScanTime) { try { $timeGenerated = ([datetime]$result.Evidence.ScanTime).ToString('o') } catch { $timeGenerated = $ScanStartTime.ToString('o') } } } $attackMapping = '' if ($result.PSObject.Properties['AttackMapping'] -and $result.AttackMapping) { $attackMapping = (@($result.AttackMapping) -join ';') } $evidenceYaml = $null $evidenceCommitSha = $null $evidencePermalink = $null $driftFrom = $null $driftTo = $null if ($result.PSObject.Properties['Evidence'] -and $result.Evidence) { if ($result.Evidence.PSObject.Properties['YamlSnippet']) { $evidenceYaml = [string]$result.Evidence.YamlSnippet } if ($result.Evidence.PSObject.Properties['CommitSha']) { $evidenceCommitSha = [string]$result.Evidence.CommitSha } if ($result.Evidence.PSObject.Properties['Permalink']) { $evidencePermalink = [string]$result.Evidence.Permalink } if ($result.Evidence.PSObject.Properties['From']) { $driftFrom = ($result.Evidence.From | ConvertTo-Json -Depth 20 -Compress) } if ($result.Evidence.PSObject.Properties['To']) { $driftTo = ($result.Evidence.To | ConvertTo-Json -Depth 20 -Compress) } } $lineObject = [ordered]@{ TimeGenerated = $timeGenerated Type = 'Fylgyr_CL' EventVendor = 'Fylgyr' EventProduct = 'Fylgyr' EventSchema = $eventSchema EventType = if ($mode -eq 'Drift') { 'ConfigurationDrift' } else { 'SecurityFinding' } ScanId_g = $ScanId ScanStartTime_dt = $ScanStartTime.ToString('o') FylgyrVersion_s = $version CheckName_s = [string]$result.CheckName Severity_s = [string]$result.Severity Status_s = [string]$result.Status Mode_s = $mode Resource_s = $resource Target_s = $target Owner_s = $owner Repo_s = $repo Detail_s = ([string]$result.Detail -replace "`r?`n", ' ') Remediation_s = ([string]$result.Remediation -replace "`r?`n", ' ') AttackMapping_s = $attackMapping DriftFrom_s = $driftFrom DriftTo_s = $driftTo EvidenceYaml_s = $evidenceYaml EvidenceCommitSha_s = $evidenceCommitSha EvidencePermalink_s = $evidencePermalink } $lines.Add(($lineObject | ConvertTo-Json -Depth 12 -Compress)) } $ndjson = $lines -join [Environment]::NewLine if ($OutputPath) { Set-Content -Path $OutputPath -Value $ndjson -Encoding UTF8 return } return $ndjson } |