vault

star 131

Call HashiCorp Vault / OpenBao through Warden — read secrets, sign, encrypt, manage PKI — without ever holding a Vault token.

stephnangue By stephnangue schedule Updated 6/12/2026

name: vault description: "Call HashiCorp Vault / OpenBao through Warden — read secrets, sign, encrypt, manage PKI — without ever holding a Vault token." category: provider-guide provider: vault requires: [foundation, discovery] upstream: HashiCorp Vault / OpenBao

Vault through Warden

What it does

Warden proxies Vault HTTP API requests. The agent sends a normal Vault request to a Warden URL; Warden authenticates the agent (JWT or cert), mints a short-lived Vault token from the configured credential spec, injects it as X-Vault-Token, and forwards. The agent never holds a Vault token.

Configure the CLI/SDK

<mount-url> and <role> below come from the discovery flow:

  • <mount-url> is the chosen provider's mount_url from warden provider list (e.g. /v1/vault/, /v1/team-data/secrets-prod/). Warden has already baked the namespace + mount path in.
  • <role> is the role you picked from warden role list to perform this task — it goes in the URL path.

Auth is your JWT:

URL pattern : $WARDEN_ADDR<mount-url>role/<role>/gateway/<vault-api-path>
Auth header : Authorization: Bearer $WARDEN_TOKEN  # OR X-Vault-Token: $WARDEN_TOKEN

Vault / OpenBao CLI

The Vault CLI works against Warden unchanged — point it at the Warden gateway and use the JWT as the Vault token. Warden detects the JWT prefix in X-Vault-Token and treats it as identity.

Use whichever binary the environment has. OpenBao ships its CLI as bao (a fork of vault); some environments install one, some the other, some both. The two are command-compatible — pick the one on PATH. Probe order:

if command -v vault >/dev/null; then CLI=vault
elif command -v bao >/dev/null; then CLI=bao
else echo "neither vault nor bao is installed" >&2; exit 1
fi

Both honour VAULT_ADDR + VAULT_TOKEN (yes, bao reads VAULT_* env vars too):

export VAULT_ADDR="$WARDEN_ADDR<mount-url>role/<role>/gateway"
export VAULT_TOKEN="$WARDEN_TOKEN"

$CLI kv get secret/myapp/config
$CLI kv put secret/myapp/config foo=bar
$CLI list secret/myapp/
$CLI write pki/sign/server-tpl csr=@./req.csr

The agent never holds a real Vault token; the JWT is the identity.

Vault SDK

For the official Go / Python / Node Vault SDKs, the same shape: set the client's Address to $WARDEN_ADDR<mount-url>role/<role>/gateway and its Token to the JWT.

Raw HTTP (curl)

curl -H "Authorization: Bearer $WARDEN_TOKEN" \
  "$WARDEN_ADDR<mount-url>role/<role>/gateway/v1/secret/data/myapp/config"

Examples

(All examples assume mount_url = /v1/vault/ and role secrets-reader; substitute yours. VAULT_ADDR and VAULT_TOKEN are exported as shown above.)

KV v2 read:

vault kv get secret/app/db

KV v2 write (operator-permitted):

vault kv put secret/app/db key=value

Cross-namespace reads (Vault Enterprise / OpenBao namespaces — pass the upstream namespace via VAULT_NAMESPACE, distinct from Warden's namespace):

VAULT_NAMESPACE=prod vault kv get secret/app/db

PKI sign:

vault write pki/sign/server-tpl csr=@./req.csr

Same operations via raw HTTP for scripting:

curl -H "Authorization: Bearer $WARDEN_TOKEN" \
  $WARDEN_ADDR/v1/vault/role/secrets-reader/gateway/v1/secret/data/app/db

Quirks

  • /v1 is auto-prepended. A request to …/gateway/secret/data/foo is rewritten to …/secret/data/foo upstream as if you'd written …/gateway/v1/secret/data/foo. Either form works.
  • X-Vault-Namespace header passes through — useful for Vault Enterprise / OpenBao namespaces, distinct from Warden's namespaces.
  • PKI verify endpoints are unauthenticated at the Vault level; Warden still requires a valid identity to reach them.
  • Returned data has Vault's normal envelope ({data: {data: {…}}} for KV v2, etc.) — the agent decodes per Vault's API.
Install via CLI
npx skills add https://github.com/stephnangue/warden --skill vault
Repository Details
star Stars 131
call_split Forks 7
navigation Branch main
article Path SKILL.md
More from Creator