The Password Nobody Types
A gMSA is an Active Directory object whose password is not set by an administrator and not stored in a vault. It is derived on demand by a domain controller, handed to explicitly authorized hosts, and replaced on a fixed interval without anyone being told. In SQL Server Configuration Manager you enter CORP\gmsa-sql01$ and leave the password field empty. That empty field is the entire point: there is no value to leak in a runbook, no value to paste into a ticket, and no value that goes stale in a password manager when it rotates.
What people usually want to know, once a gMSA is actually running a production instance, is what happens on day 30, what happens when a domain controller is unreachable, and who exactly is able to read the thing. Those three questions have precise answers.
Where the Password Comes From
gMSA passwords are not stored as passwords. They are computed from a forest-wide secret called the KDS root key, using the Microsoft Group Key Distribution Service. The inputs to the derivation are:
- The KDS root key material, which lives on domain controllers in the configuration partition and never leaves them under normal operation
- The SID of the gMSA itself
- A time-based key identifier, which advances as the rotation interval elapses
Same inputs, same output. Any domain controller can produce the current password for any gMSA without that password being stored or replicated anywhere, which is why gMSA passwords do not create the replication and reset headaches ordinary service account passwords do. The derived value is several hundred bytes of key material, far past anything a password policy could reasonably require and far past anything a human would ever transcribe. Its exact length is an implementation detail. The relevant property is that nobody ever handles it.
The KDS root key is created once per forest:
# Production: create the root key and wait
Add-KdsRootKey -EffectiveImmediately
# Lab only: skip the wait by backdating the effective time
Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))
-EffectiveImmediately is the most misleading parameter name in this area. The key becomes usable roughly ten hours later, not immediately, and the delay is deliberate: it gives the key time to replicate to every domain controller in the forest, so a host that happens to talk to a different DC does not get a "no key" failure. Backdating the effective time is fine in a lab. In production, a backdated key can be handed out by a DC that has not yet received it, which is exactly the failure the wait exists to prevent.
Rotation: Every 30 Days, Without a Restart
The rotation interval is set at creation time via -ManagedPasswordIntervalInDays and defaults to 30. It is fixed for the life of the account. There is no supported way to change the interval on an existing gMSA, so if 30 days does not fit your control requirement, decide that before the account is created. Changing it later means creating a new account and moving the service to it.
When a host retrieves the managed password, the domain controller does not return a single value. It returns a structure containing the current password, the previous password once one exists, and two timing hints: how long the current password stays valid, and when the client should ask again. That is what makes rotation non-disruptive. During the changeover both the current and the previous password authenticate, so a host that has not refreshed yet is not locked out, and a ticket issued just before the change does not become invalid mid-request.
The Local Security Authority on each host handles the refresh. For SQL Server on a supported combination that means no service restart, no maintenance window, and no scheduled task. The service keeps running across a rotation it never observes.
Who Is Allowed to Read It
Retrieval is not open to the domain. The gMSA object carries a security descriptor, exposed through PrincipalsAllowedToRetrieveManagedPassword and stored in msDS-GroupMSAMembership, listing exactly which computers or groups may ask for the password. Everything else gets nothing, including domain-joined machines that would otherwise be perfectly trusted.
Three practical consequences follow, and each accounts for a sizeable share of "the service will not start" calls:
- Group membership is evaluated from the host's Kerberos ticket. Adding a machine to the allowed group and then wondering why it still fails is the classic case. The machine needs a reboot before its new group membership actually appears in its ticket. Adding the computer object directly avoids this on first setup but scales badly.
- The host needs a writable domain controller. A read-only DC cannot hand out the managed password. Branch sites, hardened DMZ segments, and anything behind a firewall that permits only a subset of AD traffic are where this bites.
- The attribute is only returned over a protected connection. The managed password is not readable over a plain, unsealed LDAP session, which is correct behaviour and occasionally surprising when someone tries to script a retrieval to "just check".
Setting One Up for SQL Server
Group managed service accounts are supported for standalone SQL Server from SQL Server 2014 on Windows Server 2012 R2 and later, and for failover cluster instances from SQL Server 2016. The cluster case is the one that actually justifies the "group" in the name: every node runs the service under the same account, so there is no per-node credential to keep aligned.
# On a machine with the AD PowerShell module, once per account
New-ADServiceAccount -Name 'gmsa-sql01' `
-DNSHostName 'gmsa-sql01.corp.example.com' `
-PrincipalsAllowedToRetrieveManagedPassword 'SQL-Hosts' `
-ManagedPasswordIntervalInDays 30 `
-ServicePrincipalNames 'MSSQLSvc/sql01.corp.example.com:1433',
'MSSQLSvc/sql01.corp.example.com'
The account name is limited to 15 characters, and the resulting sAMAccountName carries a trailing $. That dollar sign is part of the name you type into Configuration Manager, and leaving it off produces a logon failure that looks nothing like a naming problem.
On each host that will run the service:
Install-ADServiceAccount -Identity 'gmsa-sql01'
Test-ADServiceAccount -Identity 'gmsa-sql01' # must return True before you touch SQL Server
Test-ADServiceAccount is the gate. It answers exactly one question, "can this machine retrieve the password right now", and it answers it without involving SQL Server at all. If it returns False, nothing you do in Configuration Manager will help, and every minute spent looking at SQL Server is a minute spent in the wrong place.
Then set the service account in SQL Server Configuration Manager, not in services.msc, which does not grant the rights the engine expects. Enter CORP\gmsa-sql01$ and leave the password fields empty. Configuration Manager grants "Log on as a service" and the remaining privileges.
SELECT servicename, service_account, startup_type_desc, status_desc
FROM sys.dm_server_services;
What the Usual Failures Actually Mean
| Symptom | Actual cause | Check |
|---|---|---|
| Service fails to start, logon failure in the System log | Host cannot retrieve the password, or the trailing $ is missing |
Test-ADServiceAccount on the host |
Test-ADServiceAccount returns False on a new host |
Host added to the allowed group but not rebooted | Reboot, then retest |
| Fails on every host in a brand new environment | KDS root key missing or not yet effective | Get-KdsRootKey and its effective time |
| Works at HQ, fails at a branch site | Only a read-only DC reachable, or AD traffic filtered | Confirm a writable DC is reachable from the host |
| Intermittent Kerberos failures after a while | Clock skew beyond the Kerberos tolerance | Time sync against the domain hierarchy |
| Connections fall back to NTLM, delegation breaks | SPNs still registered on the old service account | SPN report against the gMSA |
That last row deserves a note. Moving a SQL Server service from a domain user account to a gMSA moves the identity the MSSQLSvc SPNs must hang off. If the SPNs stay on the old account, Kerberos stops working for that instance and everything quietly degrades to NTLM, which usually surfaces much later as a double-hop or linked server problem rather than as an obvious authentication error. Register the SPNs on the gMSA and remove the stale ones from the old account.
Where a gMSA Cannot Help You
The absence of a password is a feature right up to the point where something requires one. The cases that come up in SQL Server work:
- SQL Server Agent proxies.
CREATE CREDENTIALrequires a secret, so a gMSA cannot back a proxy account for CmdExec, SSIS, or PowerShell job steps. This is the limitation teams hit after an otherwise clean gMSA migration, and there is no workaround inside SQL Server. - Interactive logon. A gMSA cannot be used to sign in, which is correct, but it means troubleshooting "as the service account" needs a different approach than the usual runas.
- Anything outside the domain. Workgroup machines, DMZ hosts without a domain path, and cross-forest scenarios without the appropriate trust cannot retrieve the password at all.
- Products that keep a password in configuration. Backup agents, monitoring agents, and older third-party tooling frequently expect a literal password. Check before migrating, not after.
The Golden gMSA Problem
This is the part that belongs in a risk assessment and is usually missing from one. Because gMSA passwords are derived rather than stored, anyone who obtains the KDS root key material, plus the gMSA's SID and its password identifier, can compute that account's password themselves, offline.
The attack requires access that is already serious, root key material from a domain controller or from a system state backup of one, so this is not an argument against gMSA. Ordinary service accounts are worse in every respect. It is an argument about classification and monitoring:
- Treat KDS root keys as tier-0 secrets, on the same level as the KRBTGT account. Backups of domain controllers inherit that classification, including the copies sitting on a file share or a backup appliance.
- Access to the Master Root Keys container in the configuration partition should be monitored, and reads of it by anything other than a domain controller should be an alert, not a log line.
- Recovery from a confirmed root key compromise is a forest-level exercise. Rotating gMSA passwords does not help, and neither does recreating individual accounts against the same root key.
For DBAs the practical takeaway is narrow: a gMSA behind your SQL Server estate is only as trustworthy as the domain controllers and their backups. That is generally a much better trade than a shared service account password in a spreadsheet, but it is a different risk, not an absent one.
A Note on Delegated MSAs
Windows Server 2025 adds delegated Managed Service Accounts, aimed squarely at the migration problem: taking an existing user-based service account and moving it to a machine-bound managed identity without the usual rebuild. The concept is promising for exactly those SQL Server service accounts that never got migrated because nobody wanted to touch them. Early security research on the migration attributes has also shown that write access to them is highly privileged in practice, so if you plan to adopt dMSAs, treat the delegation and migration attributes as tier-0 from day one rather than as ordinary object permissions.
Checking What You Have
Two commands worth keeping. What Active Directory says about the account:
Get-ADServiceAccount -Identity 'gmsa-sql01' -Properties `
PrincipalsAllowedToRetrieveManagedPassword,
'msDS-ManagedPasswordInterval',
ServicePrincipalNames,
PasswordLastSet |
Format-List
And what your instances are actually running under, which is the number that matters when someone claims the estate was migrated:
Get-DbaService -ComputerName 'SQL01','SQL02','SQL03' -Type Engine, Agent |
Select-Object ComputerName, ServiceName, StartName, State
For the SPN side of a gMSA migration, Get-sqmSpnReport from sqmSQLTool determines the service account per instance, including a gMSA, derives the expected MSSQLSvc SPNs for hostname, FQDN, named instances, and Availability Group listeners, and writes the missing ones out as ready-to-use setspn commands plus a comment-free block that can be handed straight to the AD team. That last part matters more than it sounds: on a gMSA migration the SPN work is usually done by a different team than the SQL work, and the handover is where it stalls. Full reference: sqmSQLTool commands.
Integration with Control Matrix
Our Control Matrix covers service account and authentication controls across SQL Server infrastructure in more depth. See also Kerberos and SPN: Windows Authentication Deep Dive for how SPN registration and delegation behave once the identity is in place, and Extended Protection for SQL Server for hardening the channel that identity authenticates over.
The Bottom Line
A gMSA password is derived from a forest secret, rotated on a fixed interval that cannot be changed after creation, handed only to hosts you named explicitly, and refreshed by the LSA without restarting SQL Server. Get three things right and it is close to maintenance-free: verify retrieval with Test-ADServiceAccount before touching SQL Server, move the SPNs to the new identity, and accept that Agent proxies still need a real credential.
Then classify the KDS root key for what it is. The whole design rests on it, and a password nobody knows stays unknown only as long as the key that produces it stays where it belongs.