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

}

 

5 thoughts on “Powershell: Script to notify when users change their passwords

  1. Hi Eric,

    I have modified the script with required field. but while running below error

    “Send-MailMessage : Unable to connect to the remote server”

  2. Hi Eric,

    Thanks for developing this powershell script. This is what my organization needed to keep track of users (particularly MacOS users with AD accounts) who change their password without notifying us.

    I have a question in regards to the time interval it runs and duplicate notifications on the same user. The script example shows 4 hours between runs. If the script runs again after the 4 hours, the same user (guilty of changing their pw) should not be listed when it runs again, correct?

    If I manually run the script, obviously, it will list that user multiple times of pw change. Is there some sort of flag that is cleared so the script doesn’t count their pw change again?

     

    Mark

    • I had to go re-read my script to figure out how it worked.

      You are correct in your assumption. As long as you do not run the script a second time within the interval you should not get duplicate results.

      There is no flag, it’s just some math. The script basically gets the execution date/time, gets all of the last password changes date/times for each user, subtracts the interval from the execution time and then looks at each password change date/time to see if it falls between when the script was run and when the script was run minus the interval.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.