<# .SYNOPSIS Apply audit policies from parsed Security Baseline JSON .DESCRIPTION Uses native auditpol.exe to configure Advanced Audit Policies. Applies settings from AuditPolicies.json generated by Parse-SecurityBaseline. .PARAMETER AuditPoliciesPath Path to AuditPolicies.json .PARAMETER DryRun Preview changes without applying .OUTPUTS PSCustomObject with applied count and errors .NOTES Requires Administrator privileges Uses auditpol.exe (built into Windows since Vista) #> function Set-AuditPolicies { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$AuditPoliciesPath, [Parameter(Mandatory = $false)] [switch]$DryRun ) $result = [PSCustomObject]@{ Applied = 0 Errors = @() } if (-not (Test-Path $AuditPoliciesPath)) { $result.Errors += "Audit policies file not found: $AuditPoliciesPath" return $result } try { $auditPolicies = Get-Content -Path $AuditPoliciesPath -Raw | ConvertFrom-Json if ($auditPolicies.Count -eq 0) { Write-Log -Level DEBUG -Message "No audit policies to apply" -Module "SecurityBaseline" return $result } Write-Log -Level DEBUG -Message "Applying $($auditPolicies.Count) audit policies..." -Module "SecurityBaseline" Write-Host " Applying $($auditPolicies.Count) audit policies..." -ForegroundColor Cyan $currentPolicy = 0 foreach ($policy in $auditPolicies) { $currentPolicy++ try { # Convert SettingValue to auditpol format # SettingValue is numeric: 0=No Auditing, 1=Success, 2=Failure, 3=Success and Failure # auditpol format: "enable" or "disable" with /success or /failure flags $settingValue = [int]$policy.SettingValue # Build auditpol command using GUID (language-independent!) $auditpolArgs = @("/set") $auditpolArgs += "/subcategory:$($policy.SubcategoryGUID)" switch ($settingValue) { 3 { # Success and Failure $auditpolArgs += "/success:enable" $auditpolArgs += "/failure:enable" } 1 { # Success only $auditpolArgs += "/success:enable" $auditpolArgs += "/failure:disable" } 2 { # Failure only $auditpolArgs += "/success:disable" $auditpolArgs += "/failure:enable" } default { # No Auditing (0 or any other value) $auditpolArgs += "/success:disable" $auditpolArgs += "/failure:disable" } } if ($DryRun) { Write-Log -Level DEBUG -Message "[DRYRUN] Would run: auditpol.exe $($auditpolArgs -join ' ')" -Module "SecurityBaseline" Write-Host " [$currentPolicy/$($auditPolicies.Count)] $($policy.Subcategory) [DRYRUN]" -ForegroundColor DarkGray $result.Applied++ continue } # Show progress (every 5th policy or first/last) if ($currentPolicy % 5 -eq 0 -or $currentPolicy -eq 1 -or $currentPolicy -eq $auditPolicies.Count) { # Remove "Audit " prefix if present for cleaner output $displayName = $policy.Subcategory -replace '^Audit\s+', '' Write-Host " [$currentPolicy/$($auditPolicies.Count)] $displayName..." -ForegroundColor Gray -NoNewline } # Execute auditpol $process = Start-Process -FilePath "auditpol.exe" ` -ArgumentList $auditpolArgs ` -Wait ` -NoNewWindow ` -PassThru ` -RedirectStandardOutput (Join-Path $env:TEMP "auditpol_stdout.txt") ` -RedirectStandardError (Join-Path $env:TEMP "auditpol_stderr.txt") if ($process.ExitCode -eq 0) { $result.Applied++ # Show success for displayed policies if ($currentPolicy % 5 -eq 0 -or $currentPolicy -eq 1 -or $currentPolicy -eq $auditPolicies.Count) { Write-Host " OK" -ForegroundColor Green } } else { $stderr = Get-Content (Join-Path $env:TEMP "auditpol_stderr.txt") -Raw -ErrorAction SilentlyContinue $result.Errors += "auditpol failed for $($policy.Subcategory): $stderr" Write-Log -Level DEBUG -Message "auditpol failed for $($policy.Subcategory): $stderr" -Module "SecurityBaseline" # Show failure if ($currentPolicy % 5 -eq 0 -or $currentPolicy -eq 1 -or $currentPolicy -eq $auditPolicies.Count) { Write-Host " FAILED" -ForegroundColor Red } } } catch { $result.Errors += "Failed to set audit policy $($policy.Subcategory): $($_.Exception.Message)" Write-Log -Level DEBUG -Message "Failed to set audit policy $($policy.Subcategory): $_" -Module "SecurityBaseline" } } Write-Log -Level DEBUG -Message "Applied $($result.Applied) audit policies" -Module "SecurityBaseline" Write-Host " Completed: $($result.Applied)/$($auditPolicies.Count) audit policies applied" -ForegroundColor Green } catch { $result.Errors += "Audit policy application failed: $($_.Exception.Message)" Write-Log -Level DEBUG -Message "Audit policy application failed: $_" -Module "SecurityBaseline" } return $result }