When you run the Install-ADServiceAccount you may receive an error message stating that Cannot install service account. An unspecified error has occured. If you also manage to extract the internal error code from $error[0].Exception.HResult, you may get the value of -2146233088 = 0x80131500.
In my experience, the only case for this error message is that you didn't correctly allowed the local computer account on which you are trying to install the AD group managed service account (gMSA) to obtain its plaint-text password. It means you didn't specify the machine account in the list of -PrincipalsAllowedToRetrieveManagedPassword parameter values of the New-ADServiceAccount or the Set-ADServiceAccount.
The gMSA object maintains the list of allowed accounts in the access rule list of its attribute msDS-GroupMsaMembership. The listed accounts can query the msDS-ManagedPassword constructed/computed attribute for the actual clear-text managed password value which the KDS (Key Distribution Service) changes regularly. Without being able to retrieve the password, the servers which need to log on the group managed service account would not be able know its password and log the account on.
For example, in case of the local server being named as SRVWEB1 and the group managed service account's SAM login being svc-iis-finance you would correct the problem with the following command. Note that you must only add the new server account in the existing list of allowed AD principals or the other servers loose the ability to log on the account after its automatic password change. Also do not confuse the parameter -PrincipalsAllowedToRetrieveManagedPassword with another parameter -PrincipalsAllowedToDelegateToAccount:
# Note: to get current list of principals allowed to download the managed password
Get-ADServiceAccount svc-iis-finance -Properties msDS-GroupMsaMembership | Select -Expand msDS-GroupMsaMembership | Select -Expand Access | Select -Expand IdentityReference
# Note: to set the new list of AD accounts allowed to retrieve the gMSA managed password
Get-ADServiceAccount svc-iis-finance | Set-ADServiceAccount -PrincipalsAllowedToRetrieveManagedPassword 'SRVWEB1$', 'SRVWEB2$'
A bit of gMSA managed password internals for geeks
With sysinternals psexec you can also verify if the local SYSTEM account can really obtain the gMSA password. The managed password is computed dynamically anytime you query a DC over a secure connection for the constructed attribute msDS-ManagedPassword. The password is automatically changed in NTDS.DIT database by KDS periodically according to the schedule stored in msDS-ManagedPasswordInterval attribute. The change and generation process is described in detail here and here:
- the current password is always based on a KDS root key - which is the secret information known only to DCs and as such the KDS service
- on the group key identifier - which is stored permanently in the msDS-ManagedPasswordID attribute of each gMSA account
- on the SID of the gMSA acount
- as well as on the current and previous password rotation period during which the computed managed password must remain the same
In all the DC just computes a hash of all these values with the KDS root key being the primary secret and returns to the client computer in the form of msds-managedpasswordblob.
If you want to verify whether the local SYSTEM of a server can query for the msDS-ManagedPassword attribute, you can either use the AD module for powershell directly, or use more generic and direct LDAP based method:
# Note: obtain the gMSA managed password with direct LDAP method over a secure connection
psexec -s -i -d powershell
$svc = [ADSI] 'LDAP://cn=svc-iis-finance,CN=Managed Service Accounts,DC=gopas,DC=virtual'
$svc.AuthenticationType = 'Sealing,Secure'
$svc.RefreshCache('msDS-ManagedPassword')
$svc.'msDS-ManagedPassword'.Value
# Note: obtain the gMSA managed password with AD module for PowerShell
psexec -s powershell -Command "Get-ADServiceAccount svc-iis-finance -Properties msDS-ManagedPassword"
From the output, the current random binary password is obtained like the following (the structure is well documented here). Note that it is actually a 256 byte long random password which cannot be written from keyboard because it contains just random bytes. It constitutes 128 unicode characters random password (excluding zeros which get converted to 00-01). Just like the domain controller machine accounts use - nothing that one would be able to type manually into a logon dialog box (my friend Michael Grafnetter was able to verify the hash extracted from inside AD database):
$gmsaBlob = $svc.'msDS-ManagedPassword'.Value
[UInt16] $pwdOffset = [BitConverter]::ToUInt16($gmsaBlob[8..9], 0) # Note: this value must not be 0x0000
[UInt16] $previousPwdOffset = [BitConverter]::ToUInt16($gmsaBlob[10..11], 0) # Note: if this value is 0x0000 then the account does not have any previous password
$pwdEnd = $pwdOffset
while (($gmsaBlob[$pwdEnd] -ne 0) -or ($gmsaBlob[$pwdEnd + 1] -ne 0)) { $pwdEnd += 2 }
[byte[]] $gmsaPwd = $gmsaBlob[$pwdOffset..$pwdEnd]
[BitConverter]::ToString($gmsaPwd)
When you install the group managed service account on a workstation or server, the current password is retrieved from the AD attribute msDS-ManagedPassword using the previously described method and saved locally in registry in the form of machine LSA secret in the HKLM\Security\Policy\Secrets as part of _SC_GMSA_{GUID} secret.
If you want to see the LSA secrets decrypted from a running local computer, I have a sample source code of PowerShell Get-LsaSecret in my ADLAB package (ZIP form here).