Files
go-caatsm/docs/secret-management.md
T

428 lines
11 KiB
Markdown
Raw Normal View History

# Secret Management Guide
This document describes best practices for managing secrets and sensitive configuration in the CAATSM application.
## Current Approach
The application currently supports secrets via environment variables with the `CAATSM_` prefix:
```bash
export CAATSM_POSTGRES_URL="postgres://user:password@localhost:5432/aviation"
export CAATSM_NATS_AUTH_TOKEN="your-token"
export CAATSM_NATS_AUTH_PASSWORD="secure-password"
```
**Security considerations:**
- Environment variables are visible to all processes on the system
- Secrets may be logged in process lists or shell history
- No automatic rotation or expiration
- Manual management required
## Recommended Secret Management Systems
For production deployments, use a dedicated secret management system:
### Option 1: HashiCorp Vault (Recommended)
[Vault](https://www.vaultproject.io/) provides secure secret storage with dynamic secrets, encryption, and access control.
#### Setup
1. **Install Vault:**
```bash
# Download and install Vault
wget https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
unzip vault_1.15.0_linux_amd64.zip
sudo mv vault /usr/local/bin/
```
2. **Start Vault (dev mode for testing):**
```bash
vault server -dev
```
3. **Store secrets:**
```bash
export VAULT_ADDR='http://127.0.0.1:8200'
vault kv put secret/caatsm \
postgres_url="postgres://user:pass@db:5432/aviation" \
nats_token="your-token" \
nats_password="secure-password"
```
#### Integration
Create a wrapper script or init container to fetch secrets from Vault:
```bash
#!/bin/bash
# fetch-secrets.sh
export VAULT_ADDR="${VAULT_ADDR:-http://vault:8200}"
export VAULT_TOKEN="${VAULT_TOKEN}"
# Fetch secrets from Vault
vault kv get -format=json secret/caatsm | jq -r '.data.data | to_entries | .[] | "export CAATSM_\(.key | ascii_upcase | gsub("-"; "_"))=\(.value)"' > /tmp/secrets.env
# Source secrets
source /tmp/secrets.env
# Start application
exec ./bin/receiver listen
```
#### Kubernetes Integration
Use Vault Agent Sidecar or Vault Secrets Operator:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: caatsm-receiver
spec:
containers:
- name: vault-agent
image: vault:latest
command: ["/bin/sh", "-c"]
args:
- |
vault agent -config=/vault/config/agent.hcl
- name: caatsm-receiver
image: caatsm/receiver:latest
envFrom:
- secretRef:
name: caatsm-secrets
```
### Option 2: AWS Secrets Manager
For AWS deployments, use [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) for centralized secret management.
#### Setup
1. **Store secrets:**
```bash
aws secretsmanager create-secret \
--name caatsm/production \
--secret-string '{
"postgres_url": "postgres://user:pass@db:5432/aviation",
"nats_token": "your-token",
"nats_password": "secure-password"
}'
```
2. **Retrieve secrets:**
```bash
aws secretsmanager get-secret-value \
--secret-id caatsm/production \
--query SecretString \
--output text | jq -r 'to_entries | .[] | "export CAATSM_\(.key | ascii_upcase | gsub("-"; "_"))=\(.value)"'
```
#### Integration
Use AWS SDK or CLI in init container:
```bash
#!/bin/bash
# fetch-aws-secrets.sh
SECRET_JSON=$(aws secretsmanager get-secret-value \
--secret-id caatsm/production \
--query SecretString \
--output text)
echo "$SECRET_JSON" | jq -r 'to_entries | .[] | "export CAATSM_\(.key | ascii_upcase | gsub("-"; "_"))=\(.value)"' > /tmp/secrets.env
source /tmp/secrets.env
exec ./bin/receiver listen
```
### Option 3: Kubernetes Secrets
For Kubernetes deployments, use [Kubernetes Secrets](https://kubernetes.io/docs/concepts/configuration/secret/).
#### Setup
1. **Create secret:**
```bash
kubectl create secret generic caatsm-secrets \
--from-literal=postgres-url="postgres://user:pass@db:5432/aviation" \
--from-literal=nats-token="your-token" \
--from-literal=nats-password="secure-password"
```
2. **Use in deployment:**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: caatsm-receiver
spec:
template:
spec:
containers:
- name: receiver
image: caatsm/receiver:latest
env:
- name: CAATSM_POSTGRES_URL
valueFrom:
secretKeyRef:
name: caatsm-secrets
key: postgres-url
- name: CAATSM_NATS_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: caatsm-secrets
key: nats-token
```
#### Best Practices
- **Encrypt at rest**: Enable encryption for etcd (Kubernetes backend)
- **RBAC**: Restrict access to secrets using Role-Based Access Control
- **External Secrets Operator**: Use [External Secrets Operator](https://external-secrets.io/) for integration with external secret stores
### Option 4: Docker Secrets
For Docker Swarm deployments, use [Docker Secrets](https://docs.docker.com/engine/swarm/secrets/).
#### Setup
1. **Create secret:**
```bash
echo "your-secret-value" | docker secret create caatsm_nats_token -
```
2. **Use in service:**
```yaml
version: '3.8'
services:
receiver:
image: caatsm/receiver:latest
secrets:
- caatsm_nats_token
environment:
- CAATSM_NATS_AUTH_TOKEN_FILE=/run/secrets/caatsm_nats_token
```
## Secret Rotation
### Manual Rotation
1. **Update secret** in secret management system
2. **Restart application** to pick up new secret
3. **Verify** application is working correctly
4. **Remove old secret** after verification
### Automated Rotation
For AWS Secrets Manager, enable automatic rotation:
```bash
aws secretsmanager rotate-secret \
--secret-id caatsm/production \
--rotation-lambda-arn arn:aws:lambda:region:account:function:rotate-secret
```
For Vault, use dynamic secrets or scheduled rotation policies.
## Security Best Practices
### 1. Principle of Least Privilege
- **Minimal access**: Grant only necessary permissions
- **Service accounts**: Use dedicated service accounts for applications
- **Secret scoping**: Limit secrets to specific services/environments
### 2. Encryption
- **Encryption at rest**: Ensure secrets are encrypted in storage
- **Encryption in transit**: Use TLS for secret retrieval
- **Key management**: Use proper key management (HSM, KMS, etc.)
### 3. Audit and Monitoring
- **Audit logs**: Enable audit logging for secret access
- **Monitoring**: Monitor secret access patterns
- **Alerts**: Set up alerts for unusual access patterns
### 4. Secret Lifecycle
- **Rotation**: Rotate secrets regularly (e.g., every 90 days)
- **Expiration**: Set expiration dates for secrets
- **Revocation**: Have a process for revoking compromised secrets
### 5. Development vs Production
- **Separate stores**: Use different secret stores for dev/staging/prod
- **No production secrets in code**: Never commit production secrets
- **Local development**: Use local secret files or dev vault instance
## Configuration Examples
### Environment Variables (Current)
```bash
# Development
export CAATSM_POSTGRES_URL="postgres://user:pass@localhost:5432/aviation?sslmode=disable"
export CAATSM_NATS_URL="nats://localhost:4222"
export CAATSM_NATS_AUTH_TOKEN="dev-token"
# Production (via secret management)
# Secrets loaded from Vault/AWS/K8s before application start
```
### Configuration File (Not Recommended for Secrets)
```toml
# config.prod.toml
# DO NOT store secrets in config files
# Use environment variables or secret management instead
[postgres]
# URL should come from CAATSM_POSTGRES_URL env var
url = "" # Empty, will be overridden by env var
[nats.auth]
# Token should come from CAATSM_NATS_AUTH_TOKEN env var
token = "" # Empty, will be overridden by env var
```
## Secret Injection Patterns
### Pattern 1: Init Container (Kubernetes)
```yaml
apiVersion: v1
kind: Pod
metadata:
name: caatsm-receiver
spec:
initContainers:
- name: fetch-secrets
image: vault:latest
command: ["/bin/sh", "-c"]
args:
- |
vault kv get -format=json secret/caatsm | \
jq -r '.data.data | to_entries | .[] | "\(.key | ascii_upcase | gsub("-"; "_"))=\(.value)"' > \
/shared/secrets.env
volumeMounts:
- name: shared-secrets
mountPath: /shared
containers:
- name: receiver
image: caatsm/receiver:latest
envFrom:
- configMapRef:
name: caatsm-config
env:
- name: CAATSM_SECRETS_FILE
value: /shared/secrets.env
volumeMounts:
- name: shared-secrets
mountPath: /shared
volumes:
- name: shared-secrets
emptyDir: {}
```
### Pattern 2: Sidecar Container
```yaml
apiVersion: v1
kind: Pod
metadata:
name: caatsm-receiver
spec:
containers:
- name: vault-agent
image: vault:latest
command: ["vault", "agent", "-config=/vault/config/agent.hcl"]
volumeMounts:
- name: vault-config
mountPath: /vault/config
- name: receiver
image: caatsm/receiver:latest
envFrom:
- secretRef:
name: caatsm-secrets
volumes:
- name: vault-config
configMap:
name: vault-agent-config
```
### Pattern 3: Application-Level Integration
For applications that need to fetch secrets at runtime:
```go
// Example: Fetch secrets from Vault at startup
func loadSecretsFromVault() error {
client, err := vault.NewClient(vault.DefaultConfig())
if err != nil {
return err
}
secret, err := client.Logical().Read("secret/data/caatsm")
if err != nil {
return err
}
// Set environment variables
for k, v := range secret.Data["data"].(map[string]interface{}) {
os.Setenv("CAATSM_"+strings.ToUpper(k), v.(string))
}
return nil
}
```
## Troubleshooting
### Secret Not Found
**Symptoms:**
- Application fails to start
- Connection errors to database/NATS
**Solutions:**
- Verify secret exists in secret store
- Check secret name/path is correct
- Verify application has permissions to access secret
- Check secret format (JSON, plain text, etc.)
### Secret Access Denied
**Symptoms:**
- Authentication errors when fetching secrets
- Permission denied errors
**Solutions:**
- Verify IAM roles/service accounts have correct permissions
- Check Vault policies or AWS IAM policies
- Verify authentication tokens/credentials are valid
### Secret Rotation Issues
**Symptoms:**
- Application fails after secret rotation
- Connection errors after rotation
**Solutions:**
- Implement graceful secret reloading
- Use connection pooling with automatic reconnection
- Test rotation process in staging first
## References
- [HashiCorp Vault Documentation](https://www.vaultproject.io/docs)
- [AWS Secrets Manager Documentation](https://docs.aws.amazon.com/secretsmanager/)
- [Kubernetes Secrets Documentation](https://kubernetes.io/docs/concepts/configuration/secret/)
- [External Secrets Operator](https://external-secrets.io/)
- [12-Factor App: Config](https://12factor.net/config)