In a security conscious environment, it may be necessary or mandated to archive the Windows security event log. By default the security log is configured to overwrite events as needed. Here is a screenshot of typical security event log settings:
To check or modify your security event log settings, launch Event Viewer. Expand Windows Logs then click Security. Right click on the Security log and select Properties. The first thing you may want to change would be the "Maximum log size (KB)". Beyond that, decide upon your retention policy. Here are the options:
The following PowerShell script will check the size of the security event log and archive it if necessary. The steps performed by the script are as follows:
# Title: MonitorSecurityLog.ps1 # Version: 1.0.0, 18JAN17 # Author: James Sanders # Purpose: Monitor the security log and automatically archive and clear the log if it's over 250 MB in size. # Set the archive location $ArchiveFolder = "D:\Logs\OS" # How big can the security event log get in MB before we automatically archive? $ArchiveSize = 250 # Verify the archive folder exists If (!(Test-Path $ArchiveFolder)) { Write-Host Write-Host "Archive folder $ArchiveFolder does not exist, aborting ..." -ForegroundColor Red Exit } # Configure environment $sysName = $env:computername $eventName = "Security Event Log Monitoring" $mailMsgServer = "your.smtp.server.name" $mailMsgSubject = "$sysName Security Event Log Monitoring" $mailMsgFrom = "[email protected]" $mailMsgTo = "[email protected]" # Add event source to application log if necessary If (-NOT ([System.Diagnostics.EventLog]::SourceExists($eventName))) { New-EventLog -LogName Application -Source $eventName } # Check the security log $Log = Get-WmiObject Win32_NTEventLogFile -Filter "logfilename = 'security'" $SizeCurrentMB = [math]::Round($Log.FileSize / 1024 / 1024,2) $SizeMaximumMB = [math]::Round($Log.MaxFileSize / 1024 / 1024,2) Write-Host # Archive the security log if over the limit If ($SizeCurrentMB -gt $ArchiveSize) { $ArchiveFile = $ArchiveFolder + "\Security-" + (Get-Date -Format "yyyy-MM-dd@HHmm") + ".evt" $EventMessage = "The security event log size is currently " + $SizeCurrentMB + " MB. The maximum allowable size is " + $SizeMaximumMB + " MB. The security event log size has exceeded the threshold of $ArchiveSize MB." $Results = ($Log.BackupEventlog($ArchiveFile)).ReturnValue If ($Results -eq 0) { # Successful backup of security event log $Results = ($Log.ClearEventlog()).ReturnValue $EventMessage += "The security event log was successfully archived to $ArchiveFile and cleared." Write-Host $EventMessage Write-EventLog -LogName Application -Source $eventName -EventId 11 -EntryType Information -Message $eventMessage -Category 0 $mailMsgBody = $EventMessage Send-MailMessage -From $mailMsgFrom -to $MailMsgTo -subject $mailMsgSubject -Body $mailMsgBody -SmtpServer $mailMsgServer } Else { $EventMessage += "The security event log could not be archived to $ArchiveFile and was not cleared. Review and resolve security event log issues on $sysName ASAP!" Write-Host $EventMessage Write-EventLog -LogName Application -Source $eventName -EventId 11 -EntryType Error -Message $eventMessage -Category 0 $mailMsgBody = $EventMessage Send-MailMessage -From $mailMsgFrom -to $MailMsgTo -subject $mailMsgSubject -Body $mailMsgBody -SmtpServer $mailMsgServer } } Else { # Write an informational event to the application event log $EventMessage = "The security event log size is currently " + $SizeCurrentMB + " MB. The maximum allowable size is " + $SizeMaximumMB + " MB. The security event log size is below the threshold of $ArchiveSize MB so no action was taken." Write-Host $EventMessage Write-EventLog -LogName Application -Source $eventName -EventId 11 -EntryType Information -Message $eventMessage -Category 0 } # Close the log $Log.Dispose()
Before using the script in your environment, configure the following variables:
You can save the following to an XML file and then import it into Task Scheduler. Change the <Arguments> section to the folder/file name where you saved the script. This XML file sets the script to run every hour.
<?xml version="1.0" encoding="UTF-16"?> <Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date>2017-01-18T16:41:30.9576112</Date> <Description>Monitor security event log. Archive and clear log if threshold is met.</Description> </RegistrationInfo> <Triggers> <CalendarTrigger> <Repetition> <Interval>PT2H</Interval> <StopAtDurationEnd>false</StopAtDurationEnd> </Repetition> <StartBoundary>2017-01-18T00:00:00</StartBoundary> <ExecutionTimeLimit>PT30M</ExecutionTimeLimit> <Enabled>true</Enabled> <ScheduleByDay> <DaysInterval>1</DaysInterval> </ScheduleByDay> </CalendarTrigger> </Triggers> <Principals> <Principal id="Author"> <UserId>S-1-5-18</UserId> <RunLevel>HighestAvailable</RunLevel> </Principal> </Principals> <Settings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession> <UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>P3D</ExecutionTimeLimit> <Priority>7</Priority> </Settings> <Actions Context="Author"> <Exec> <Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command> <Arguments>c:\scripts\PS\MonitorSecurityLog.ps1</Arguments> </Exec> </Actions> </Task>