CoursesVault from dev to productionAppRole and response wrapping

AppRole and response wrapping

Machines without a browser, delivered once.

In short. Not every machine lives in Kubernetes. CI runners, VMs, and legacy app servers still need a Vault login path that does not involve a browser.

Intermediate30 min · lesson 9 of 13

Not every machine lives in Kubernetes. CI runners, VMs, and legacy app servers still need a Vault login path that does not involve a browser. AppRole is Vault's purpose-built machine auth: a role identifier that is not secret, plus a secret ID that is. Response wrapping delivers that secret ID once, through a single-use token, so it never sits long in a ticket or chat.

AppRole done wrong becomes "static password with extra steps." AppRole done right keeps RoleID in config, injects SecretID at provision time via wrap, sets tight TTLs and use limits, and binds CIDR or other constraints when the platform allows.

Enable AppRole and define a role

Enable the auth method, write a role with token_policies, token_ttl, secret_id_ttl, and token_num_uses as appropriate. Prefer short SecretID lifetimes for CI. For long-running hosts, pair with periodic tokens carefully — or better, prefer platform identity (cloud IAM, Kubernetes) when available.

terminal
vault auth enable approle
vault write auth/approle/role/ci-deploy \
token_policies="ci-deploy" \
token_ttl=15m \
token_max_ttl=30m \
secret_id_ttl=10m \
secret_id_num_uses=1
vault read auth/approle/role/ci-deploy/role-id
output
Key Value
--- -----
role_id a1b2c3d4-role-id-example

Response wrapping for SecretID delivery

Generate a SecretID with -wrap-ttl=2m. Vault returns a wrapping token instead of the SecretID. Only the intended runner should unwrap it (vault unwrap). If unwrap fails because the wrap was already used, treat it as interception — rotate and investigate. This is the practical answer to secret-zero for AppRole bootstraps.

terminal
vault write -wrap-ttl=2m -force auth/approle/role/ci-deploy/secret-id
# deliver wrapping_token to the runner out of band, then on the runner:
vault unwrap <wrapping_token>
vault write auth/approle/login role_id=$ROLE_ID secret_id=$SECRET_ID
output
Key Value
wrap_info ...
# after unwrap + login
token hvs.CAESIJci
token_policies [ci-deploy]
Wrapped SecretID path
1Operator mints wrap
secret-id with wrap_ttl
2Runner unwraps once
receives SecretID
3Login AppRole
RoleID + SecretID → Vault token
4Fetch secrets
short token TTL
If unwrap is already used, stop — do not regenerate quietly into the same channel.
RoleID is not authentication alone
RoleID can live in config management. The SecretID is the credential. Long-lived unlimited SecretIDs recreate static passwords.

Going deeper

Bind CIDRs on SecretID or tokens when runners have stable egress. It will not stop a compromised runner inside the range, but it blocks stolen SecretIDs used from a laptop on another network. Combine with secret_id_num_uses and short TTLs so replay windows stay tiny.

CI systems should mint wrapped SecretIDs in a privileged bootstrap job, then unwrap only on the job that needs Vault — never echo the SecretID into logs. Prefer OIDC/JWT auth to Vault when your Vault version and platform support it; AppRole remains the bridge for legacy fleets.

Rotate RoleIDs rarely and SecretID generation often. If a RoleID leaks with a long-lived unlimited SecretID, you have reinvented a password. Audit auth/approle/login failures for spraying, and alert on unwrap failures that suggest interception.

Try this

In a lab, mint a wrapped SecretID, unwrap it, login, then try unwrap again and confirm failure.

terminal
WRAP=$(vault write -wrap-ttl=2m -force -field=wrapping_token auth/approle/role/ci-deploy/secret-id)
vault unwrap $WRAP
vault unwrap $WRAP || true
output
secret_id ...
Error unwrapping: wrapping token is not valid or has already been used
# SUCCESS — single delivery proven

Takeaway

AppRole plus response wrapping gives non-Kubernetes machines a least-privilege login without parking forever-SecretIDs in git. Prefer platform-native identity when you can; use AppRole when you must.

Next: Vault Agent — keep applications from speaking Vault's API themselves.

Quick check
01Response wrapping helps AppRole by…
Incorrect — Seal/storage are separate.
Correct — interception shows up as a used wrap.
Incorrect — Audit should remain on.
Incorrect — RoleID stays non-secret by design.
02secret_id_num_uses=1 is useful because…
Incorrect — Uses limits are about replay, not speed.
Correct — steal-once semantics.
Incorrect — Unrelated.
Incorrect — Uses do not escalate policy.

Related