Powershell: Script to notify when users change their passwords

We’re about to start a domain migration due to some applications we have tied into Active Directory and that we are taking a phased approach to migrating we have to have user objects active in the new domain while users are still logging into the old domain.

We’ve disabled password expiry during the migration and disabled forcing migrated accounts to change their passwords. This allows our users to login to certain services thinking they are using their existing account when really they are using their migrated account in the new domain.

The only problem that comes up is if someone changes their password in the old domain. It won’t change in the new domain and then they will start getting invalid username/password when trying to login to certain services that are authenticating against the new domain.

To make things easier we’ve written a Powershell script that monitors for password changes every 4 hours (can be changed) and sends a list of users who have changed their password to our Help Desk. The Help Desk can then pro-actively contact those users and help them change their password for their account in the new domain.

Terrible right?

Anywhere here is the script I wrote. Hopefully it’s helpful for someone else.

This script requires Powershell 3.0 or newer I think so it can use ‘Get-ADUser’

 

Update 2015-08-14 – Some minor improvements to the script. A users display name is now shown in the bullet list in the e-mail body instead of their logon name. If no users are found no e-mail is sent. The new script is below.

 

#
# Powershell Script you can run on a schedule to check AD for any users who have changed their password in the last 'x' minutes
# and have the results e-mailed to you in two formats. A bulleted list (HTML e-mail support required) and a semi-colon delemited
# list for easy copy/pasting into a new e-mail.
#
# Created by: Eric schewe
# Created on: 2015-07-22
# 

# ..................................................
# ..... Start of user configuratable variables .....
# ..................................................

# E-mail settings
# Comma seperate multiple e-mail addresses for $emailTo
# Example: $emailTo = "[email protected]", "[email protected]"
$emailTo = ""
$emailFrom = "[email protected]"
$emailSMTP = "smtp.localhost.localdomain"

# Domain controller for the domain you want to look in
$domainController = "mydomain.local"

# Specify the top level OU you want to look in. By default this script will recuse through any sub-OUs
# Example: "mydomain.local/User Accounts/Staff" == "OU=Staff,OU=User Accounts,DC=mydomain,DC=local"
$searchBase = ""


# Script run interval (in minutes)
# If you're running this script every 4 hours set this to 240 (minutes). This way when the script runs again in 4 hours
# you won't get double notifications
$scriptRunInterval = 240

# ................................................
# ..... End of user configuratable variables .....
# ................................................


# Get the launch time of this script
$compareDateTime = get-date -Format s

# Convert the script run interval into hours for the e-mail we'll send
$scriptRunIntervalHours = (New-Timespan -Minutes $scriptRunInterval).Hours

# Empty arrays to populate with found users
$usersFound = @()
# Start the ordered list
$usersFound += "<ul>"
$usersFoundDL = @()

# Counter to help determine if we need to send an e-mail or not
$userCount = 0

# Get the information we need about all users in the domain
$userinfo = Get-ADuser -SearchBase $searchBase -Filter * -properties SamAccountName,PasswordLastSet,displayname -Server $domainController

foreach ($user in $userinfo) {

    if ($user.PasswordLastSet -ne $null) {

        # Get the amount of minutes between the run time of this script and the last password change time
        $timeDiff = (New-TimeSpan $user.PasswordLastSet $compareDateTime).TotalMinutes

        # If the password has been changed in the last 4 hours
        if ($timeDiff -le $scriptRunInterval) {

            $usersFound += "<li>" + $user.displayname  + "</li>"
            $usersFoundDL += $user.SamAccountName + ";"
            $userCount++

        }
    
    }

}

# End the ordered list
$usersFound += "</ul>"

# Determine if we need to send an e-mail or not
if ($userCount -ne 0) {

    # Craft the e-mail based on the user information gathered
    $emailSubject = "[Password Change Notificaton] for $compareDateTime"
    $emailBody = "The following users have changed their password in the last $scriptRunIntervalHours hours from $compareDateTime `n`r$usersFound `n`rNice and easy copy/paste DL of the found users: `n`r$usersFoundDL"

    # Send a notification for each user who has changed their password
    Send-MailMessage -To $emailTo -Subject $emailSubject -Body $emailBody -SmtpServer $emailSMTP -From $emailFrom -BodyAsHtml

}