In enterprise Active Directory environments, service accounts often appear identical to regular user accounts in their basic attributes. Both account types share the same objectClass
(user) and similar schema attributes, making automated differentiation challenging.
Most organizations use these approaches, often in combination:
// PowerShell example to find accounts with "Service Account" in description
Get-ADUser -Filter {Description -like "*Service Account*"} -Properties Description |
Select-Object Name,SamAccountName,Description
- Organizational Unit (OU) Structure: Dedicated OUs like "ServiceAccounts" or "Non-Interactive"
- Naming Conventions: Prefixes like "svc_", "sa_", or "app_"
- Account Description Field: Explicit "SERVICE ACCOUNT" markers
- Password Policies: "Password never expires" flag enabled
Microsoft suggests these technical markers for service accounts:
# Recommended AD attributes to modify for service accounts
Set-ADUser -Identity "svc_sql" -ServicePrincipalNames "MSSQLSvc/sql01.contoso.com" -Description "SQL Service Account"
For enterprises needing robust identification:
- Extend the AD schema with custom attributes
- Use the
msDS-ServiceAccount
attribute for managed service accounts - Leverage group membership in dedicated "ServiceAccounts" groups
This PowerShell function identifies potential service accounts:
function Get-ADServiceAccounts {
param([string]$SearchBase = "OU=ServiceAccounts,DC=contoso,DC=com")
$serviceAccounts = @()
# Check naming convention
$serviceAccounts += Get-ADUser -Filter {SamAccountName -like "svc_*"} -SearchBase $SearchBase
# Check description field
$serviceAccounts += Get-ADUser -Filter {Description -like "*Service Account*"} -SearchBase $SearchBase
# Check password policy
$serviceAccounts += Get-ADUser -Filter {PasswordNeverExpires -eq $true} -SearchBase $SearchBase |
Where-Object {$_.SamAccountName -notlike "Admin*"}
return $serviceAccounts | Sort-Object -Unique -Property DistinguishedName
}
For modern Windows environments, gMSA provides built-in differentiation:
# Creating a group managed service account
New-ADServiceAccount -Name "gmsa_websvc" -DNSHostName "websvc.contoso.com"
-PrincipalAllowedToRetrieveManagedPassword "IIS_Servers"
In Active Directory environments, service accounts often get created with identical attributes as regular user accounts, making automated identification difficult. While organizations implement various ad-hoc solutions (OU placement, description fields, password policies), there's no single standardized approach that works across all scenarios.
Here are several programmatic ways to distinguish service accounts:
# PowerShell example: Find accounts with "svc_" prefix and never-expiring passwords
Get-ADUser -Filter {Enabled -eq $true -and PasswordNeverExpires -eq $true} -Properties Description |
Where-Object {$_.SamAccountName -like "svc_*" -or $_.Description -like "*Service Account*"}
The most maintainable approach combines multiple attributes:
- Naming Convention: Prefix like "svc_", "sa_", or "adm_" (e.g., svc_sqlprod01)
- Custom Attribute: ExtensionAttribute1-15 for service-specific metadata
- Password Policies: PasswordNeverExpires=true (with compensating controls)
- Group Membership: Dedicated "Service Accounts" security group
This PowerShell script tags service accounts using a standard attribute:
# Set serviceAccount flag on identified accounts
$serviceAccounts = Get-ADUser -Filter * -Properties Description |
Where-Object {$_.Description -match "service account" -or $_.Name -like "sa_*"}
foreach ($account in $serviceAccounts) {
Set-ADUser -Identity $account -Replace @{extensionAttribute1="serviceAccount"}
Write-Output "Tagged $($account.SamAccountName) as service account"
}
When implementing identification methods:
- Audit service account usage quarterly
- Implement Just-In-Time access for privileged service accounts
- Use Group Managed Service Accounts (gMSA) where possible
Example organizational unit hierarchy:
DC=corp,DC=com
├── OU=Users
│ ├── OU=Standard
│ └── OU=Privileged
└── OU=ServiceAccounts
├── OU=Application
├── OU=Database
└── OU=ScheduledTasks