PowerShell Active Directory Scripts to Check for Service Account Lockouts and Pull Event Logs From Domain Controllers
So if you’ve ever had users repeatedly locking out a service account, you may know what a nightmare it can be to track down and fix, as well as the problems it can cause with applications or automations. While the best approach is for users to use their own accounts, in some cases (due to legacy or configuration requirements) it is not possible. Also, sometimes users who know better are the culprits, like developers.
Here are two scripts for checking and getting details on the lockouts. I recommend setting them in Task Scheduler to check every 5 minutes and alert your team.
AD_lockoutalert.ps1
########## c:\ps_scripts\ad_lockoutalert.ps1 import-module activedirectory #######variables $email ="ebruce@thedomain.com,helpdesk@thedomain.com" $mailfrom ="ebruce@thedomain.com" $mailsmtp ="mail.thedomain.com" $Reportname ="[Error] Sensitive Accounts Locked Out in Active Directory" $alertflag= $False $filepath = "c:\ps_output\checklocked.txt" ####### users to check - by AD username/samaccountname $users = @("ServiceAccount1","ServiceAccount2","ServiceAccount3") write-host $users ########### add headers "<style> p {font-family:arial;} </style>" | out-file $filepath -append "<p><b>Sensitive Accounts Locked Out in Active Directory</b></p><hr />" | out-file $filepath -append ########## Check users foreach ($user in $users){ $usertocheck = get-aduser $user -prop LockedOut $lockedstatus = $usertocheck.LockedOut $line = "[" + $lockedstatus + "] <b>"+ $usertocheck.samaccountname + ":</b> AD LockedOut status" write-host $line write-host --------------------------------------- if ($lockedstatus -eq $True){ write-host Locked out has validated to True $alertflag = $True write-host alertflag is $alertflag "<p style="color: red">$line is <b>LOCKED!</b><p></p>" | out-file $filepath -append }else{ write-host FALSE "<p>$line is <b>UNLOCKED</b></p>" | out-file $filepath -append } } ########## send mail only on Lockout = True found if($alertflag -eq $True){ send-mailmessage -to "$email" -from "$mailfrom" -smtp "$mailsmtp" -subject "$Reportname" -bodyashtml -body "$(get-content $filepath | out-string)" #-att $filepath } ###########Delete created file write-host "deleting $filepath" Remove-Item "$filepath" #While(Test-Path $filepath) {Remove-Item $filepath} #$userslocked = search-adaccount -lockedout #$userslocked | select samaccountname | write-host
Get-EventLogsLockouts.ps1
# c:\ps_scripts\get-eventlogslockouts.ps1
import-module ActiveDirectory
########### variables
$S = "DC1","DC2"
[xml]$a = Get-Content "C:\ps_scripts\getEventLogsLockouts.xml"
$filepath = "c:\ps_output\dev_Get-eventslogslockouts.txt"
$Reportname = "[Error] Event Log Lockout Details"
$email ="ebruce@thedomain.com,helpdesk@thedomain.com"
$mailfrom ="ebruce@thedomain.com"
$mailsmtp ="mail.thedomain.com"
########### Check each dc server for events
foreach ($server in $S){
Write-host Checking $server ...
$myevents = Get-WinEvent -FilterXml $a -computername $server
write-host EVENTS FROM $server
"EVENTS FROM $server"| out-file $filepath -append
$myevents = $myevents| format-list -prop message
$myevents | out-file $filepath -append
}
########## send email
$content = Get-Content $filepath
Write-host $filepath | out-string
send-mailmessage -to "$email" -from "$mailfrom" -smtp "$mailsmtp" -subject "$Reportname" -body "$(get-content $filepath | out-string)"
-att $filepath
###########Delete created file
write-host "deleting $filepath"
Remove-Item "$filepath"
The XML file
<querylist> <query id="0" path="Security"> <select path="Security"> *[System[(EventID=4740)]] and *[EventData[Data[@Name='TargetUserName']='MyServiceAccountName']]</select> </query> </querylist>