CPM password rotation failing: plugin error, account status, target-side cause
This runbook is for developers and support engineers diagnosing failed CPM password rotations against target systems. It shows how to read the plugin error first, correlate it with the managed account state, and then confirm the actual target-side cause with concrete checks and fixes.
TL;DR — When CPM password rotation fails, do not start by guessing at network or policy issues. Read the plugin error from the CPM logs/job details, check whether the managed account is disabled/locked/expired on the target, then validate the target-side cause directly with a native login test or directory query; the most common fix is unlocking/enabling the account or correcting the current credential stored in the vault so CPM can authenticate before changing the password. Reading time: ~6 min
The scenario
It is Tuesday at 3:40 PM and your rotation window just ended with a pile of failed password changes. The vault UI shows the account in a failed state, the application team is asking whether the next deploy will lose database access, and the only clue in the job output is a plugin error that looks annoyingly generic. You have the account name, the platform/plugin used for rotation, and access to the target host or directory. You need to decide fast whether this is a bad stored password, a locked/disabled account, or something on the target side like password policy, SSH/sudo, or login restrictions.
Symptoms
- Rotation job fails with a plugin/runtime message similar to:
Change password failed
CPM error: Verify password task failed
Execution error in plugin
Authentication failure
- Job detail or CPM log includes target-native errors such as:
ssh: Permission denied (publickey,password)
Access denied for user 'svc_app'@'10.20.30.40' (using password: YES)
ORA-01017: invalid username/password; logon denied
The user name or password is incorrect.
Account locked out
User must change password at next logon
- Account status in the target directory/OS/database shows disabled, locked, expired, or password change blocked.
- Manual login with the currently stored credential fails, so CPM never reaches the password-change step.
- Manual login succeeds, but the password change command returns a policy error such as complexity/history/minimum-age violation.
- In SSH targets, login works interactively for a human but fails for CPM because non-interactive auth, forced TTY, or sudo restrictions differ.
Likely causes
| Cause | How common | Quick check |
|---|---|---|
| Stored current password in the vault is wrong, so verify/authentication fails before change | Very common | ```bash |
| ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@target.example.com |
| Target account is locked, disabled, expired, or forced to change password | Very common | ```bash
sudo chage -l svc_app
``` |
| Target password policy rejects the new password (complexity/history/min age) | Common | ```bash
sudo passwd svc_app
``` |
| SSH/sudo/login method mismatch for the plugin (no TTY, wrong shell, password auth disabled) | Common | ```bash
ssh -vvv -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@target.example.com
``` |
| Directory/DB-specific account restriction on the target (AD logon hours, SQL login disabled, Oracle profile) | Occasional | ```powershell
Get-ADUser svc_app -Properties Enabled,LockedOut,PasswordExpired,LogonHours
``` |
| Connectivity/name resolution issue between CPM and target | Occasional | ```bash
nc -vz target.example.com 22
``` |
## Step-by-step diagnosis
1. Read the exact plugin error from the failed rotation job or CPM logs.
- Use your vault/CPM job details first; if you have host access, grep the CPM log directory for the account or address.
```bash
grep -R -iE "svc_app|10\.20\.30\.40|Permission denied|Access denied|ORA-01017|locked|expired" /var/log 2>/dev/null | tail -n 50
- This is your problem if you see a target-native error string that already points to auth, lockout, policy, or protocol mismatch.
- Jump to the matching fix section below instead of broad trial-and-error.
- Test whether the current stored credential can authenticate to the target.
- For SSH targets:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@target.example.com
- For MySQL targets:
mysql -h db.example.com -u svc_app -p -e "select 1;"
- For Windows/AD-backed checks from a Windows admin host:
runas /user:DOMAIN\svc_app cmd
- This is your problem if login fails with invalid credentials, access denied, or logon failure. The plugin cannot change a password if it cannot verify/authenticate first.
- Jump to ### Stored current password in the vault is wrong.
- Check whether the account itself is locked, disabled, or expired.
- On Linux:
sudo passwd -S svc_app
sudo chage -l svc_app
sudo faillock --user svc_app
- Typical output indicating the issue:
svc_app L 2026-08-05 0 99999 7 -1
Account expires : Aug 05, 2026
Password inactive : never
Maximum number of days between password change : 30
- On Windows/AD:
Get-ADUser svc_app -Properties Enabled,LockedOut,AccountExpirationDate,PasswordExpired,PasswordNeverExpires | Format-List Name,Enabled,LockedOut,AccountExpirationDate,PasswordExpired,PasswordNeverExpires
- This is your problem if the account is locked, disabled, expired, or forced into a state that blocks normal authentication/change.
- Jump to ### Target account is locked, disabled, expired, or forced to change password.
- If login works, test whether the target accepts a password change at all.
- On Linux:
sudo passwd svc_app
- Typical policy failure output:
BAD PASSWORD: is too simple
BAD PASSWORD: is based on a dictionary word
Password has been already used. Choose another.
passwd: Authentication token manipulation error
- On AD from PowerShell:
Set-ADAccountPassword -Identity svc_app -Reset -NewPassword (Read-Host -AsSecureString)
- This is your problem if the change operation fails while authentication succeeds.
- Jump to ### Target password policy rejects the new password.
- Validate the plugin’s login method assumptions against the target.
- For SSH, inspect auth methods and TTY/shell behavior:
ssh -vvv -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@target.example.com
- Output that points to the issue:
debug1: Authentications that can continue: publickey
Permission denied (publickey).
- Or:
Pseudo-terminal will not be allocated because stdin is not a terminal.
This account is currently not available.
- This is your problem if password auth is disabled, the shell is nologin, or the plugin needs sudo/TTY that the target denies.
- Jump to ### SSH/sudo/login method mismatch for the plugin.
- Check service-specific restrictions and basic connectivity only after the above.
- Connectivity from the CPM host or a network-equivalent host:
nc -vz target.example.com 22
- AD/Windows restrictions:
Get-ADUser svc_app -Properties LogonHours,SmartcardLogonRequired,UserWorkstations
- DB restrictions examples:
SELECT username, account_status, profile FROM dba_users WHERE username = 'SVC_APP';
- This is your problem if the port is unreachable or the service account is restricted by target-specific policy/profile.
- Jump to the relevant fix section.
Fixes
Stored current password in the vault is wrong
If manual authentication with the current secret fails, update/reconcile the stored password before retrying rotation.
- If you know the correct current password, update the secret in your vault/CPM account record using the account edit path in your product’s dashboard, then trigger an immediate verify/reconcile.
- If you do not know it, reset the password directly on the target with an admin account, then update the vault to match.
Linux local account reset:
⚠️ This changes a live credential. Anything still using the old password will fail until consumers pick up the new secret.
sudo passwd svc_app
AD reset:
⚠️ This can break services immediately if the account is in active use.
Set-ADAccountPassword -Identity svc_app -Reset -NewPassword (ConvertTo-SecureString "Temp-Strong-Password-Here" -AsPlainText -Force)
MySQL reset:
ALTER USER 'svc_app'@'%' IDENTIFIED BY 'Temp-Strong-Password-Here';
FLUSH PRIVILEGES;
Verify it worked:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@target.example.com
Target account is locked, disabled, expired, or forced to change password
Unlock or re-enable the account, clear expiration/forced-change flags if your policy allows it, then rerun verify/change.
Linux:
sudo usermod -U svc_app
sudo chage -E -1 svc_app
sudo chage -d $(date +%F) svc_app
sudo faillock --user svc_app --reset
Check status after changes:
sudo passwd -S svc_app
sudo chage -l svc_app
AD:
Unlock-ADAccount -Identity svc_app
Enable-ADAccount -Identity svc_app
Set-ADUser -Identity svc_app -ChangePasswordAtLogon $false
If the account is intentionally disabled by policy, stop here and fix the ownership/process issue instead of forcing rotation.
Verify it worked:
Get-ADUser svc_app -Properties Enabled,LockedOut,PasswordExpired | Format-List Enabled,LockedOut,PasswordExpired
Target password policy rejects the new password
Align the CPM-generated password with target policy: length, complexity classes, history, minimum age, and forbidden substrings.
Linux PAM quality/history examples to inspect:
grep -R "pam_pwquality\|pam_pwhistory" /etc/pam.d /etc/security 2>/dev/null
cat /etc/security/pwquality.conf 2>/dev/null
Typical settings you must account for:
minlen = 15
minclass = 4
maxrepeat = 2
remember = 24
AD policy quick view:
Get-ADDefaultDomainPasswordPolicy | Format-List MinPasswordLength,ComplexityEnabled,PasswordHistoryCount,MinPasswordAge,MaxPasswordAge
If minimum password age is non-zero, a second rotation too soon will fail even with a strong password. Either wait for the age window or use a break-glass admin reset path if your policy permits it.
Verify it worked:
sudo passwd svc_app
SSH/sudo/login method mismatch for the plugin
Fix the target so the plugin can authenticate non-interactively using the method it is configured for.
Inspect SSH daemon settings:
sudo grep -E "^(PasswordAuthentication|KbdInteractiveAuthentication|UsePAM|PermitRootLogin)" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* 2>/dev/null
If password auth is required for rotation and disabled, enable it and reload sshd:
⚠️ Changing SSH auth settings can widen access. Apply only to hosts/accounts that require it and follow your hardening standard.
sudo sh -c 'printf "\nPasswordAuthentication yes\nUsePAM yes\n" >> /etc/ssh/sshd_config'
sudo systemctl reload sshd
If the account shell is nologin, set a real shell if policy allows:
sudo chsh -s /bin/bash svc_app
If sudo requires a TTY and the plugin cannot provide one, adjust sudoers for the specific command path instead of disabling controls globally:
sudo visudo
Add a narrow rule like:
Defaults:svc_app !requiretty
svc_app ALL=(root) NOPASSWD: /usr/bin/passwd svc_app
Verify it worked:
ssh -vvv -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@target.example.com
Directory/DB-specific account restriction on the target
Clear the restriction that blocks the change, or move the account to a profile/OU policy intended for service accounts.
AD examples:
Set-ADUser -Identity svc_app -LogonWorkstations $null
# LogonHours usually needs a byte array; easiest safe action is to compare with a known-good service account in your environment.
Oracle examples:
SELECT username, account_status, profile FROM dba_users WHERE username = 'SVC_APP';
ALTER USER SVC_APP ACCOUNT UNLOCK;
ALTER PROFILE APP_SERVICE LIMIT PASSWORD_REUSE_TIME UNLIMITED;
SQL Server examples:
SELECT name, is_disabled FROM sys.sql_logins WHERE name = 'svc_app';
ALTER LOGIN [svc_app] ENABLE;
ALTER LOGIN [svc_app] WITH PASSWORD = 'Temp-Strong-Password-Here';
Verify it worked:
SELECT username, account_status FROM dba_users WHERE username = 'SVC_APP';
Connectivity/name resolution issue between CPM and target
Fix DNS, routing, firewall, or listener state from the CPM host to the target.
Basic checks:
getent hosts target.example.com
nc -vz target.example.com 22
curl -I telnet://target.example.com:22
Typical failure shapes:
nc: connect to target.example.com port 22 (tcp) failed: Connection timed out
nc: connect to target.example.com port 22 (tcp) failed: Connection refused
If DNS is wrong, correct the A/AAAA record in your provider’s dashboard (for example, DNS/Records in your DNS provider UI) or /etc/hosts for a temporary test only. If the port is blocked, add the CPM source IP to the target firewall/security group.
Verify it worked:
nc -vz target.example.com 22
Prevention
- Log and alert on the exact plugin error class, not just “rotation failed”. Parse CPM/job logs for auth/policy/lockout signatures.
grep -R -iE "ORA-01017|Access denied|Permission denied|locked out|BAD PASSWORD|must change password" /var/log/cpm* | logger -t cpm-rotation-signatures
- Add a pre-rotation health check from the CPM host that tests network reachability and target auth path without changing anything.
nc -vz target.example.com 22 && ssh -o BatchMode=no -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@target.example.com exit
- Pin service-account password policy separately from human-user policy where your platform supports it, especially minimum password age and forced-change-at-logon. On AD, review the effective policy regularly:
Get-ADDefaultDomainPasswordPolicy | Format-List *
- For Linux SSH targets, keep auth settings explicit in config management so a hardening change does not silently break rotation.
# example rendered by config management; for sshd use a managed file instead of ad-hoc edits
sudo grep -E "^(PasswordAuthentication|UsePAM)" /etc/ssh/sshd_config
- In CI for platform/plugin changes, run a disposable target test that performs verify + change + revert against a sandbox account and fails the pipeline on any non-zero exit.
set -euo pipefail
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no svc_app@sandbox.example.com exit
# call your rotation API/job here, then assert success and revert
- Track account state drift daily for managed accounts: disabled, locked, expired, shell set to nologin, SQL login disabled, AD change-at-logon set. Export and diff the results.
Get-ADUser -Filter 'Name -like "svc_*"' -Properties Enabled,LockedOut,PasswordExpired | Select-Object Name,Enabled,LockedOut,PasswordExpired | Export-Csv .\svc-account-state.csv -NoTypeInformation
This article was written by an AI system and published pending human review. Verify anything you intend to act on.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI