Service Accounts in Active Directory: Best Practices

Using service accounts managed in active directory to have detailed security control of the technical applications is a best practice. A while ago, one my clients experienced a major issue in their production environment, and this due to an expired technical service account. To anticipate similar behavior in the future and avoid further impact on other applications, we created a small PowerShell script to scan the entire or parts of the active directory for those kind of misconfigured settings.

Service accounts managed in active directory are a good solution to fine-tune your control over the scope of a technical application or process.
Some best practices for technical service accounts include:

  • Account expiration” should be disabled
  • Password expiration” should be disabled

By default, these values come deselected when creating a new account. Additionally, “User cannot change the password” can be selected as well: this obligates administrators to go through a domain administrator to change the password and thus make sure they are the only ones managing the account.

active directory service account settings

If one of the above values has not been configured correctly, the account will become disabled and the execution of the service will fail. The tricky part is that the effect won’t be visible immediately, but only after a few months!
You’ll either have to:

  • Unlock the account
  • Reset the password

Companies that are using non-automation tools for active directory to create accounts, such as, for example, runbooks. The creation of such service accounts in an active directory is a manual action that, after a while, can lead to the above-described kind of stability problems.


To anticipate this problem, it’s recommended to every now and then validate all service accounts in active directory against these best practice settings.

Execute the script in PowerShell, using an account that has read access in AD.
Change line three to the depending root or OU where you’d like to narrow down the scan.

$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.Filter = '(&(objectClass=user))'
$Searcher.SearchRoot = 'LDAP://OU=ServiceUsers,OU=Users,OU=Production,DC=production,DC=MySite'
$result = $Searcher.FindAll()
foreach($res in $result){
if(!($res.Properties.accountexpires -eq '9223372036854775807')){
Write-Host "Account with expiration date found: $($res.Properties.distinguishedname)"
$useraccontcontrol = $res.Properties.useraccountcontrol.Item(0)
$pwd_do_not_expired_enabled = $useraccontcontrol -band 65536
if($pwd_do_not_expired_enabled -eq 0){
Write-Host "Account with password expiration found: $($res.Properties.distinguishedname)"

Managed service accounts

As a small side note, I would like to refer to managed service accounts,that provide the following features to simplify service administration:

  • Requires no password management.
  • Has the ability to access the network with a computer identity in a domain environment.

More information about this topic can be found on MSDN: Service Accounts Step-by-Step Guide

Think about it!

This PowerShell script is no rocket science, yet I couldn’t find it online when bumping into the above-described issue myself. This instantly motivated me to share this information with you! Unfortunately, similar misconfiguration problems are still part of our daily reality and cause perfectly preventable issues for the (production) environments. Based on my own experience, I can say that I ran into such production issues multiple times over the last five years. So, think about how you create service accounts in your company and how such a – obviously human – error can be tackled before the account really expires, and burns down the availability of a certain application.