Updated 29 Jul 2015: Improved property name matching in the script and added an additional recommended settings spreadsheet.

Windows security auditing policies determine which events will be written to the Security event log and some are invaluable when diagnosing client connection and access issues, not to mention their use during and after potential security attacks.

But unfortunately as described in this fantastic article by Ned Pyle this part of Windows has had extensive rework with new bits bolted on which make it difficult to configure correctly and also to verify. The only accurate way to calculate what is in effect is to run auditpol.exe on each server.

Luckily we can still automate this using WinRM remoting or PSExec. I chose the latter for the script below which will output multiple servers into a usable CSV format that can be opened and manipulated in Excel.

# Update with whatever method you use to generate your host list
$hostNames = @("localhost")
$psExec = "C:\Temp\PSExec.exe"
$auditPol = "C:\Windows\System32\AuditPol.exe"
$auditPolicy = @()
foreach ($hostName in $hostNames) {
    Write-Host "Processing $hostName" -NoNewline
    $ErrorActionPreference = "Continue" # Required for PSExec  
    $auditPolicyString = &$psExec "\\$hostName" -accepteula -n 5 cmd /c $auditPol /get /category:* 2>&1
    $ErrorActionPreference = "Stop"
    if ($LastExitCode -ne 0) {
        Write-Host ": Failed"
        # You can parse the ErrorRecord types from $auditPolicyString if you want to get the real error
    } else {
        $thisAuditPolicy = New-Object PSObject -Property @{
            "Host Name" = $hostName
        $auditPolicyString | Where { $_ -is [string] -and $_ } <# Remove blank lines #> | Select -Skip 2 <# Headers #> | %{
            # Headers don't have two columns and so don't have two spaces
            if ($_ -like "*  *") {
                # The left and right columns are separated by two spaces, extract into two groups and ignore spaces between them
                $_ -match '  ([a-z, /-]+)  ([a-z, ]+)' | Out-Null
                # Add a property for each audit policy
                $thisAuditPolicy | Add-Member -MemberType NoteProperty -Name "$($Matches[1].Trim())" -Value $Matches[2]
        $auditPolicy += $thisAuditPolicy
        Write-Host ": Ok"

# Output ready for Excel
$auditPolicy | ConvertTo-Csv -NoTypeInformation | Set-Content C:\Temp\AuditPolicy.csv

# Optionally test that every property name is accessible
# $auditPolicy[0].psobject.Properties | Select -ExpandProperty Name | Where { $_ -ne "Host Name" } | %{ &$auditPol /Get /Subcategory:"$_" } 

Here's what the output looks like.

If you're interested to investigate this topic further you'll need to bookmark these:

I've also taken those guidelines and created an Excel spreadsheet laying out the high security recommendation and details, as well as the Auditpol commands to set them, which you could tailor however you wish.

Just enabling everything will be detrimental, perhaps to performance, but mostly to log size and retention period. All the auditing in the world isn't much use if you can only hold an hour's worth at a time!