centralize guides and rails under mosaic with runtime compatibility links
This commit is contained in:
192
guides/vault-secrets.md
Normal file
192
guides/vault-secrets.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Vault Secrets Management Guide
|
||||
|
||||
This guide applies when the project uses HashiCorp Vault for secrets management.
|
||||
|
||||
## Before Starting
|
||||
1. Verify Vault access: `vault status`
|
||||
2. Authenticate: `vault login` (method depends on environment)
|
||||
3. 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```json
|
||||
// secret-prod/postgres/database/app
|
||||
{
|
||||
"username": "app_user",
|
||||
"password": "secure-password-here",
|
||||
"host": "db.example.com",
|
||||
"port": "5432",
|
||||
"database": "myapp"
|
||||
}
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
1. **DO NOT GUESS** secret paths - Always verify the path exists
|
||||
2. **Use helper scripts** in `scripts/vault/` when available
|
||||
3. **All lowercase, hyphenated** (kebab-case) for all path segments
|
||||
4. **Standard field names** - Use the conventions above
|
||||
5. **No sensitive data in path names** - Path itself should not reveal secrets
|
||||
6. **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
|
||||
```bash
|
||||
# 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):**
|
||||
```python
|
||||
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):**
|
||||
```javascript
|
||||
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:**
|
||||
```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:
|
||||
|
||||
1. Request through proper channels (ticket, PR to IaC repo)
|
||||
2. Follow the canonical structure
|
||||
3. Document the secret's purpose
|
||||
4. Set appropriate access policies
|
||||
|
||||
```bash
|
||||
# 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 list` to 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
|
||||
|
||||
1. **Least privilege** - Request only the permissions you need
|
||||
2. **Short-lived tokens** - Use tokens with appropriate TTLs
|
||||
3. **Audit logging** - All access is logged; act accordingly
|
||||
4. **No local copies** - Don't store secrets in files or env vars long-term
|
||||
5. **Rotate on compromise** - Immediately rotate any exposed secrets
|
||||
Reference in New Issue
Block a user