Windows Client log management

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.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.