HashiCorp Vault
HashiCorp Vault credential provider.
The hashicorp-vault provider resolves secrets from HashiCorp Vault KV v2. It supports three authentication modes - token, AppRole, and Kubernetes - and integrates with the credential dispatch adapter's live-rotation subscription model.
The MVP ships token-auth and AppRole. Kubernetes auth (IRSA-equivalent for Vault) is the recommended production mode for containerized deployments. All three are implemented and production-exercised.
Prerequisites
- A running HashiCorp Vault instance (OSS or Enterprise) accessible from the platform deployment.
- KV v2 secrets engine enabled on your Vault cluster.
- A Vault policy that allows
readon the secret path{mount}/data/{orgId}/*. - The platform's credential encryption key must be set by the platform operator (used to encrypt the Vault config row at rest in
rensei-encrypted).
Configuration
Vault is configured per-org. The config is stored as an encrypted JSON payload in a credentials row with providerType = 'vault'.
Configuration fields
| Field | Type | Required | Description |
|---|---|---|---|
addr | URL | Yes | Vault server URL (e.g. https://vault.example.com:8200) |
namespace | string | No | Vault Enterprise namespace |
mount | string | Yes | KV v2 mount path (e.g. secret) |
authMode | string | Yes | token, approle, or kubernetes |
token | string | If token mode | Vault token (stored encrypted in rensei-encrypted) |
roleId | string | If approle mode | AppRole Role ID |
secretId | string | If approle mode | AppRole Secret ID |
role | string | If kubernetes mode | Vault Kubernetes auth role name |
jwtPath | string | No | Override for the ServiceAccount JWT file path |
pathTemplate | string | No | Override for the secret path template |
Setup via Settings UI
Go to Settings → Security → Credential Backend.
Click Configure HashiCorp Vault.
Enter the Vault server address, mount, and auth mode.
Provide the auth-mode-specific credentials (token, AppRole roleId+secretId, or Kubernetes role name).
Click Test Connection to verify Vault is reachable and the auth credentials are valid.
Click Save. The provider registers immediately for the org.
Setup via API
curl -X POST https://rensei.ai/api/org/credential-backend \
-H "Authorization: Bearer rsk_live_..." \
-H "Content-Type: application/json" \
-d '{
"providerType": "vault",
"config": {
"addr": "https://vault.example.com:8200",
"mount": "secret",
"authMode": "approle",
"roleId": "my-role-id",
"secretId": "my-secret-id"
}
}'Secret path convention
By default, the provider looks up secrets at:
{mount}/data/{orgId}/{kind}Where kind is the credential kind (e.g. anthropic-api-key, linear-oauth). The pathTemplate field overrides this default using {mount}, {orgId}, and {kind} placeholders.
Expected secret shape
The provider reads the data.data object from the KV v2 response and probes for the primary scalar using this field priority: value → accessToken → apiKey → token. If none of those keys exist but other keys do, they are exposed as multiField.
# Example Vault secret layout
vault kv put secret/org_abc123/anthropic-api-key value="sk-ant-..."
vault kv put secret/org_abc123/jira-credentials site="myorg.atlassian.net" email="bot@example.com" apiToken="..."Authentication modes
Token mode
Simplest for development. The Vault token is stored encrypted in the Rensei credentials table. There is no upstream TTL signal - refreshAt defaults to resolvedAt + 1h.
AppRole mode
Recommended for production deployments without Kubernetes. The provider exchanges roleId + secretId for a Vault client_token at first resolve. The token is cached in-process and refreshed lazily at 80% of the lease_duration.
The AppRole secretId is itself a sensitive credential. In production, use Vault Response Wrapping to prevent the secretId from persisting in plaintext. Plain secretId storage in the config row is the MVP mode - wrapping support is a planned follow-up.
Kubernetes mode
For platform deployments on Kubernetes. The provider reads the ServiceAccount JWT from the kubelet-projected volume (default path: /var/run/secrets/kubernetes.io/serviceaccount/token) and exchanges it for a Vault token via /v1/auth/kubernetes/login. The JWT path can be overridden via jwtPath for sidecar layouts.
{
"addr": "https://vault.example.com:8200",
"mount": "secret",
"authMode": "kubernetes",
"role": "rensei-platform"
}The Vault token returned from login is cached per (orgId, role) and renewed at 80% of lease lifetime.
Refresh policy
| Auth mode | refreshAt calculation |
|---|---|
| Token | resolvedAt + 1h (no upstream TTL) |
| AppRole | loginTime + 0.8 × lease_duration |
| Kubernetes | loginTime + 0.8 × lease_duration |
| KV read lease | resolvedAt + 0.8 × response.lease_duration when > 0 |
No background timers are spawned. Refresh happens lazily on the next resolve() call after refreshAt.
Security notes
- Vault tokens are never logged or included in error messages. All non-2xx error paths redact the
X-Vault-Tokenheader value before throwing. - Kubernetes mode also redacts the ServiceAccount JWT from error messages.
- The provider makes all HTTP calls with a 30-second timeout. Vault connection failures surface as
CredentialNotFoundErrorto callers. - This provider does not auto-register. Configuring Vault in Settings activates it only for the configured org.
Health check
The Settings UI runs a health check that performs a test resolve() against the configured Vault server. You can also trigger it via the API:
curl -X POST https://rensei.ai/api/org/credential-backend/vault/health \
-H "Authorization: Bearer rsk_live_..."
# Returns: { "ok": true, "latencyMs": 45 } or { "ok": false, "error": "..." }Related pages
- Credentials Overview - provider family, dispatch adapter, blocklist
- 1Password
- AWS Secrets Manager
- GCP Secret Manager