Service account hardening: gMSA, SPNs and LAPS
A practical guide to replacing risky service accounts with gMSA/dMSA, cleaning SPN exposure, fine-grained password policies, and Windows LAPS.
Standard service accounts are one of the most persistent weak points in Active Directory: static passwords that rarely rotate, credentials embedded in scripts and config files, and Service Principal Names that turn ordinary user accounts into offline password-cracking targets. Most of this risk has a direct, supported fix in modern Windows Server — the barrier is usually migration effort, not missing tooling. This guide covers the practical path from standard service accounts to managed ones, plus the password-policy and local-admin controls that round out the picture.
Why standard service accounts are a liability
A typical legacy service account is a normal user object with Password never expires set, a password chosen once at provisioning and rarely changed, and often reused across multiple applications because rotating it means coordinating downtime with every consumer. If that account also has a Service Principal Name (SPN) registered, it becomes a Kerberoasting target: any authenticated domain user can request a Kerberos service ticket for it and attempt to crack the ticket's encrypted portion offline, with no logon attempt and no lockout trigger.
Group Managed Service Accounts (gMSA) and, in Windows Server 2025, delegated Managed Service Accounts (dMSA) solve the underlying problem: AD generates and rotates a 240-byte (120-character) random password automatically, no human ever knows it, and it can't be reused elsewhere because it was never chosen by a person in the first place.
Migrating to gMSA
Prerequisites
- gMSA needs the Windows Server 2012 (or later) schema and at least one DC running Windows Server 2012 or later; there is no functional level requirement. dMSA requires Windows Server 2025 domain controllers.
- The KDS Root Key must exist before the first gMSA can be created.
# One-time forest setup — check if a KDS root key already exists
Get-KdsRootKey
# If none exists, create one. In production, allow the 10-hour replication
# safety window rather than backdating it:
Add-KdsRootKey -EffectiveImmediately
# Lab only (single DC): Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))Create and deploy a gMSA
# Create a gMSA scoped to the hosts allowed to use it
New-ADServiceAccount -Name "svc-sqlapp" `
-DNSHostName "svc-sqlapp.corp.example.com" `
-PrincipalsAllowedToRetrieveManagedPassword "SQLAppServers" `
-Enabled $true
# On each authorized host, install the gMSA
Install-ADServiceAccount -Identity "svc-sqlapp"
# Verify the host can retrieve the managed password
Test-ADServiceAccount -Identity "svc-sqlapp"Configure the consuming service (e.g., a Windows Service, IIS Application Pool, or scheduled task) to run as CORP\svc-sqlapp$ with no password — the OS retrieves and rotates it transparently.
# Point an existing Windows service at the gMSA
sc.exe config "MyAppService" obj= "CORP\svc-sqlapp$"dMSA for hard-to-migrate accounts (Server 2025)
dMSA is designed specifically for accounts you can't cleanly re-point at a new identity — Windows can link a dMSA to the original standard service account and transparently redirect Kerberos authentication, easing migration for services that hard-code an account name.
# Create a dMSA linked to an existing standard service account for migration
New-ADServiceAccount -Name "svc-sqlapp-dmsa" -DNSHostName "svc-sqlapp-dmsa.corp.example.com" `
-CreateDelegatedServiceAccount -KerberosEncryptionType AES256
# Link it to the legacy account and start the migration
Start-ADServiceAccountMigration -Identity "svc-sqlapp-dmsa" `
-SupersededAccount "CN=svc-sqlapp,OU=Service Accounts,DC=corp,DC=example,DC=com"The full migration sequence (start, let the hosts pick up the dMSA, then complete) is covered in Migrating service accounts to gMSA and dMSA. Test it in a lab before touching production service accounts.
SPN hygiene
Audit every SPN registered on a user object (not a computer or gMSA object) — these are the Kerberoastable set:
Get-ADUser -Filter { ServicePrincipalName -like "*" } -Properties ServicePrincipalName |
Select-Object SamAccountName, ServicePrincipalNameFor each result:
- Identify the service and owning team.
- Migrate the service to run as a gMSA/dMSA where the application supports Group Managed Service Accounts (most modern SQL Server, IIS, and Windows Service hosting scenarios do).
- Where migration isn't yet possible, enforce a long (25+ character), random password via a dedicated Fine-Grained Password Policy (below), and rotate it.
- Remove the SPN entirely from any account where the associated service no longer exists — stale SPNs are common after application decommissioning.
# Remove a stale SPN
Set-ADUser -Identity "svc_oldapp" -ServicePrincipalNames @{Remove="MSSQLSvc/oldapp.corp.example.com:1433"}Fine-grained password policies (PSOs)
The domain's single default password policy is usually too weak for privileged and service accounts but too strict to impose on every user. Fine-Grained Password Policies let you layer stricter requirements onto specific groups without changing the domain default.
New-ADFineGrainedPasswordPolicy -Name "PSO-ServiceAccounts" `
-Precedence 10 `
-MinPasswordLength 32 `
-PasswordHistoryCount 24 `
-MaxPasswordAge "180.00:00:00" `
-MinPasswordAge "1.00:00:00" `
-ComplexityEnabled $true `
-ReversibleEncryptionEnabled $false
Add-ADFineGrainedPasswordPolicySubject -Identity "PSO-ServiceAccounts" -Subjects "SVC-Accounts-NonMigrated"
New-ADFineGrainedPasswordPolicy -Name "PSO-Tier0Admins" `
-Precedence 5 `
-MinPasswordLength 20 `
-MaxPasswordAge "60.00:00:00" `
-ComplexityEnabled $true
Add-ADFineGrainedPasswordPolicySubject -Identity "PSO-Tier0Admins" -Subjects "Tier 0 Admins"Lower Precedence values win when an account is subject to multiple PSOs. Verify effective policy per account:
Get-ADUserResultantPasswordPolicy -Identity "svc_oldapp"Consider a banned-password approach as well — either a third-party password-filter DLL or Entra Password Protection's on-premises agent — so both human and any remaining human-set service account passwords are checked against a compromised/common-password list at set time, not just a complexity regex.
Windows LAPS for local admin passwords
Local administrator passwords shared across a machine fleet are a lateral-movement multiplier — one leaked local admin password can unlock every machine that shares it. Windows LAPS (built into Windows Server 2019+ and Windows 10/11 with the update, replacing the legacy LAPS CSE) randomizes and rotates the local administrator password per machine and stores it encrypted in AD.
# Extend the schema (one-time, run on a schema master)
Update-LapsADSchema
# Configure via GPO: Computer Configuration → Policies → Administrative Templates → System → LAPS
# Set "Configure password backup directory" to Active Directory (nothing happens until this is set),
# then "Password Settings", and "Enable password backup for DSRM accounts" on DCs as needed
# Set OU permissions so only authorized admins can read the encrypted password
Set-LapsADReadPasswordPermission -Identity "OU=Workstations,DC=corp,DC=example,DC=com" -AllowedPrincipals "Tier2-Helpdesk-Admins"
# Verify a machine is reporting its LAPS password
Get-LapsADPassword -Identity "WKS-01" -AsPlainTextNote: DSRM and DC local admin credential handling is a distinct topic. Windows LAPS can manage the DSRM password on domain controllers, as described in Windows LAPS deployment; see also the DC-specific guidance rather than applying workstation LAPS scope assumptions to domain controllers.
Verification checklist
# Confirm no user accounts hold SPNs outside an approved exception list
Get-ADUser -Filter { ServicePrincipalName -like "*" } -Properties ServicePrincipalName
# Confirm gMSA accounts are retrievable by their intended hosts
Test-ADServiceAccount -Identity "svc-sqlapp"
# Confirm PSO is applied to the intended group
Get-ADFineGrainedPasswordPolicySubject -Identity "PSO-ServiceAccounts"
# Confirm LAPS is actively rotating on a sample of machines
Get-LapsADPassword -Identity "WKS-01" | Select-Object PasswordUpdateTime, ExpirationTimestampWhat it breaks
- Applications that don't support gMSA. Some legacy or third-party software insists on an interactive-style account with a settable password and can't consume a computer-account-style identity. These stay on standard accounts, isolated behind the strictest PSO you can apply, until the vendor adds support.
- Cross-forest or cross-domain service usage can complicate gMSA deployment, since retrieval depends on KDS root key replication and group membership resolution within scope.
- Hard-coded credentials in scripts or config files referencing the old account's password will break outright once you rotate to a gMSA with no static password — audit for these before cutting over, not after.
- Helpdesk workflows built around shared local admin passwords will need to change once Windows LAPS enforces per-machine uniqueness; document the new retrieval process (
Get-LapsADPassword) for support staff.
This guide intentionally does not cover krbtgt password rotation — that has its own cadence and blast-radius considerations and is covered in a dedicated guide. See also Kerberos hardening for the broader Kerberos configuration this sits alongside.
Frequently asked questions
What's the real security benefit of a gMSA over a standard service account?
A group Managed Service Account has a 240-byte (120-character) random password that Active Directory automatically rotates roughly every 30 days, and the password is never known to or typeable by a human. That removes the two biggest risks of standard service accounts: static, often-weak passwords and password reuse across systems.
Does removing a Service Principal Name from a user account stop Kerberoasting entirely?
It stops that specific account from being a Kerberoasting target, since there's no SPN to request a service ticket against. But Kerberoasting targets any account with an SPN, so the fix is systemic: audit all SPNs on user accounts, migrate the associated services to gMSA/dMSA where possible, and enforce long, random passwords on any SPN-bearing account you can't migrate.
What is the difference between a gMSA and a dMSA?
A gMSA (group Managed Service Account) is the long-standing option, usable by multiple hosts, with AD-managed automatic password rotation. A dMSA (delegated Managed Service Account, new in Windows Server 2025) is designed as a drop-in migration target for existing standard service accounts, letting Windows automatically redirect authentication from the old account to the new managed one during migration.
Service account hardening: gMSA, SPNs and LAPS