-
-
Save jlawhon/704652bc60b1c0569b6c5e853292dc99 to your computer and use it in GitHub Desktop.
A PowerShell function and format file for getting Active Directory user management events from the security event logs on domain controllers.
This file contains hidden or 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
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!-- | |
| Format type data generated 02/04/2021 08:56:49 by COMPANY\ArtD | |
| This file was created using the New-PSFormatXML command that is part | |
| of the PSScriptTools module. | |
| https://github.com/jdhitsolutions/PSScriptTools | |
| --> | |
| <Configuration> | |
| <ViewDefinitions> | |
| <View> | |
| <!--Created 02/04/2021 08:56:49 by COMPANY\ArtD--> | |
| <Name>default</Name> | |
| <ViewSelectedBy> | |
| <TypeName>ADAuditTrail</TypeName> | |
| </ViewSelectedBy> | |
| <GroupBy> | |
| <PropertyName>DomainController</PropertyName> | |
| <Label>DomainController</Label> | |
| </GroupBy> | |
| <ListControl> | |
| <ListEntries> | |
| <ListEntry> | |
| <ListItems> | |
| <ListItem> | |
| <Label>EventType</Label> | |
| <PropertyName>EventType</PropertyName> | |
| </ListItem> | |
| <ListItem> | |
| <Label>Since</Label> | |
| <PropertyName>Since</PropertyName> | |
| </ListItem> | |
| <ListItem> | |
| <Label>TargetCount</Label> | |
| <PropertyName>TargetCount</PropertyName> | |
| </ListItem> | |
| <ListItem> | |
| <Label>Targets</Label> | |
| <PropertyName>Targets</PropertyName> | |
| </ListItem> | |
| <ListItem> | |
| <Label>Administrators</Label> | |
| <PropertyName>Administrators</PropertyName> | |
| </ListItem> | |
| </ListItems> | |
| </ListEntry> | |
| </ListEntries> | |
| </ListControl> | |
| </View> | |
| </ViewDefinitions> | |
| </Configuration> |
This file contains hidden or 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
| #you might need to increase the size of the Security eventlog | |
| # limit-eventlog -LogName security -ComputerName dom2,dom1 -MaximumSize 1024MB | |
| Function Get-ADUserAudit { | |
| [cmdletbinding()] | |
| Param( | |
| [Parameter(Position=0,HelpMessage = "Specify one or more domain controllers to query.")] | |
| [ValidateNotNullOrEmpty()] | |
| [string[]]$DomainController = (Get-ADDomain).ReplicaDirectoryServers, | |
| [Parameter(HelpMessage = "Find all matching user management events since what date and time?")] | |
| [Datetime]$Since = (Get-Date).Addhours(-24), | |
| [Parameter(HelpMessage = "Select one or more user account events")] | |
| [ValidateNotNullOrEmpty()] | |
| [ValidateSet("Created","Deleted","Enabled","Disabled","Changed")] | |
| [string[]]$Events = "Created", | |
| [Parameter(HelpMessage = "Specify an alterate credential")] | |
| [PSCredential]$Credential | |
| ) | |
| Function _getNames { | |
| # a private helper function to parse out names from the eventlog message | |
| [cmdletbinding()] | |
| Param( | |
| [Parameter(Mandatory, ValueFromPipeline)] | |
| [System.Diagnostics.Eventing.Reader.EventLogRecord]$Data | |
| ) | |
| Process { | |
| #convert the record to XML which makes it easier to parse | |
| [xml]$r = $data.toxml() | |
| #Target is the user account | |
| #Subject is the admin who performed the operation | |
| $target = "{0}\{1}" -f ($r.Event.EventData.Data.Where({ $_.name -eq 'TargetDomainName'}).'#text'), ($r.Event.EventData.Data.Where({$_.name -eq 'TargetUserName'}).'#text') | |
| $admin = "{0}\{1}" -f ($r.Event.EventData.Data.Where({ $_.name -eq 'SubjectDomainName'}).'#text'), ($r.Event.EventData.Data.Where({$_.name -eq 'SubjectUserName'}).'#text') | |
| [pscustomobject]@{ | |
| Target = $target | |
| Administrator = $admin | |
| TimeCreated = $data.timeCreated | |
| } | |
| } #process | |
| } # close _getNames | |
| # a hashtable of user management event IDs for the Security event log | |
| $ADEvent = @{ | |
| UserChanged = 4738 | |
| UserCreated = 4720 | |
| UserDeleted = 4726 | |
| UserEnabled = 4722 | |
| UserDisabled = 4725 | |
| } | |
| $EventIDs = @() | |
| Switch ($events) { | |
| "Created" { $EventIDs += $adevent.getenumerator().Where({$_.name -match "created"}) } | |
| "Deleted" { $eventIDs += $adevent.getenumerator().Where({$_.name -match "deleted"}) } | |
| "Enabled" { $eventIDs += $adevent.getenumerator().Where({$_.name -match "enabled"}) } | |
| "Disabled" { $eventIDs += $adevent.getenumerator().Where({$_.name -match "disabled"}) } | |
| "Changed" { $eventIDs += $adevent.getenumerator().Where({$_.name -match "changed"}) } | |
| } | |
| #this hashtable filter will be used by Get-WinEvent | |
| $filter = @{LogName = 'Security'; ID = 0 ; StartTime = $Since } | |
| #parameters to eventually splat to Get-WinEvent | |
| $getParams = @{ | |
| ErrorAction = "Stop" | |
| FilterHashtable = $filter | |
| Computername = "" | |
| } | |
| if ($Credential.UserName) { | |
| $getParams.add("Credential",$Credential) | |
| } | |
| Write-Verbose "Searching for AD log entries since $since" | |
| #Searching the Security event log on each domain controller | |
| foreach ($dc in $DomainController) { | |
| Write-Verbose "Processing $dc" | |
| foreach ($evt in $eventIDs) { | |
| $filter.ID = $evt.value | |
| $getParams.FilterHashtable = $filter | |
| $getParams.Computername = $DC | |
| Write-Verbose "...Looking for $($evt.name) events" | |
| Try { | |
| $logs = Get-WinEvent @getParams | |
| Write-Verbose "Found $($logs.count) log records" | |
| } | |
| Catch { | |
| Write-Warning "No matching $($evt.name) events $since found on $dc." | |
| } | |
| if ($logs.count -gt 0) { | |
| $names = $logs | _getnames | |
| $targets = ($names | Select-Object -Property Target -Unique).target | |
| $admins = ($names | Select-Object -Property Administrator -Unique).administrator | |
| [pscustomobject]@{ | |
| PSTypeName = "ADAuditTrail" | |
| DomainController = $dc | |
| ID = $evt.Value | |
| EventType = $evt.Name | |
| LogCount = $logs.count | |
| Since = $Since | |
| Targets = $targets | |
| Administrators = $admins | |
| } | |
| Remove-Variable -Name logs | |
| } | |
| } | |
| } | |
| } #close function | |
| Update-TypeData -TypeName ADAuditTrail -MemberType ScriptProperty -MemberName TargetCount -Value { $($this.targets).count } -Force | |
| #the format file should be in the same folder as this file. | |
| Update-FormatData -AppendPath $psscriptroot\adaudittrail.format.ps1xml |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment