3 Ways to Keep Active Directory Clean

Cleaning up the Active Directory

5 Bite-Sized Ways to Improve Your Business Every Week

Join fellow growth-minded MSPs and feed your business with new tips and tutorials delivered straight to your inbox.

Grow faster. Stress less.

Visit our Resources Center for more MSP content.
Adam Bertram      

Active Directory is one of those products that tend to get bloated. It's a product where lots of people are making changes every day to and ultimately ends up being this enormous pile of stuff that somehow still works. Even the most well-intentioned IT department always seems to end up with an Active Directory environment that's got lots of user accounts no longer needed, GPOs attached to OUs people didn't even know existed and computer accounts that represented computers long gone. This state seems to creep up on people. One day, someone sits down in front of Active Directory Users and Computers (ADUC) and has that moment where they go, "Wow! This needs cleaned up.".

Once someone in your organization has that moment, it's probably going to be a daunting and overwhelming task. You may start a project to "clean up stuff" but you'll soon find that right-clicking and deleting isn't going to cut it. There are lots of ways to make this project a success with the first task being to define what exactly "clean up" means. For this article, we're going to focus on unused user accounts. More specifically, we're going to focus on three attributes that a user account might have that would deem it "deletable." Those attributes are disabled accounts, accounts that haven't been used in X days and accounts with expired passwords.

One of the easiest ways to find these potentially unused accounts is to use PowerShell. The ActiveDirectory PowerShell is a module that includes an extremely useful cmdlet called Search-AdAccount that makes building queries and returning exactly what we need easily. Before this cmdlet can be used, however, you must download the Remote Server Administration Tools (RSAT) package from Microsoft. Once that package is installed, you should have the ActiveDirectory module, and you're ready to go! Also, for any of the below code to work, I'm assuming you're on a Windows PC that's domain-joined to the same domain as the users you'd like to find. With that being said, let's get to it!

The first task is finding disabled accounts. To find disabled accounts, we'll use the Search-ADAccount cmdlet. This cmdlet has a single parameter called Disabled that makes this task a cinch. Simply run Search-AdAccount -AccountDisabled and voila, all of your disabled accounts are shown. Notice below that I used the UsersOnly parameter because this cmdlet can also find disabled computer accounts as well.

C:> Search-ADAccount -UsersOnly -AccountDisabled -Server dc

AccountExpirationDate :
DistinguishedName : CN=Guest,CN=Users,DC=mylab,DC=local
Enabled : False
LastLogonDate :
LockedOut : False
Name : Guest
ObjectClass : user
ObjectGUID : 89cfaf2b-c6d8-4ae0-a720-e2da7d201717
PasswordExpired : False
PasswordNeverExpires : True
SamAccountName : Guest
SID : S-1-5-21-4117810001-3432493942-696130396-501
UserPrincipalName :

Another usual suspect to clean up is inactive user accounts and is a little harder to track down. "Inactive" is a subjective term so for our purposes we're going to define "inactive" as any user as having a value of LastLogonTimeStemp older than 30 days. You'll find lots of articles on the Internet about finding inactive users but some people don't realize that it's much easier than building complicated AD LDAP filters. The support is native in Search-AdAccount.

We can use Search-AdAccount -AccountInactive -UsersOnly -Timespan 30.00:00:00 to immediately find all AD user accounts that haven't been used in 30 days.

There is one caveat though. Microsoft only updates the LastLogonTimestamp attribute, which is the same as LastLogonDate, once every 14 days to prevent replication storms. Because of this characteristic of AD, using this method (or even Get-AdUser or Get-AdComputer with the advanced filter) won't be 100% accurate if you're attempting to get accounts with inactivity older than 14 days. So be forewarned.

Finally, we need to find all AD users that have an expired password that are no longer need. This one is tricky because "active" user accounts could have an expired password if it just recently expired. I not only need to find expired passwords but how long ago they expired. If they expired, say, 30 days or longer ago I can assume that these user accounts are, in fact, inactive.

To find how long ago a password expired, I first have to find the maximum password age for the domain's password policy. I can do this with the Get-AdDefaultDomainPasswordPolicy cmdlet.

$MaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.Days

Next, I can then find all user accounts that have an expired password then filter those users accounts by seeing the last time their password was last set and ensuring that was before the maximum time the password could be plus 30 (how old I'm defining the account to be).

The code will look something like this:

Search-AdAccount -PasswordExpired -UsersOnly | Where-Object {((Get-Date) - (Get-AdUser -Filter "samAccountName -eq $_.SamAccountName").PasswordLastSet) -lt ($MaxPasswordAge + 30)}

The next time you're searching AD for inactive records, be sure to look at Search-AdAccount to see if it already does what you're trying to do. It might just save you a ton of time!

Adam Bertram is a Microsoft Windows Cloud and Datacenter Management MVP and has authored various training courses, is a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at adamtheautomator.com or on Twitter at @adbertram.

5 Bite-Sized Ways to Improve Your Business Every Week

Join fellow growth-minded MSPs and feed your business with new tips and tutorials delivered straight to your inbox.