Rotate Admin Accounts
Overview
This guide configures JIT credential rotation for dedicated AD admin accounts — accounts like jdoe-a that exist alongside a user’s standard account for privileged access.
At checkout, Britive rotates the password and delivers the new credential to the requesting user. At checkin, the password is rotated again without sharing the new value — leaving the account with an unknown password until the next checkout. This eliminates standing credential risk without deleting the account.
Two password generation modes are available:
- Random — 12-character alphanumeric + symbol string (standard compliance)
- Passphrase — pronounceable multi-word passphrase (easier to type in RDP sessions or on a phone)
Before You Begin
- The Britive Access Broker is running (see Getting Started)
- The broker gMSA has the following delegations on the managed accounts OU:
- Create user objects
- Reset Password
- Write
userAccountControl(enable/disable)
- RSAT Active Directory module installed on the broker host
Checkout Routine — Random Password
Full script: Active Directory/permissions/rotate-a-account/rotate-a-account-checkout.ps1
At checkout, this script creates the -a account if it does not yet exist, generates a random password, enables the account, and returns the credentials to the user.
Environment variable: user (UPN of the requesting user)
Derive admin account name and generate password:
$Email = $env:user
$Username = ($Email -split "@")[0] + "-a"
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-+="
$password = -join ((1..12) | ForEach-Object { $chars[(Get-Random -Maximum $chars.Length)] })
$SecurePassword = ConvertTo-SecureString $password -AsPlainText -ForceCreate or rotate the account:
$User = Get-ADUser -Filter { SamAccountName -eq $Username } -ErrorAction SilentlyContinue
if (-not $User) {
New-ADUser -Name $Username -SamAccountName $Username -UserPrincipalName $Email `
-AccountPassword $SecurePassword -Enabled $true
} else {
Set-ADAccountPassword -Identity $Username -NewPassword $SecurePassword -Reset
Enable-ADAccount -Identity $Username
}
Write-Output "username: $Username"
Write-Output "password: $password"Checkout Routine — Passphrase Password
Full script: Active Directory/permissions/rotate-a-account/rotate-a-account-checkout-passphrase.ps1
Generates a memorable, pronounceable passphrase — useful when the credential must be typed manually (e.g., RDP without clipboard, mobile devices).
Generate pronounceable passphrase:
function New-PronounceableWord {
param([int]$syllables = 2)
$consonants = "bdfghjklmnprstvwz"
$vowels = "aeiou"
$word = ""
for ($s = 0; $s -lt $syllables; $s++) {
$word += $consonants[(Get-Random -Maximum $consonants.Length)]
$word += $vowels[(Get-Random -Maximum $vowels.Length)]
}
$word += $consonants[(Get-Random -Maximum $consonants.Length)]
return $word
}
$password = ""
while ($password.Length -lt 18) {
$word = New-PronounceableWord -syllables (Get-Random -Minimum 2 -Maximum 4)
$password += $word.Substring(0,1).ToUpper() + $word.Substring(1)
}
$password += (Get-Random -Minimum 10 -Maximum 100).ToString()Checkin Routine
Full script: Active Directory/permissions/rotate-a-account/rotate-a-account-checkin.ps1
At checkin, the password is rotated to a new random value that is not returned to the user — the account is left with an unknown password, eliminating standing access.
$Username = ($env:user -split "@")[0] + "-a"
$User = Get-ADUser -Filter { SamAccountName -eq $Username } -ErrorAction SilentlyContinue
if ($User) {
$password = -join ((1..12) | ForEach-Object { $chars[(Get-Random -Maximum $chars.Length)] })
$SecurePassword = ConvertTo-SecureString $password -AsPlainText -Force
# Rotate password — do NOT output the new value
Set-ADAccountPassword -Identity $Username -NewPassword $SecurePassword -Reset
Write-Output "Account '$Username' password rotated on checkin. Credential is no longer valid."
}Configure in Britive
Create a response template
Go to Resource Manager → Response Templates → New Template. Add fields that surface username and password from the checkout output.
Create a permission
Go to Resource Manager → Resource Type Permissions → New Permission. Set Language to PowerShell.
Paste the checkout routine (random or passphrase — choose one) into the Checkout field. Paste checkin.ps1 into the Checkin field.
Declare variables:
| Variable | System defined | Notes |
|---|---|---|
user | Yes | Injected automatically |
Under Response Templates, attach the template you created.
Create a profile
Go to Resource Manager → Profiles → New Profile. Set an expiration (e.g. 4h). Under Associations, select the resource label(s) covering your AD domain resources. Under Permissions, add the permission above.
Add a policy
Under Policies, assign members (users or tags) and configure approval conditions.
The checkin routine intentionally does not output the new password. This is by design — the -a account is left with an unknown credential between sessions. Do not modify the checkin routine to return the password.
Verify
Check out the profile
In the Britive console, check out the profile. The username and password should appear in the checkout response.
Test access
Log in to a domain resource using the -a account and the delivered password — access should work.
Check in
Check in (or allow the session to expire).
Confirm revocation
Attempt to log in with the previously delivered password — it should fail.
Get-ADUser -Identity "jdoe-a" -Properties Enabled, PasswordLastSet |
Select-Object SamAccountName, Enabled, PasswordLastSetTroubleshoot
| Symptom | Cause | Fix |
|---|---|---|
| Account not created on first checkout | gMSA missing Create user delegation | Delegate CC;user on the accounts OU |
Access denied on Set-ADAccountPassword | gMSA missing Reset Password right | Delegate CA;Reset Password;user on the accounts OU |
| Credentials not shown after checkout | show_orig_creds = false and no response template | Set show_orig_creds = true or add a response template that exposes username and password |
| Old password still works after checkin | Checkin routine did not run | Check broker logs — look for script execution errors |