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 }
Hi Eric,
I have modified the script with required field. but while running below error
“Send-MailMessage : Unable to connect to the remote server”
That means the host running the script can’t find/resolve/connect to your mail server.
Hi, i need script for local users( not in AD domain). any one can help ??
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.
Thank you
Hi Eric,
Hopefully you are still monitoring your site. Is there a way that this PS script can work with Google SMTP that requires a username/password to send notifications? We’ve run in to that issue since moving from Office 365 to Gmail.
Let me know if this is possible.
What you want is authenticated SMTP. I believe these two resources will send you in the right direction:
https://www.undocumented-features.com/2018/05/22/send-authenticated-smtp-with-powershell/
https://support.google.com/mail/answer/7126229?hl=en