Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

When Audit Trails Disappear: The Hidden Configuration Chaos


I recently discovered a configuration inconsistency across our domain controllers that was made physical when a group policy monitor script failed to detect updates.

What I found when I ran my PowerShell audit script was inconsistency’s - our Security Event Log sizes were all over the place, creating compliance gaps and potential audit trail loss.

The Discovery That Started It All

I had built a PowerShell script to audit our domain controllers' Security Event Log configurations, expecting to find uniform settings across the environment. Instead, I was greeted with this inconsistent output:

Checking ROADRUNNER...
  Current size: 13958643712 bytes (13 GB)
  ✓ Correctly configured

Checking COYOTE...
  Current size: 13421772800 bytes (12.5 GB)
  MISMATCH DETECTED: Expected 13958643712 bytes (13 GB)

Checking SPEEDY...
  Current size: 13428326400 bytes (12.51 GB)
  MISMATCH DETECTED: Expected 13958643712 bytes (13 GB)

Checking PEPE...
  Current size: 13421772800 bytes (12.5 GB)
  MISMATCH DETECTED: Expected 13958643712 bytes (13 GB)

Checking TWEETY...
  Current size: 5599985664 bytes (5.22 GB)
  MISMATCH DETECTED: Expected 13958643712 bytes (13 GB)

Out of our domain controller infrastructure, I found configurations ranging from 5.22 GB to 12.51 GB - a massive variance that could impact audit capabilities and compliance posture.

Domain controllers with smaller log sizes were cycling through security events much faster. "TWEETY" with only 5.22 GB was overwriting security events after just 18 hours, while others maintained 3-4 days of history.

PowerShell Discovery Script

Here's the script that revealed this configuration chaos:

param([switch]$ForceValue)

# Target size: 13 GB in bytes  
$RecommendedSizeBytes = 13958643712

Write-Host "Domain Controller Security Event Log Audit" -ForegroundColor Green
Write-Host "Target size: 13 GB ($RecommendedSizeBytes bytes)" -ForegroundColor Yellow

# Get all domain controllers
$DomainControllers = Get-ADDomainController -Filter * | Select-Object Name

$MismatchedDCs = @()
$CorrectDCs = @()

foreach ($DC in $DomainControllers) {
    Write-Host "`nChecking $($DC.Name)..." -ForegroundColor White
    
    try {
        $SecurityLog = Get-WinEvent -ListLog Security -ComputerName $DC.Name -ErrorAction Stop
        $CurrentSize = $SecurityLog.MaximumSizeInBytes
        $SizeGB = [math]::Round($CurrentSize/1GB, 2)
        
        Write-Host "  Current size: $CurrentSize bytes ($SizeGB GB)" -ForegroundColor White
        
        if ($CurrentSize -ne $RecommendedSizeBytes) {
            Write-Host "  MISMATCH DETECTED: Expected $RecommendedSizeBytes bytes (13 GB)" -ForegroundColor Red
            $MismatchedDCs += [PSCustomObject]@{
                Name = $DC.Name
                CurrentSize = $CurrentSize
                CurrentSizeGB = $SizeGB
                RecommendedSize = $RecommendedSizeBytes
            }
        } else {
            Write-Host "  ✓ Correctly configured" -ForegroundColor Green
            $CorrectDCs += $DC.Name
        }
    }
    catch {
        Write-Host "  ERROR: Unable to retrieve log configuration - $($_.Exception.Message)" -ForegroundColor Red
    }
}

Root Cause Analysis

After digging deeper, I discovered three main causes for this inconsistency:

1. Manual Configuration Drift

This setting was free to be updated by Administrators which means each server had the potential to be on a different value.

2. No Centralized Management

Each DC was configured locally, allowing for individual changes that weren't tracked or standardized.

3. Legacy Settings Persistence

Some domain controllers retained old configuration values from previous OS upgrades or migrations.

💡 Key Insight: Without centralized management, configuration drift is inevitable in enterprise environments.

Group Policy : Centralized Control

To solve this inconsistency permanently, I implemented a Group Policy-based approach which would centrally enforce these settings.

Step 1: Create the Domain Controller Security Policy

  1. Open Group Policy Management Console (gpmc.msc)
  2. Navigate to your domain → Domain Controllers OU
  3. Right-click "Default Domain Controllers Policy" → Edit

Step 2: Configure Security Event Log Size

Navigate through the policy tree:

Computer Configuration
└── Policies
    └── Administrative Templates  
        └── Windows Components
            └── Event Log Service
                └── Security

Step 3: Apply the Specific Settings

Policy 1: Maximum Log File Size

  • Setting: Specify the maximum log file size (KB)
  • State: Enabled
  • Value:13631488 (13 GB in KB)
  • Impact: Forces uniform log size across all DCs

Policy 2: Retention Method

  • Setting: Control Event Log behavior when the log file reaches its maximum size
  • State: Enabled
  • Option : Overwrite events as needed (oldest events first)
  • Impact: Ensures continuous logging without manual intervention

Step 4: Link and Enforce the Policy

  1. Verify this GPO is linked to the Domain Controllers OU
  2. Verify No Conflicts: Check GPO precedence and filtering

Step 5: Force Policy Application

On each domain controller, run:

gpupdate /force

Or centrally trigger via PowerShell:

$DomainControllers | ForEach-Object {
    Invoke-Command -ComputerName $_.Name -ScriptBlock { gpupdate /force }
}

Prevented Future Drift 

The Event Log Properties dialog now shows:

  • Maximum log size field: Grayed out
  • Retention options: Grayed out 
  • Tooltip: "This setting is managed by your system administrator"
Previous Post Next Post

نموذج الاتصال