Secrets Management
Open Astra supports three secret backends for managing API keys and sensitive values, plus per-workspace API key overrides so tenants can supply their own credentials without exposing platform keys.
Secret backends
Set SECRET_BACKEND to select the backend. All backends use an in-process TTL cache (default 5 minutes) to avoid redundant network calls. On cache miss, every secret read is recorded to secret_audit_log.
| Backend | Value | When to use |
|---|---|---|
| Environment (default) | env | Development and simple deployments — reads directly from process.env |
| HashiCorp Vault | vault | Production — fetches the entire KV v2 secret blob and caches all keys |
| AWS Secrets Manager | aws-asm | AWS-native production — fetches a JSON-valued ASM secret |
HashiCorp Vault (KV v2)
Store all Astra secrets as a single JSON object at a KV v2 path. The gateway fetches the whole blob on startup and caches individual keys with a 5-minute TTL.
SECRET_BACKEND=vault
VAULT_ADDR=http://vault:8200
VAULT_TOKEN=s.xxxx
# Optional: custom path (default: secret/data/astra)
VAULT_PATH=secret/data/astra
SECRET_TTL_SECONDS=300The Vault secret object should be a flat JSON map of env var name → value:
{
"JWT_SECRET": "...",
"ANTHROPIC_API_KEY": "sk-ant-...",
"TYPESENSE_API_KEY": "...",
"INTERNAL_API_KEY": "..."
}AWS Secrets Manager
Requires @aws-sdk/client-secrets-manager installed at runtime. The secret value must be a JSON-encoded object with env var names as keys.
SECRET_BACKEND=aws-asm
AWS_REGION=us-east-1
AWS_SECRET_ID=prod/astra
# Also needs AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (or an IAM role)k8s/external-secrets.yaml (External Secrets Operator) to sync AWS ASM secrets automatically into a Kubernetes Secret that the pod mounts as environment variables.Fallback behaviour
If a Vault or ASM fetch fails at runtime (network error, token expiry), the gateway falls back to process.env for that key and logs a warning. The secret is not cached after a fallback fetch, so the next request will retry the remote backend.
Per-workspace API key overrides
Workspace owners and admins can store their own API keys for supported providers. When an agent runs inside that workspace, its provider client uses the workspace key instead of the platform-level env var. This enables multi-tenant SaaS deployments where each customer brings their own credentials.
Overrideable keys
| Env var | Provider |
|---|---|
OPENAI_API_KEY | OpenAI |
ANTHROPIC_API_KEY | Anthropic (Claude) |
GEMINI_API_KEY | Google Gemini |
GROK_API_KEY | xAI Grok |
GROQ_API_KEY | Groq |
BRAVE_API_KEY | Brave Search |
RESEND_API_KEY | Resend (Email) |
Setting a workspace secret
Requires owner or admin role. Values are stored encrypted in the workspace_secrets table. An optional expiry can be set in days.
# Set a per-workspace API key (owner or admin only)
curl -X PUT http://localhost:3000/workspaces/ws_abc123/secrets/ANTHROPIC_API_KEY \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{ "value": "sk-ant-...", "expiresInDays": 90 }'Listing workspace secrets
Returns metadata only — secret values are never returned by any API endpoint.
# List secret metadata (values are never returned)
curl http://localhost:3000/workspaces/ws_abc123/secrets \
-H "Authorization: Bearer ${JWT_TOKEN}"
# Response
[
{
"key": "ANTHROPIC_API_KEY",
"setBy": "usr_xyz",
"updatedAt": "2026-02-26T10:00:00Z",
"expiresAt": "2026-05-26T10:00:00Z"
}
]Deleting a workspace secret
curl -X DELETE http://localhost:3000/workspaces/ws_abc123/secrets/ANTHROPIC_API_KEY \
-H "Authorization: Bearer ${JWT_TOKEN}"Audit trail
Every secret read (cache hit or remote fetch) is recorded to the secret_audit_log table with the key name, backend used, and timestamp. All sensitive gateway operations (auth, workspace changes, secret writes) are also recorded to the audit_log table via the event bus. Both tables are created by migration 023-security-rbac.sql.
| Table | Records |
|---|---|
secret_audit_log | Every secret key read: key name, backend, timestamp |
audit_log | Sensitive operations: auth events, workspace changes, admin actions |
audit_log is populated by an event bus subscriber (src/events/audit.ts) that listens for structured events emitted by gateway routes. No additional configuration is required — it runs automatically when the gateway starts.