vault AppRole Auth: RoleID and SecretID Login
AppRole authenticates a machine with a role_id plus a secret_id, returning a token scoped to the role policies.
AppRole is the classic CI login when there is no cloud identity to lean on. The trick is delivering the secret_id securely, since it is effectively a password.
What it does
AppRole splits credentials into a stable role_id and a dynamic secret_id. A workload logs in by writing both to auth/approle/login, receiving a token whose policies come from the role config (token_policies). secret_ids can be made single-use and short-lived.
Common usage
# one-time setup
vault write auth/approle/role/ci token_policies="ci" \
secret_id_ttl=10m secret_id_num_uses=1 token_ttl=20m
ROLE_ID=$(vault read -field=role_id auth/approle/role/ci/role-id)
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/ci/secret-id)
# login from the job
vault write -field=token auth/approle/login \
role_id="$ROLE_ID" secret_id="$SECRET_ID"Options
| Field | What it does |
|---|---|
| role_id | Stable identifier for the role |
| secret_id | Dynamic credential, like a password |
| token_policies | Policies attached to issued tokens |
| secret_id_ttl / secret_id_num_uses | Limit secret_id lifetime and uses |
| token_ttl / token_max_ttl | Issued token lifetime |
In CI
Treat secret_id as a secret: keep role_id in config but inject secret_id from a protected store, and prefer secret_id_num_uses=1 so a leaked value is useless after the run. Cloud-native methods (JWT/OIDC, Kubernetes, AWS) avoid handling a long-lived secret_id entirely and are preferred where available.
Common errors in CI
"invalid role or secret id" (HTTP 400) means a wrong, expired, or already-used secret_id, or a typo in role_id. "failed to validate SecretID: SecretID has been used up" means num_uses is exhausted; mint a fresh one. "permission denied" reading the role-id path means the bootstrap token lacks access to auth/approle/role/ci/role-id.