-
-
Save ion-storm/585436e3a91140419c5c47826200a2d5 to your computer and use it in GitHub Desktop.
PowerShell function used to collect security events from a list of servers using a start date, end date, username or domain as needed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-SecurityLogs | |
{ | |
<# | |
.SYNOPSIS | |
Pulls security logs from the given list of computers using the given date range | |
.DESCRIPTION | |
Using the computername, startdate and enddate parameters you can pull the event logs for the given computers. Once the data is collected to a variable you can alter the output as needed. | |
.EXAMPLE | |
PS>Get-SecurityLogs | |
Collects the security logs for the last day on the local machine | |
.EXAMPLE | |
PS>Get-SecurityLogs -ComputerName "DC1","SQL1","FS1" -StartDate "11/21/2016" | |
Collects the security logs from the given start date to today on all the computers in the list | |
.EXAMPLE | |
PS>Get-SecurityLogs -ComputerName "DC1","SQL1","FS1" -StartDate $((Get-Date).AddDays(-14)) -EndDate $((Get-Date).AddDays(-7)) | |
Collects the security logs from 2 weeks to 1 week ago on all the computers in the list | |
.EXAMPLE | |
PS>Get-SecurityLogs -UserName "username" -Domain "FABRIKAM" -EventID "4648","4624" | |
Check logon events for the last day pertaining to user username on the domain FABRIKAM | |
.EXAMPLE | |
PS>(Get-ADComputer -SearchBase "CN=Servers,DC=Fabrikam,DC=com").Name | Get-SecurityLogs -StartDate $((Get-Date).AddDays(-14)) -EndDate $((Get-Date).AddDays(-7)) | |
Pipeline input from Get-ADComputer for each computer in the Servers OU | |
.OUTPUTS | |
Deserialized.Selected.System.Diagnostics.Eventing.Reader.EventLogRecord | |
.NOTES | |
Britt Thompson | |
bthompson@automation.haus | |
Some code sourced from http://bit.ly/2giP9yW | |
.LINK | |
https://gist.github.com/amesritter/82e0972de5d75135b0b6ac3a9e3977e3 | |
#> | |
[CmdletBinding(SupportsShouldProcess=$true)] | |
Param | |
( | |
# ComputerName array of strings | |
[Parameter( | |
ValueFromPipeline=$true, | |
ValueFromPipelineByPropertyName=$true, | |
ValueFromRemainingArguments=$false, | |
Position=0, | |
ParameterSetName='Computer' | |
)] | |
[Alias("Computer")] | |
[string[]]$ComputerName = $env:COMPUTERNAME, | |
# Earliest date to collect logs from - last day by default | |
[Parameter()] | |
[datetime]$StartDate = (Get-Date).AddDays(-1), | |
# Latest date to collect logs from | |
[Parameter()] | |
[datetime]$EndDate = (Get-Date), | |
# Event IDs to search for - Logon / Logoff by default | |
[Parameter()] | |
[string[]]$EventID = @("4648","4647","4624","4634"), | |
# Usernames to include in the search - SubjectUserName | |
[Parameter()] | |
[string[]]$Username, | |
# Domain name to include inthe search - SubjectDomainName | |
[Parameter()] | |
[string]$DomainName | |
) | |
Begin | |
{ | |
# Get time difference in milliseconds for the XML query | |
$LTMS = ((Get-Date) - $StartDate).TotalMilliseconds | |
$GTMS = ((Get-Date) - $EndDate).TotalMilliseconds | |
$EventIDs = @() | |
foreach($ID in $EventID){ $EventIDs += "(EventID=`"$ID`")" } | |
[string]$IDs = $EventIDs -join " or " | |
if($Username -or $DomainName) | |
{ | |
# Generate the XML for all the usernames if they exist | |
$EventData = "*[EventData[" | |
if($Username) | |
{ | |
$Users = @() | |
$Username | | |
%{ | |
$Users += "Data[@Name=`"SubjectUserName`"] and (Data=`"$_`")" | |
} | |
$EventData += $Users -join " or " | |
} | |
# Append the XML for the domain name if it exists | |
if($DomainName) | |
{ | |
$EventData += " and Data[@Name=`"SubjectDomainName`"] and (Data=`"$_`")" | |
} | |
$EventData += "]] and " | |
} else { $EventData = $null } | |
} | |
Process | |
{ | |
# Process if WhatIf not present | |
if ($PSCmdlet.ShouldProcess($ComputerName)) | |
{ | |
# Build the script block to use in the invoke-command | |
$SB = { | |
# XML filter for the date range in the security log | |
[xml]$FilterXML = @" | |
<QueryList> | |
<Query Id="0" Path="Security"> | |
<Select Path="Security"> | |
$Using:EventData | |
*[System[($Using:IDs) | |
and TimeCreated[timediff(@SystemTime) <= $Using:LTMS | |
and timediff(@SystemTime) >= $Using:GTMS]]] | |
</Select> | |
</Query> | |
</QueryList> | |
"@ | |
try | |
{ | |
$ErrorActionPreference = "Stop" | |
$Events = Get-WinEvent -FilterXml $FilterXML | |
foreach ($Event in $Events) | |
{ | |
# Convert the event to XML | |
$EventXML = [xml]$Event.ToXml() | |
# Iterate through each one of the XML message properties | |
for ($i=0; $i -lt $EventXML.Event.EventData.Data.Count; $i++) | |
{ | |
# Append these as object properties | |
Add-Member -InputObject $Event -MemberType NoteProperty -Force ` | |
-Name $EventXML.Event.EventData.Data[$i].name ` | |
-Value $EventXML.Event.EventData.Data[$i].'#text' | |
} | |
} | |
$Events | Select-Object * | |
} | |
catch | |
{ | |
if($_.Exception -match "No events were found") | |
{ | |
Write-Warning "[$(hostname)] No events found" | |
} else { $_ } | |
} | |
} | |
# Run the command on all the computers in the list | |
Invoke-Command -ScriptBlock $SB -ComputerName $ComputerName | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment