How to Clean Up Active Directory 🧹
Active Directory (AD) is one of those products that tend to get bloated. The more data you have on hand, the harder it is to do anything, from managing users to setting up AD backups. It's a product where lots of people are making changes every day 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 to be 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!
Find Disabled Accounts in Active Directory
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 which 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 : ............
Find Inactive User Accounts in Active Directory
Another usual suspect to clean up is inactive user accounts which are 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 needed. 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 also 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 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.