-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProcessLatestWindowsUpdateLogs.ps1
155 lines (134 loc) · 7.21 KB
/
ProcessLatestWindowsUpdateLogs.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# ProcessLatestWindowsUpdateLogs.ps1
# By Craig Woodford ([email protected])
# Last update 4/26/2018
###
# Copyright 2017 University of Minnesota, Office of Information Technology
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with Foobar. If not, see <http://www.gnu.org/licenses/>.
###
# This script is used to convert Windows Update logs for Server 2016 systems
# into text-based logs for ingestion into a SIEM system such as Splunk. The
# script is designed to run on a regular basis so that only logs that have not
# been converted since the last script run-time are processed. The script needs
# to be run with administrative rights.
# Windows update ETL log files location (default: C:\Windows\Logs\WindowsUpdate).
$logPath = "C:\Windows\Logs\WindowsUpdate"
# Path of the file that will contain the last run time.
$runTimePath = "C:\Scripts\powershell-scratch\fileread_example.txt"
# Path for the Windows update log file (this file will be overwritten with each run).
$outputPath = "C:\Scratch\WindowsUpdate.log"
# Windows Event Log source name.
$eventLogSourceName = "MPT-GetLatestWindowsUpdateLogs.ps1"
# Windows build number - the script will only run for build numbers greater then provided.
# The windows 10 RTM build number is 10240.
$earliestBuildtoRun = 10240
function Invoke-ProcessLatestWindowsUpdateLogs {
<#
.Synopsis
Builds the Windows update logs since the last time the function ran.
.DESCRIPTION
Builds the Windows update logs from a time specified in a file and then
updates that file to contain the latest run time. This function is intended
to be run to automate the collection of the Windows update logs into a SIEM
solution such as Splunk. This function leverages the Get-WindowsUpdateLog
cmdlet to convert .etl log files into a text-based log file. This function
should be executed by an account with administrative rights.
.EXAMPLE
Invoke-GetLatestWindowsUpdateLogs -etlDirectoryPath "C:\Windows\Logs\WindowsUpdate" `
-lastRunTimeFilePath "C:\WULogScript\lastruntime.txt" `
-LogOutputSource "C:\WULogScript\WindowsUpdate.log" `
-eventLogSource "GetLatestWindowsUpdateLogs"
.etlDirectoryPath
The path to the directory containing the Windows update .etl log files.
The default location is: C:\Windows\Logs\WindowsUpdate
.lastRunTimeFilePath
The location of the file containing a timestamp of the last time the function ran. The file
should only contain the timestamp (generated using (Get-Date).toString()). The file will be
overwritten as a part of the function. If the file is not present, the user executing the
function does not have rights to the file or if the file data is invalid then a date of
1/1/2018 will be assumed and all Windows update logs written after that date will be processed.
.logOutputPath
The path for the text-based Windows update log to be written to. This file will be overwritten
the next time the function runs.
.eventLogSource
The name of the Windows Event Log source that will be instantiated in the Windows Application
Event Log. This is used to log the function's actions into a log that is assumed to be
ingested by a SIEM solution.
#>
Param (
[Parameter(mandatory=$true)]
[string]$etlDirectoryPath,
[Parameter(mandatory=$true)]
[string]$lastRunTimeFilePath,
[Parameter(mandatory=$true)]
[string]$logOutputPath,
[Parameter(mandatory=$true)]
[string]$eventLogSource
)
try {
# Test if the Windows Application Event Log source has been instantiated yet.
if(-not [System.Diagnostics.EventLog]::SourceExists($eventLogSource)) {
# Instantiate the log source.
New-EventLog -LogName Application -Source $eventLogSource
}
}
catch {
# Depending on the rights of the using invoking the function the previous
# test may throw an error which just indicates that the Log source is not
# present.
New-EventLog -LogName Application -Source $eventLogSource
}
try {
# Test is if the last run time file is valid.
if(Test-Path -Path $lastRunTimeFilePath) {
try {
# Get the content of the last run time file and convert it into a DateTime.
$fileTimeContent = Get-Content -Path $lastRunTimeFilePath
$lastRunTime = [DateTime]$fileTimeContent
}
catch {
# If there is a problem accessing the run time file or if the data does not convert into a DateTime then set the last run time to 60 days earlier and log this.
$lastRunTime = (Get-Date).AddDays(-60)
Write-EventLog -LogName Application -Source $eventLogSource -EventId 11666 -Message "Unable to access $lastRunTimeFilePath or bad last run time."
}
}
else {
# If the last run time file doesn't exist set the last run time to 60 days earlier and log this.
$lastRunTime = (Get-Date).AddDays(-60)
Write-EventLog -LogName Application -Source $eventLogSource -EventId 11667 -Message "Last run time file $lastRunTimeFilePath does not exist."
}
# Get all files with modified times greater then the last run time.
$filesToCheck = Get-ChildItem -Path $etlDirectoryPath -File | where {$_.LastWriteTime -gt $lastRunTime}
# If there are files to check then run Get-WindowsUpdateLog against them.
if($filesToCheck) {
$filesToCheck | Get-WindowsUpdateLog -LogPath $logOutputPath
$fileCheckCount = $filesToCheck.Count
}
else {
$fileCheckCount = 0
}
# Set the current run time and update the last run time file with the updated timestamp.
$currentRunTime = (Get-Date).ToString()
Set-Content -Path $lastRunTimeFilePath -Value $currentRunTime -Force
# Update the Windows Application Event Log with function run information.
Write-EventLog -LogName Application -Source $eventLogSource -EventId 11660 -Message "GetLatestWindowsUpdateLogs ran: $fileCheckCount files. Previous run time was: $lastRunTime"
return
}
catch {
Write-EventLog -LogName Application -Source $eventLogSource -EventId 11668 -Message $_.Exception
throw $_
}
}
# Run the script only on systems with OS build numbers greater then $earliestBuildtoRun.
if([Environment]::OSVersion.Version.Build -ge $earliestBuildtoRun) {
Invoke-ProcessLatestWindowsUpdateLogs -etlDirectoryPath $logPath -lastRunTimeFilePath $runTimePath -logOutputPath $outputPath -eventLogSource $eventLogSourceName
return
}