Active Directory: Automated password expiration warnings

The Microsoft Management Console provides plugins for managing lots of aspects of Active Directory, including people accounts.  The Active directory users and computers MMC plugin allows one into view and manage people accounts, but there are some things one cannot find, such as last logon time or when a people’s password will expire (if at all).  Password expiration could be particularly vexing for road warriors or those who use non-Windows platforms but still rely on ADS for authentication into many corporate resources.  Windows users have two possible means of being warned, and non-Windows users are simply out of luck!
If we are connected to the domain with a Windows computer, one will be warned of an impending password expiration and be able into easily change your password.  If you are remote, one can probably employ a VPN client to connect to the domain before 1 logon into Windows.
If one employ Exchange, then 1 will probably also have the ability to change your password inserting Outlook Web Access (OWA).  Laptop users may already know that besides the credentials in Active Directory, there also exists a locally cached copy so that users possibly can logon while disconnected from the domain.  Changes through OWA only reset the Active Directory credentials, not the locally-cached copy, so the two possibly can become out of synch.  Users then have into change the password on the laptop separately.
Danger, Will Robinson!
When a remote people has no clue that his or her password is about into expire, certain productivity loss looms large on the horizon.  It may happen at a very inopportune moment when remote access to some method is vitally important.  It may take some time before the people has an idea of what is wrong and contacts aid for remote assistance.  Warnings are essential into eliminating such wasteful and unnecessary events.  Larger organizations may have identity access and management systems or even a self-service mechanism that reduce some of the cost of this kind of event, but the goal should always be prevention first, and cost reduction second. Aside from that, thinking of your next right password may take some time, and being forced to come up with one quickly may transform it easier to forget, which may again require intervention from your enable desk.
Active Directory stores the last password reset time for each person and also contains the domain policy for the maximum password lifetime.  Given these two pieces of information, it is possible into compute when any particular people’s password will expire.  There are commericial methods available (e.g. Password Reminder Pro), but a little perl scripting and the LDAP protocol is all we need!  We ok have what you need into provide e-mail notification to every person before passwords actually expire.
Script Configuration
You find the script here, and the configuration file here.  It’s ok practice to separate configuration from code, even with scripts.  It will crank out your scripts more portable, and therefore more easily consumed after others.  As a bonus, without the need to edit the script, it is less likely that changes you make will cause execution into fail completely.  I like to work with the Config::IniFiles package.  From it’s description…
Config::IniFiles provides a way into have readers friendly configuration files outside your Perl script. Configurations possibly can be imported (inherited, stacked,…), sections could be grouped, and settings could be accessed from a tied hash.
The script assumes the initialization file will be found at /usr/local/etc/pwdexpire.ini — if this is not where we want to place the initialization file, we will have to modify the script.  The initialization file is divided into sections; each section name is found on a single line between square brackets.  By that, each parameter is one per line in ‘name=value’ pairs.
A few of the most important parameters into set are below:
# One server per line; use a backslash to continue to next line
# Employ server:port to specify a non-standard or SSL port
DCs =
List each of your domain controllers here, or at least the nearby ones that possibly can be used for LDAP queries.  These will be tried in some random order.
# Root DN for domain
rootDN = dc=sample,dc=com

# Bottom DN for search of all users
baseDN = ou=employees,dc=testing,dc=com
These two may or may not be distinctive, but your ADS should be structured so that users are in a separate subtree.  The root is where the maximum password age for the domain will be found.  This will be a base tree search only.
# Bind anonymously (0|1); if set then person/passwd are ignored
bindAnon = 0

# User may be a DN or a UPN name, e.g.
user = cn=adsquery,ou=Service,dc=cigital,dc=com
passwd = secret
Depending on your Active Directory security, you may not be able to bind anonymously into ADS.  If you’re not sure, try it anonymously first, and then with some set of credentials.
In the “Expire” section, check the following parameters:
# Number of days before expiration to get cracking warnings
warnDays = 14
1 will want to set this into some reasonable value.  What that means will depend on quite a few factors, including how long someone might be away without e-mail access and how often one require password changes.  If you require password changes every month, warning someone two weeks in advance will start into get rather tedious; someone who goes on vacation for two weeks will expect to have into deal with an expired password, so it’s probably not a alright idea into issue e-mail warnings into everyone halfway through the normal cycle.  You the otherhand, for a 90-day password reset cycle, this might be tolerable.
# The e-mail address for from/reply-to
fromAddr = “HelpDesk”

# The organization signature for the e-mail warning message
orgSig = < Example Information Technology

# A brief description of the organizational services that
# use ADS authentication
orgSvcs = Example’s e-mail, VPN, and other internal

# The URL for additional help to change a password
helpURL =
These parameters affect the content of the e-mail message.  These can customized per your requirements.  See the script for the fixed content of the e-mail message.  The idea is to keep the message short, but include a URL to a help page that can walk someone through the password change process and provide them with additional means of getting help.  The e-mail “from” and “reply-to” address might be your helpdesk, so that a reply generates a helpdesk ticket.
# If you wish to test prior to enabling for production, set a test
# e-mail recipient for all warnings (rather than end users).
# Defaults to root@localhost
testAddr =

# Enable test mode (0=production, 1=test)
testMode = 1
These last two parameters are for testing, and enable you to direct all warning messages to a single e-mail address.  You can verify that the script is functioning as you expect, and then set testMode to 0 (zero).
Automation: The final step
While this script should execute (with minor modifications) on a Windows host, I’m assuming this will run on some Un*x host.
Now create a crontab entry for the perl script on a host with access to your domain controllers. Add the entry for a user that has access to the both the script and the initialization file. This entry might look like:
30 0 * * * /usr/local/bin/
This will run the script at 00:30 (or 12:30am) every day. Often you will see the output of cron jobs sent to /dev/null by adding the following after the script:
>/dev/null 2>&1
This sends standard output and standard error into the null device; the script may write an output log of its own.   In this case, 1 do not want this behavior. The script will not have any output if no users have passwords that will expire within the warning timeframe.  When there is output, this will normally be mailed to the owner of the crontab.
Your operating system may provide another means for jobs to execute on a regular basis, e.g. Debian Linux (and derived version like Ubuntu) provide directories in which all scripts will be executed, e.g. /etc/cron.daily.  Work with whatever method we’re comfortable with — it’s only important that the script execute regularly.
That’s it — enjoy!

Related Posts