Private/Logging/Write-SecurityLog.ps1

function Write-SecurityLog {
    <#
    .SYNOPSIS
        Writes security audit log entries for compliance and monitoring
 
    .DESCRIPTION
        Provides standardized security event logging with proper audit trails,
        security context tracking, and correlation IDs for compliance requirements.
 
    .PARAMETER SecurityEventType
        Type of security event being logged (ObjectAccess, Authentication, Authorization, etc.)
 
    .PARAMETER Message
        Descriptive message for the security event
 
    .PARAMETER Outcome
        Result of the security operation (Attempt, Success, Failure)
 
    .PARAMETER SecurityContext
        Additional security context information for audit trail
 
    .PARAMETER CorrelationId
        Unique identifier for tracking related operations
 
    .EXAMPLE
        PS> Write-SecurityLog -SecurityEventType 'ObjectAccess' -Message 'AD user access attempt' -Outcome 'Success'
 
        DESCRIPTION: Logs successful AD object access operation
        OUTPUT: Security log entry with audit trail
        USE CASE: Compliance and security monitoring
 
    .NOTES
        Author: Jeffrey Stuhr
        Blog: https://www.techbyjeff.net
        LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/
 
        TROUBLESHOOTING:
        - For logging configuration: .\Troubleshooting\Security\Audit-Configuration.md
        - For compliance requirements: .\Troubleshooting\Security\Compliance-Guide.md
    #>


    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$SecurityEventType,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Message,

        [Parameter(Mandatory)]
        [ValidateSet('Attempt', 'Success', 'Failure')]
        [string]$Outcome,

        [Parameter()]
        [hashtable]$SecurityContext = @{},

        [Parameter()]
        [string]$CorrelationId = [System.Guid]::NewGuid().ToString()
    )

    process {
        # Build comprehensive security log entry
        $securityLogEntry = @{
            Timestamp = Get-Date
            SecurityEventType = $SecurityEventType
            Outcome = $Outcome
            Message = $Message
            UserContext = "$env:USERNAME@$env:COMPUTERNAME"
            ProcessId = $PID
            CorrelationId = $CorrelationId
            Component = 'SecurityAudit'
        }

        # Merge additional security context
        foreach ($key in $SecurityContext.Keys) {
            $securityLogEntry["Security_$key"] = $SecurityContext[$key]
        }

        # Determine log level based on outcome
        $logLevel = switch ($Outcome) {
            'Attempt' { 'Information' }
            'Success' { 'Information' }
            'Failure' { 'Warning' }
            default { 'Information' }
        }

        # Format security message with audit identifiers
        $auditMessage = "[$SecurityEventType] [$Outcome] $Message"

        try {
            # Write to security-specific structured log system (bypasses log level filtering)
            Write-SecurityStructuredLogEntry -Level $logLevel -Component 'SecurityAudit' -Message $auditMessage -CorrelationId $CorrelationId -Data $securityLogEntry

            # Also write to verbose stream for immediate visibility during security operations
            Write-Verbose "SECURITY AUDIT: $auditMessage (CorrelationId: $CorrelationId)"

        } catch {
            # Fallback logging if structured logging fails - security events must be captured
            Write-Warning "Security log entry failed: $($_.Exception.Message) - Event: $auditMessage"

            # Try direct file append as last resort for critical security events
            try {
                $fallbackEntry = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff') [SecurityAudit] [$logLevel] $auditMessage (CorrelationId: $CorrelationId)"
                $fallbackEntry | Out-File -FilePath "$env:TEMP\OrphanedSid-Security-Fallback.log" -Append -Encoding UTF8 -WhatIf:$false
            } catch {
                Write-Error "Critical: Unable to write security audit log entry: $auditMessage"
            }
        }
    }
}