Thursday, May 31, 2012

Active Directory Account Lockout Notifications using PowerShell

I've found it's often helpful to get an email notification when an Active Directory account is locked out. In a previous job we used Account Lockout Examiner from NetWrix for this functionality. A few years and a job or two later and I've found a way to do this with the Windows Task Scheduler and PowerShell. You also need to have a Windows Server 2008 Domain Controller. Your Active Directory domain does not need to be in 2008 Native Mode.

Before going on, I should mention that the following scripts were originally created by Joe0126 and shared in this post on the SpiceWorks Community site. I simply took what Joe0126 created and updated the output to meet my needs. The email notification will look like this:

Subject: Account Locked Out: ADDOMAIN\username
Email Body:
Account Name: ADDOMAIN\username
Workstation: ADCOMPUTERNAME
Time: 05/28/2012 17:45:43


In the case of an account lock event, the workstation will tell you what computer or server the account was locked out on. Usually this will be the user's workstation or one of your Exchange CAS servers. If the lockout happened on a computer that isn't joined to the domain workstation will be blank.

The account unlock notification is slightly different. The workstation will be the workstation AD Users and Computers is running on, and who is responsible for unlocking the account will be in the notification as well.

Subject: Account Unlocked: ADDOMAIN\username
Email Body:
Account Name: ADDOMAIN\username
Workstation: somecomputer.domain.com
Time: 05/29/2012 11:03:31

Unlocked By:
ADDOMAIN\someadmin


To start, grab the code for the scripts below. One will generate an email notification for an account lock event, the other will generate an email notification for an account unlock event. Update the script with the SMTP server and email addresses for your domain (update lines with domain.com) and save them to your Domain Controller.

On your domain controller, open Task Scheduler and create a new task (Not create basic task). Your trigger should be "On an Event." Select the Security Log and enter 4740 for the EventID. EventID 4740 is an Account Lock. For your action run your PowerShell Script. For the unlock notification, do the same for EventID 4767 and use the Unlock Notification Script.

Notifications won't be instantaneous as PowerShell's get-eventlog commandlet isn't very fast when it comes to finding events in the Windows log, but it has been fast enough for our environment. In most cases we get the account lockout notification before the user calls the helpdesk to report a problem.

Account Lock Notification Script:
$SMTPServer = "mail.example.com"
$MailFrom = "no-reply@example.com"
$MailTo = "account-lockout-notifications@example.com"

Import-Module activedirectory

$Event=Get-EventLog -LogName "Security" -InstanceId "4740" -Newest 1000

$User = $Event.ReplacementStrings[0]

$Computer = $Event.ReplacementStrings[1]

$Domain = $Event.ReplacementStrings[5]

$MailSubject= "Account Locked Out: " + $Domain + "\" + $User

$MailBody = "Account Name: " + $Domain + "\" + $User + "`r`n" + "Workstation: " + $Computer + "`r`n" + "Time: " + $Event.TimeGenerated + "`r`n"

$lockedAccounts = Search-ADAccount -LockedOut | Select -Property SamAccountName | Out-String

$MailBody = $MailBody + "`r`nThe following accounts are currently locked out:`r`n" +  $lockedAccounts

Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -SmtpServer $SMTPServer -Body $MailBody

Account Unlock Notification Script:
$SMTPServer = "mail.example.com"
$MailFrom = "no-reply@example.com"
$MailTo = "account-lockout-notifications@example.com"




Import-Module activedirectory

$Event=Get-EventLog -LogName "Security" -InstanceId "4767" -Newest 1000

$User = $Event.ReplacementStrings[0]


$Domain = $Event.ReplacementStrings[1]

$UnlockBy =  $Event.ReplacementStrings[4]


$UnlockByDomain = $Event.ReplacementStrings[5]

$Computer = $Event.MachineName

$MailSubject= "Account Unlocked: " + $Domain + "\" + $User

$MailBody = "Account Name: " + $Domain + "\" + $User + "`r`n" + "Workstation: " + $Computer + "`r`n" + "Time: " + $Event.TimeGenerated + "`r`n`r`n Unlocked By: " + $UnlockByDomain + "\" + $UnlockBy

Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -SmtpServer $SMTPServer -Body $MailBody

For the extra lazy, unlock everyone:
Import-Module activedirectory
Search-ADAccount -LockedOut | Unlock-ADAccount

Update 1, 2012-06-18: I added the Unlock notification to all our Server 2008 R2 domain controllers. We were only getting notifications when an account was unlocked on the domain controller running the script. I don't think this is a similar issue with the lock notification script.

Update 2, 2014-12-29: Checked this post and found I've made a few more improvements since my last posting. Configuration for mail server is now at the top, and I added a line to get all locked accounts to the lock notification, just in case your IT Service Desk missed a few accounts. Also added PowerShell to unlock all locked accounts. Use with caution obviously.