Public/Test-AuditLogStreaming.ps1
|
function Test-AuditLogStreaming { [CmdletBinding()] [OutputType([PSCustomObject[]])] param( [Parameter(Mandatory)] [ValidatePattern('^[a-zA-Z0-9._-]+$')] [string]$Owner, [Parameter(Mandatory)] [string]$Token ) $resource = "org/$Owner" $results = [System.Collections.Generic.List[PSCustomObject]]::new() $ownerContext = Get-FylgyrOwnerContext -Owner $Owner -Token $Token if ($ownerContext.Type -eq 'User') { $results.Add((Format-FylgyrResult ` -CheckName 'AuditLogStreaming' ` -Status 'Info' ` -Severity 'Info' ` -Resource $resource ` -Detail "Owner '$Owner' is a personal account. Organization audit log streaming does not apply." ` -Remediation 'No action needed. Run this check against an organization owner.' ` -Target $resource)) return $results.ToArray() } try { $streamKey = Invoke-GitHubApi -Endpoint "orgs/$Owner/audit-log/stream-key" -Token $Token } catch { $msg = $_.Exception.Message if ($msg -match '404') { $results.Add((Format-FylgyrResult ` -CheckName 'AuditLogStreaming' ` -Status 'Info' ` -Severity 'Info' ` -Resource $resource ` -Detail 'Audit log streaming endpoint is not available at organization scope in the current feature/policy/access context. Enterprise-level streaming can be configured centrally and still return 404 for org endpoint checks.' ` -Remediation 'Advisory for now. Confirm streaming under enterprise settings, then use org-level checks as supplemental visibility when endpoint support is available.' ` -Target $resource)) return $results.ToArray() } if ($msg -match '403') { $results.Add((Format-FylgyrResult ` -CheckName 'AuditLogStreaming' ` -Status 'Info' ` -Severity 'Info' ` -Resource $resource ` -Detail 'Insufficient permissions to read organization audit log streaming configuration.' ` -Remediation 'Use a fine-grained token with organization Administration:read, or a classic token with admin:org scope.' ` -Target $resource)) return $results.ToArray() } $results.Add((Format-FylgyrResult ` -CheckName 'AuditLogStreaming' ` -Status 'Error' ` -Severity 'Medium' ` -Resource $resource ` -Detail "Failed to evaluate audit log streaming: $($_.Exception.Message)" ` -Remediation 'Verify token scope and organization access, then rerun.' ` -Target $resource)) return $results.ToArray() } $configured = $false if ($streamKey -and $streamKey.PSObject.Properties['stream_key'] -and $streamKey.stream_key) { $configured = $true } if ($configured) { $results.Add((Format-FylgyrResult ` -CheckName 'AuditLogStreaming' ` -Status 'Pass' ` -Severity 'Info' ` -Resource $resource ` -Detail 'Organization audit log streaming key is configured.' ` -Remediation 'No action needed. Validate downstream SIEM ingestion and retention.' ` -Target $resource)) } else { $results.Add((Format-FylgyrResult ` -CheckName 'AuditLogStreaming' ` -Status 'Warning' ` -Severity 'Medium' ` -Resource $resource ` -Detail 'Organization audit log streaming is not configured. Incident response and forensic reconstruction become harder after compromise.' ` -Remediation 'Configure audit log streaming to an external SIEM or immutable storage target with alerting on privileged events.' ` -AttackMapping @('github-device-code-phishing', 'uber-credential-leak') ` -Target $resource)) } $results.ToArray() } |