PowerShell Least privilege automation
Automation accounts accumulate privilege because it is easier to add Domain Admin than to work out which four rights a script needs. That is how one compromised scheduled task becomes a domain-wide problem.
Documentation: Microsoft Learn
Overview
Group Managed Service Accounts are the answer on Windows. Active Directory holds and rotates the password, so it never appears in a script, a config file or a password manager. Create with New-ADServiceAccount, allow the target machines to retrieve the password with -PrincipalsAllowedToRetrieveManagedPassword, then install it on each machine with Install-ADServiceAccount.
Where a gMSA does not fit, use SecretManagement with a vault rather than a credential in a file. Export-Clixml encrypts with DPAPI tied to one user on one machine, which is better than plaintext but is not a secret store and does not survive a machine rebuild.
Rights should be scoped to the OU or the resource, and read-only where reading is all that is needed. Deny interactive logon on service accounts so a stolen credential cannot be used at a console. Log what the account does, so you can tell normal from abnormal.
Start by auditing what your existing automation accounts actually use. It is usually far less than what they hold.
Inspect this example’s structure
Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.
$account = [pscustomobject]@{
Type = 'gMSA'
Name = 'svc-Reporting$'
Password = 'managed by AD, rotated automatically'
Rights = 'read-only on the reporting OU'
Interactive = 'denied'
}
$account | Format-List- Stage 1$account
Positional values or no named parameters - Stage 2Format-List
Positional values or no named parameters
An example to inspect
Preview the example. Sign in for the full lesson and activities.
$account = [pscustomobject]@{
Type = 'gMSA'
Name = 'svc-Reporting$'
Password = 'managed by AD, rotated automatically'
Rights = 'read-only on the reporting OU'
Interactive = 'denied'
}
$account | Format-ListWhat happens
This prints the shape of a properly scoped service account. The trailing dollar sign in the name marks it as a machine-type account, which is how gMSAs appear in AD. The three properties after it are the ones that matter: no stored password, rights limited to one OU, and no interactive logon.
Worth remembering
- gMSA passwords are held and rotated by AD, never by you.
- Use SecretManagement with a vault where a gMSA does not fit.
- Export-Clixml is DPAPI-bound to one user on one machine.
- Scope rights to the OU, and deny interactive logon.
Primary documentation
Try it
Illustrative output · values vary by environment
Example reader
Inspect this page's example
Run supported commands against the practice data, or inspect the example without executing it.
Ready to inspect.
Prints the properties of a least-privilege service account.
Show reference output
Illustrative output · values vary by environment
Type : gMSA Name : svc-Reporting$ Password : managed by AD, rotated automatically Rights : read-only on the reporting OU Interactive : denied