One of our clients recently asked us to locally archive windows logs for 90 days – they didn’t want the expense of a log aggregator such as Logrhythm.
The requirement was to retain 90 days of security and application logs (although you can expand the script to include others) in a compressed folder with restricted security. They also wanted this to run daily; run if missed, and store the logs by date. The Task is set to run as SYSTEM.
The Powershell script below will:
- create a scheduled task to run at 10:00 am every day
- create a log directory under the root of C:\
- compress this directory
- Write out the script needed to run every day
######################################### # Log Rotate Script - Jimmy White # # Feel free to use and redistribute # ######################################### # Create an action for a new scheduled task.. $action = New-ScheduledTaskAction -Execute 'Powershell.exe' '-WindowStyle Hidden -ExecutionPolicy Bypass -WindowStyle Hidden -file c:\logs\rotate.ps1 -localhost -clear' # Set some of the options... $STSet = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries:$TRUE -StartWhenAvailable:$TRUE $trigger = New-ScheduledTaskTrigger -Daily -At 10am # Commit the Task... Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "LogRotate" -User "System" -Description "Daily dump of Logs" -settings $STSet #create the script #check the log dir does NOT exisit then create it if (!(test-path "c:\logs")){md "c:\logs" Invoke-WmiMethod -Path "Win32_Directory.Name='c:\logs'" -Name Compress} #All text between $line1=@" and "@ should be unchanged. Note the preceeding ` before variable names, this is neccesssary or the variable will not be written out correctly #This text is the actual script that will perform the log rotation ############################################################################################# $line1=@" #Change path as necessary `$logdir = "C:\Logs\Security" #If the log path doesnt exist, create and compress it if (!(test-path `$logdir)){md `$logdir Invoke-WmiMethod -Path "Win32_Directory.Name='`$logdir'" -Name Compress} # Get any new entries in the security log since this script was last run an export `$LatestLog = Get-ChildItem -Path `$logdir | Sort-Object CreationTime -descending | Select-Object -First 1 `$Now = (get-date -Format s) -replace ":","" `$Applog = `$logdir + "\" + `$now + "applog.csv" `$LogExportPath = `$logdir + "\" + `$now + "security.csv" # Grab the security log.. get-eventlog security | where {`$_.timewritten -gt `$LatestLog.CreationTime} | select EventID,MachineName,Data,Index,Category,CategoryNumber,EntryType,@{n='Message';e={`$_.Message -replace '\s+', " "}},Source,@{n='ReplacementStrings';e={[system.string]::join(" ",`$_.ReplacementStrings)}},InstanceId,TimeGenerated,TimeWritten,UserName,Site,Container | export-csv -Path `$LogExportPath -Append #Grab the appliction log get-eventlog application | where {`$_.timewritten -gt `$LatestLog.CreationTime} | select EventID,MachineName,Data,Index,Category,CategoryNumber,EntryType,@{n='Message';e={`$_.Message -replace '\s+', " "}},Source,@{n='ReplacementStrings';e={[system.string]::join(" ",`$_.ReplacementStrings)}},InstanceId,TimeGenerated,TimeWritten,UserName,Site,Container | export-csv -Path `$Applog -Append #Remove any files in log dir older than 90 days get-childitem `$logdir -recurse | where {`$_.CreationTime -lt (get-date).adddays(-90) -and -not `$_.psiscontainer} |% {remove-item `$_.fullname -force} "@ ############################################################################################# #Name of the file we want to output to: $file="c:\logs\rotate.ps1" #write the file out $line1 | Add-Content -Path $file #disable inheritance on folder.. $acl = Get-Item "C:\logs" |get-acl $acl.SetAccessRuleProtection($true,$true) $acl |Set-Acl #now set specific permissions #get current permission first.. $acl = Get-Acl -Path 'C:\logs' #remove user permissions for USERS and AUTHENTICATED USERS $ACL.Access | ?{ $_.IdentityReference -Like "*users" } |%{ $ACL.RemoveAccessRuleSpecific($_) } Set-ACL "c:\logs" $ACL #Define permissions for system and domain admins - dontforget to change DOMAIN to your domain name $acl = Get-Item "C:\logs" |get-acl $AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule ("Administrators","FullControl","ContainerInherit,ObjectInherit","None","Allow") $acl.AddAccessRule($AccessRule) $AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule ("system","FullControl","ContainerInherit,ObjectInherit","None","Allow") $acl.AddAccessRule($AccessRule) $AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule ("DOMAIN\domain admins","FullControl","ContainerInherit,ObjectInherit","None","Allow") $acl.AddAccessRule($AccessRule) $acl | Set-Acl -Path 'C:\logs'
This script was then made part of the task sequence for new machines and pushed via SCCM to existing machines.