Sunday, May 22, 2011

PowerShell, Active Directory and Expiring Passwords

Have you ever wanted to find out how many days are left until your (or someone else’s) Active Directory user account password expires? This (and just about everything else) can be done using Windows PowerShell.

Windows Server 2008 introduced a new Active Directory attribute called “msDS-UserPasswordExpiryTimeComputed”. This is a constructed attribute, which keeps track of when the password expires. Before Fine Grained Password Policies (FGPP) it used to be a simple matter of comparing the user’s pwdLastSet attribute with today’s date and subtracting it from the domain’s pwdMaxAge attribute.

I say used to be simple, because now you have to take FGPP into account. But as it turns out, it’s actually easier now, thanks to the new attribute.

Here comes the command. It looks a bit daunting at first, but broken down it’s actually quite simple.

PowerShell with the AD cmdlets:
(([datetime]::FromFileTime((Get-ADUser -Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(Get-Date)).Days

What we do here is begin with the Get-ADUser cmdlet followed by the user name, in this case AHultgren: Get-ADUser –Identity AHultgren
We also need to get the property containing the password expiration date. We do that by using the –Properties parameter and specify "msDS-UserPasswordExpiryTimeComputed".

Now if we wrap that entire command within parenthesis, we can return just the value of the attribute we need:
(Get-ADUser –Identity AHultgren –Properties "msDS-UserPasswordExpiryTimeComputed").”msDS-UserPasswordExpiryTimeComputed”

In my case the number 129538573151710728 is returned. This is not very helpful, so we need to translate the number to an actual date. We can do this by pre-fixing the command with [datetime]::FromFileTime() to convert it to a proper date:
[datetime]::FromFileTime((Get-ADUser -Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed")

This returns Wednesday, June 29, 2011 3:41:55 PM.

We could end it all here, since we now know the date the password will expire. But it can be interesting to know how many days are left. We do that by simply subtracting today’s date:
(([datetime]::FromFileTime((Get-ADUser –Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(Get-Date)).Days

Both the AD cmdlet and Get-Date must each be enclosed within parenthesis, and both commands must in turn also be enclosed within parenthesis, and then we can use “.Days” to just return the number of days. Instead of “.Days” you can pipe it all to Get-Member to show the available methods and properties you can use.

Running the final command looks like this:
PS C:\Windows\system32> (([datetime]::FromFileTime((Get-ADUser –Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(Get-Date)).Days
38

This means my password will expire in 38 days.


As an added bonus, this is how you turn a date into an Integer8 value:
(Get-Date(“2011-05-22”)).ToFileTime()
Which returns 129505176000000000.

4 comments:

  1. so how can I use this to get a list of all users?

    ReplyDelete
  2. I would like to get a list by container

    ReplyDelete
  3. You could do something like:

    $UserList = get-aduser -filter * -searchbase "OU=Users,OU=MyOrganization,DC=mycompany,DC=com" | sort-object samaccountname
    ForEach ($User in $UserList){
    $PWLeft = (([datetime]::FromFileTime((Get-ADUser –Identity $user.samaccountname –Properties "msDS-UserPasswordExpiryTimeComputed").”msDS-UserPasswordExpiryTimeComputed”))-(Get-Date)).Days
    $User.samaccountname + [char]9 + $PWLeft
    }

    ReplyDelete