5.2 KiB
5.2 KiB
Vault Secrets Management Guide
This guide applies when the project uses HashiCorp Vault for secrets management.
Before Starting
- Verify Vault access:
vault status - Authenticate:
vault login(method depends on environment) - Check your permissions for the required paths
Canonical Structure
ALL Vault secrets MUST follow this structure:
{mount}/{service}/{component}/{secret-name}
Components
- mount: Environment-specific mount point
- service: The service or application name
- component: Logical grouping (database, api, oauth, etc.)
- secret-name: Specific secret identifier
Environment Mounts
| Mount | Environment | Usage |
|---|---|---|
secret-dev/ |
Development | Local dev, CI |
secret-staging/ |
Staging | Pre-production testing |
secret-prod/ |
Production | Live systems |
Examples
# Database credentials
secret-prod/postgres/database/app
secret-prod/mysql/database/readonly
secret-staging/redis/auth/default
# API tokens
secret-prod/authentik/admin/token
secret-prod/stripe/api/live-key
secret-dev/sendgrid/api/test-key
# JWT/Authentication
secret-prod/backend-api/jwt/signing-key
secret-prod/auth-service/session/secret
# OAuth providers
secret-prod/backend-api/oauth/google
secret-prod/backend-api/oauth/github
# Internal services
secret-prod/loki/read-auth/admin
secret-prod/grafana/admin/password
Standard Field Names
Use consistent field names within secrets:
| Purpose | Fields |
|---|---|
| Credentials | username, password |
| Tokens | token |
| OAuth | client_id, client_secret |
| Connection | url, host, port |
| Keys | public_key, private_key |
Example Secret Structure
// secret-prod/postgres/database/app
{
"username": "app_user",
"password": "secure-password-here",
"host": "db.example.com",
"port": "5432",
"database": "myapp"
}
Rules
- DO NOT GUESS secret paths - Always verify the path exists
- Use helper scripts in
scripts/vault/when available - All lowercase, hyphenated (kebab-case) for all path segments
- Standard field names - Use the conventions above
- No sensitive data in path names - Path itself should not reveal secrets
- Environment separation - Never reference prod secrets from dev
Deprecated Paths (DO NOT USE)
These legacy patterns are deprecated and should be migrated:
| Deprecated | Migrate To |
|---|---|
secret/infrastructure/* |
secret-{env}/{service}/... |
secret/oauth/* |
secret-{env}/{service}/oauth/{provider} |
secret/database/* |
secret-{env}/{service}/database/{user} |
secret/credentials/* |
secret-{env}/{service}/{component}/{name} |
Reading Secrets
CLI
# Read a secret
vault kv get secret-prod/postgres/database/app
# Get specific field
vault kv get -field=password secret-prod/postgres/database/app
# JSON output
vault kv get -format=json secret-prod/postgres/database/app
Application Code
Python (hvac):
import hvac
client = hvac.Client(url='https://vault.example.com')
secret = client.secrets.kv.v2.read_secret_version(
path='postgres/database/app',
mount_point='secret-prod'
)
password = secret['data']['data']['password']
Node.js (node-vault):
const vault = require('node-vault')({ endpoint: 'https://vault.example.com' });
const secret = await vault.read('secret-prod/data/postgres/database/app');
const password = secret.data.data.password;
Go:
secret, err := client.Logical().Read("secret-prod/data/postgres/database/app")
password := secret.Data["data"].(map[string]interface{})["password"].(string)
Writing Secrets
Only authorized personnel should write secrets. If you need a new secret:
- Request through proper channels (ticket, PR to IaC repo)
- Follow the canonical structure
- Document the secret's purpose
- Set appropriate access policies
# Example (requires write permissions)
vault kv put secret-dev/myapp/database/app \
username="dev_user" \
password="dev-password" \
host="localhost" \
port="5432"
Troubleshooting
Permission Denied
Error: permission denied
- Verify your token has read access to the path
- Check if you're using the correct mount point
- Confirm the secret path exists
Secret Not Found
Error: no value found at secret-prod/data/service/component/name
- Verify the exact path (use
vault kv listto explore) - Check for typos in service/component names
- Confirm you're using the correct environment mount
Token Expired
Error: token expired
- Re-authenticate:
vault login - Check token TTL:
vault token lookup
Security Best Practices
- Least privilege - Request only the permissions you need
- Short-lived tokens - Use tokens with appropriate TTLs
- Audit logging - All access is logged; act accordingly
- No local copies - Don't store secrets in files or env vars long-term
- Rotate on compromise - Immediately rotate any exposed secrets