Rotate Service Accounts
Overview
This guide covers JIT credential rotation for Active Directory service accounts — accounts used by Windows services, scheduled tasks, or applications to authenticate against AD resources.
Two rotation patterns are available:
- Password-only — rotates the AD account password. Use this when the consuming application reads credentials from a secrets store or Britive at startup and the service does not need to be restarted.
- Password + service update — rotates the AD account password and immediately updates the Windows service logon credential on the remote host via WinRM, then optionally restarts the service.
Unlike user account rotation (the -a account pattern), service account rotation uses Britive to push a new password to AD — no credential is returned to the end user.
Before You Begin
- The Britive Access Broker is running (see Getting Started)
- The broker gMSA has the following delegations on the service account OU:
- Reset Password
- Write
userAccountControl(enable/disable) - Write
lockoutTime(unlock) - Write
pwdLastSet(disable force-change-at-logon)
- RSAT Active Directory module installed on the broker host
- For the service update pattern: WinRM/PSRemoting enabled on all target servers, and the broker gMSA has remote administration rights on those servers
Pattern 1 — Password Rotation Only
Full script: Active Directory/rotate/rotate-ad-account.ps1
Rotates the AD account password. The new password is not returned to the requesting user.
Environment variables: AD_TARGET_USER (SamAccountName), AD_NEW_PASSWORD
$adUser = Get-ADUser -Identity $env:AD_TARGET_USER -ErrorAction Stop
$SecurePass = ConvertTo-SecureString $env:AD_NEW_PASSWORD -AsPlainText -Force
Set-ADAccountPassword -Identity $env:AD_TARGET_USER -NewPassword $SecurePass -Reset -ErrorAction Stop
# Unlock and disable force-change-at-logon
Unlock-ADAccount -Identity $env:AD_TARGET_USER -ErrorAction SilentlyContinue
Set-ADUser -Identity $env:AD_TARGET_USER -ChangePasswordAtLogon $false -ErrorAction StopPattern 2 — Password Rotation + Windows Service Update
Full script: Active Directory/rotate/rotate-ad-service-account.ps1
Rotates the AD account password and updates the Windows service logon credential on the remote server via PSRemoting (WinRM). Optionally restarts the service so the new credential takes effect immediately.
Environment variables:
| Variable | Required | Default | Notes |
|---|---|---|---|
AD_TARGET_USER | Yes | — | SamAccountName of the service account |
AD_NEW_PASSWORD | Yes | — | New password to set |
AD_TARGET_SERVER | Yes | — | Hostname or FQDN of the server running the service |
AD_SERVICE_NAME | Yes | — | Windows service name (e.g. MySvc) |
AD_RESTART_SERVICE | No | true | Set to false to skip restart |
AD password rotation:
Set-ADAccountPassword -Identity $TargetUser -NewPassword $SecurePass -Reset -ErrorAction Stop
Unlock-ADAccount -Identity $TargetUser -ErrorAction SilentlyContinue
Set-ADUser -Identity $TargetUser -ChangePasswordAtLogon $false -ErrorAction StopService credential update via WinRM:
Invoke-Command -ComputerName $TargetServer -ScriptBlock {
param($svcName, $svcAccount, $svcPassword, $shouldRestart)
# Update service logon credential using sc.exe
sc.exe config $svcName obj= $svcAccount password= $svcPassword
if ($shouldRestart) {
Stop-Service -Name $svcName -Force
Start-Service -Name $svcName
}
} -ArgumentList $ServiceName, $serviceAccount, $NewPassword, $RestartServiceConfigure in Britive
Create the password-only permission
Go to Resource Manager → Resource Type Permissions → New Permission. Set Language to PowerShell.
Paste rotate-ad-account.ps1 as the checkout routine. Leave the checkin field empty.
Declare variables — AD_NEW_PASSWORD must be system-generated (never static):
| Variable | Notes |
|---|---|
AD_TARGET_USER | SamAccountName of the service account |
AD_NEW_PASSWORD | Generated by Britive at checkout |
Create the service-update permission
Go to Resource Manager → Resource Type Permissions → New Permission. Set Language to PowerShell.
Paste rotate-ad-service-account.ps1 as the checkout routine.
Declare variables:
| Variable | Notes |
|---|---|
AD_TARGET_USER | SamAccountName of the service account |
AD_NEW_PASSWORD | Generated by Britive at checkout |
AD_TARGET_SERVER | Hostname or FQDN of the server running the service |
AD_SERVICE_NAME | Windows service name |
AD_RESTART_SERVICE | Optional — defaults to true |
Create a profile
Go to Resource Manager → Profiles → New Profile. Set an expiration. Under Associations, select the resource label(s) covering your AD resources. Under Permissions, add whichever permission matches your rotation pattern.
Add a policy
Under Policies, assign members and configure conditions.
AD_NEW_PASSWORD must be a system-generated variable from Britive — never a static value. Britive generates a new random password at each rotation and injects it via this variable.
Enable WinRM on Target Servers
Pattern 2 requires PSRemoting on each target server. Run on each target as a local administrator:
Enable-PSRemoting -Force
# Verify the broker can reach the target
Test-WSMan -ComputerName "target-server.contoso.com"If the broker and target are in the same domain, Kerberos authentication is used automatically — no additional credential configuration is needed, provided the broker gMSA has remote administration rights on the target.
Verify
# Check when the service account password was last changed
Get-ADUser -Identity "svc-myapp" -Properties PasswordLastSet |
Select-Object SamAccountName, PasswordLastSet
# Confirm the service is running with the updated credential (on the target server)
Get-WmiObject Win32_Service -ComputerName "target-server" -Filter "Name='MySvc'" |
Select-Object Name, StartName, StateAfter rotation:
PasswordLastSetshould show the current date and timeStartNameon the service should match the rotated accountStateshould beRunningifAD_RESTART_SERVICE = true
Troubleshoot
| Symptom | Cause | Fix |
|---|---|---|
AD_TARGET_USER not set | Variable not declared on the permission | Declare AD_TARGET_USER in the permission variable list |
Access denied on Set-ADAccountPassword | gMSA missing Reset Password delegation | Delegate CA;Reset Password;user on the service account OU |
Invoke-Command access denied | Broker gMSA not a remote admin on target | Add broker gMSA to the local Administrators group on target, or grant Remote Management Users membership |
WinRM cannot complete the operation | WinRM not enabled or firewall blocks port 5985 | Run Enable-PSRemoting -Force on target; open TCP 5985 from the broker |
sc.exe config failed | Insufficient rights to modify service | Confirm the broker gMSA (not a limited account) is connecting via WinRM |
| Service fails to start after restart | New password does not meet domain policy | Check the domain password policy minimum length and complexity requirements |