Vault
OS secrets engine
Enterprise
Appropriate Vault Enterprise license required
The OS secrets engine manages the secure rotation of user credentials (passwords) on remote hosts. It is designed to automate password management for local accounts, reducing manual effort and improving security posture. The engine supports two rotation flows:
- Parent Managed Rotation: A superuser (parent) account rotates the password for another account.
- Self Managed Rotation: The account rotates its own password using its own privileges.
General Requirements
The OS secrets engine is supported for Vault Enterprise 2.0.0 and later.
It supports managing passwords on RHEL systems with shadow-utils version greater than 4.6.
It must be able to establish an SSH connection to the target host.
Setup
Most secrets engines must be configured in advance before they can perform their functions. These steps are usually completed by an operator or configuration management tool.
Download and register the plugin in Vault's plugin catalog. Note that the plugin version must match exactly with the target version from releases.hashicorp.com:
```shell $ vault plugin register -download -version="0.1.0-rc1+ent" secret vault-plugin-secrets-os ```Enable the OS secrets engine:
$ vault secrets enable -path=os vault-plugin-secrets-osBy default, the secrets engine will mount at the name of the engine. To enable the secrets engine at a different path, use the
-pathargument.
Hosts
The OS secrets engine organizes accounts by "hosts". A host represents a remote system that Vault can connect to in order to rotate account credentials. Each host can have multiple accounts, and each account can have its own rotation configuration.
Setup:
- Configure the connection parameters for a remote host:
$ vault write os/hosts/my-box \ address="box.example.com" \ port=22
SSH Host Key Verification
The engine supports two methods for establishing the host's identity:
Pre-Shared Key (Explicit Trust)
The operator provides the target host's public key (e.g., RSA, ED25519) during host onboarding via the ssh_host_key field.
Verification: During the first connection attempt, the engine will validate that the host's presented key matches the pre-shared key. If it does not match, the engine will abort the connection and log an error.
Security Posture: This is the most secure method and is recommended for production environments.
Trust On First Use (TOFU)
By default, ommitting the ssh_host_key during host onboarding will result in the inability to create accounts on the host.
The operator must explicitly allow the engine to trust the first key presented by the host during the first connection attempt by setting ssh_host_key_trust_on_first_use to true on the /config endpoint.
Verification: During the first connection attempt, the engine fetches the host's public key and stores it.
Persistence: All subsequent connections will strictly validate against this stored key. If the host presents a different key in the future, the engine will abort the connection and log an error.
Notice: In both cases, the first connection attempt happens during the creation of the first account on the host by default. If verify_connection is set to false on the account,
then the first connection attempt will be deferred until the first credential rotation.
Accounts
An account represents a local user on the remote host that Vault will rotate credentials for. Each account must be associated with a host, and can optionally reference a parent account that will perform the rotation on its behalf.
Parent Managed Rotation
In this flow, a privileged (parent) account rotates the password for the target account. The parent account is stored in Vault as a standard account even though it may have elevated privileges on the remote host.
Vault executes the rotation by establishing an SSH session using the credentials of the Parent Account.
Once authenticated, Vault issues the chpasswd command to update the target account's credentials.
Requirements:
chpasswdmust be at the following path on the target system:/usr/sbin/chpasswdsudomust be at the following path on the target system:/usr/bin/sudo- The parent account must have passwordless
sudoaccess to/usr/sbin/chpasswd.
Notice: The sudo privileges given to a parent account should be granted with care, and scoped as narrowly
as possible. For example, they could be limited to only the chpasswd command in the sudoers entry:
$user ALL=NOPASSWD:/usr/sbin/chpasswd
Setup:
- Configure the parent (superuser) account:
$ vault write os/hosts/my-box/accounts/mgmt-user \ username="super-user" \ password="super-secret" - Configure the target account, referencing the parent account:
$ vault write os/hosts/my-box/accounts/app-user \ username="user-1" \ password="bigsecret" \ parent_ref="mgmt-user"
Notice: Parent accounts are highly privileged, and should be treated as such. To prevent standard users from accessing sensitive "management" credentials,
we recommend adopting a naming convention for parent accounts (e.g. prefixing with "mgmt-" as in the example above) and implementing policies to restrict access to them.
For example, you could explicitly deny access to any account with the "mgmt-" prefix in the policy for non-privileged users: path "os/hosts/+/accounts/mgt-*" { capabilities = ["deny"] }
Self Managed Rotation
In this flow, Vault authenticates to the target system as the target account itself and issues the passwd command to update its own credentials. This will be the default configuration.
Vault establishes an SSH session using the currently stored credentials for the account. Once authenticated, Vault opens an interactive PTY session and executes an expect-like workflow: it waits for the passwd command to prompt for the current password, then sends the current password, waits for the prompt for the new password, sends the new password, etc.
This flow is ideal for environments where creating a dedicated administrative service user is not feasible or where security policies dictate that accounts should have strictly isolated lifecycles.
Requirements:
passwdmust be at the following path on the target system:/usr/bin/passwd- The SSH daemon must allow PTY allocation for expect workflows
Setup: Configure the target account without a parent reference:
$ vault write os/hosts/my-box/accounts/app-user \
username="user-1" \
password="bigsecret"
Usage
Password Rotation
After a user is configured, the password can be rotated either manually, on a cron-like schedule, or on a specified period.
Here's an example of manually rotating a user:
$ vault write -f os/hosts/my-box/accounts/my-user/rotate
For a detailed description of rotation options, see the API.
Versioning
Whenever a new credential is created, the plugin will create a new version. Metadata about these versions can be viewed
with the /versions sub-command:
$ vault write -f os/hosts/my-box/accounts/my-user/versions
Key Value
--- -----
created_time 2026-04-03T20:01:29Z
current_version 2
oldest_version 1
ttl <nil>
versions map[1:map[created_time:2026-04-03T20:01:19Z expired_time:2026-04-03T20:01:29Z] 2:map[created_time:2026-04-03T20:01:29Z expired_time:0001-01-01T00:00:00Z]]
The current value of a credential can also be reverted to a prior value - see Recovery
Recovery
If the plugin's information becomes out-of-sync with the credential on the remote host, an operator can change the password
known to Vault using the /reset or :version/restore sub-commands.
Here's an example of a reset command:
$ vault write -f os/hosts/my-box/accounts/my-user/reset password="new-password"
And of a version restore:
$ vault write -f os/hosts/my-box/accounts/my-user/versions/1/restore
Note that because these are intended to recover from scenarios where Vault doesn't have the correct user password, they do not act on the remote server.
For a more complete description of these endpoints, see the API.
Offboarding
To offboard a credential that is managed by the plugin, follow these steps:
Stop any automated rotations by setting the
disable_automated_rotationflag:$ vault write os/hosts/my-box/accounts/my-user disable_automated_rotation=trueRetrieve the current credential on the account and store it securely:
$ vault read os/hosts/my-box/accounts/my-user/creds Key Value --- ----- created_time 2026-04-03T20:01:29Z last_vault_rotation 2026-04-03T20:01:29Z next_vault_rotation <nil> password zyfiqmjl ttl <nil> username user-1 version 2Delete the account:
$ vault delete os/hosts/my-box/accounts/my-user Success! Data deleted (if it existed) at: os/hosts/my-box/accounts/my-user
To delete an entire host, repeat these steps for each managed account, then delete the host:
$ vault delete os/hosts/my-box
Success! Data deleted (if it existed) at: os/hosts/my-box
API
The OS secrets engine has a full HTTP API. Please see the OS secrets engine API for more details.