# Secret Management Guide This guide covers best practices for managing secrets in ThrillWiki, including rotation procedures, integration with secret management services, and emergency procedures. ## Overview Secrets are sensitive configuration values that must be protected: - Database credentials - API keys and tokens - Encryption keys - Service passwords ThrillWiki provides a flexible secret management system that can work with environment variables (development) or integrate with enterprise secret management services (production). ## Secret Classification ### Critical Secrets (Immediate rotation required if compromised) | Secret | Impact | Rotation Frequency | |--------|--------|-------------------| | `SECRET_KEY` | All cryptographic operations | 90 days recommended | | `DATABASE_URL` | Database access | On suspected breach | | `SENTRY_DSN` | Error tracking access | On suspected breach | ### High-Priority Secrets | Secret | Impact | Rotation Frequency | |--------|--------|-------------------| | `CLOUDFLARE_IMAGES_API_TOKEN` | Image CDN access | 180 days | | `FORWARD_EMAIL_API_KEY` | Email sending | 180 days | | `TURNSTILE_SECRET_KEY` | CAPTCHA bypass | 365 days | ### Service Secrets | Secret | Impact | Rotation Frequency | |--------|--------|-------------------| | `CLOUDFLARE_IMAGES_WEBHOOK_SECRET` | Webhook verification | 365 days | | `REDIS_URL` (with password) | Cache access | On suspected breach | ## Development Setup For development, use a `.env` file: ```bash # Copy the template cp .env.example .env # Generate a secure SECRET_KEY python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" # Edit .env with your values ``` ### Validation Validate your configuration: ```bash python manage.py validate_settings ``` ## Production Secret Management ### Option 1: Environment Variables (Simple) Set secrets as environment variables in your deployment platform: ```bash # Heroku heroku config:set SECRET_KEY="your-secret-key" # Docker docker run -e SECRET_KEY="your-secret-key" ... # Kubernetes (from secret) kubectl create secret generic thrillwiki-secrets \ --from-literal=SECRET_KEY="your-secret-key" ``` ### Option 2: AWS Secrets Manager For AWS deployments, integrate with Secrets Manager: ```python # In config/settings/secrets.py, implement: from config.settings.secrets import SecretProvider class AWSSecretsProvider(SecretProvider): def __init__(self, secret_name: str): import boto3 self.client = boto3.client('secretsmanager') self.secret_name = secret_name self._cache = {} def get_secret(self, name: str) -> str: if not self._cache: response = self.client.get_secret_value( SecretId=self.secret_name ) import json self._cache = json.loads(response['SecretString']) return self._cache.get(name) # Usage in settings from config.settings.secrets import set_secret_provider set_secret_provider(AWSSecretsProvider('thrillwiki/production')) ``` ### Option 3: HashiCorp Vault For Vault integration: ```python class VaultSecretsProvider(SecretProvider): def __init__(self, vault_addr: str, token: str, path: str): import hvac self.client = hvac.Client(url=vault_addr, token=token) self.path = path def get_secret(self, name: str) -> str: response = self.client.secrets.kv.read_secret_version( path=self.path ) return response['data']['data'].get(name) ``` ## Secret Rotation Procedures ### Rotating SECRET_KEY **Impact:** All sessions will be invalidated. Users will need to log in again. 1. **Prepare the new key:** ```bash python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" ``` 2. **Update deployment:** ```bash # Update environment variable export SECRET_KEY="new-secret-key-here" export SECRET_KEY_VERSION="2" # Increment version ``` 3. **Deploy during low-traffic period** 4. **Clear session cache:** ```bash python manage.py clearsessions ``` 5. **Monitor for issues:** - Check error rates - Monitor login success rates - Watch for authentication errors ### Rotating Database Credentials **Impact:** Application downtime if not done carefully. 1. **Create new database user:** ```sql CREATE USER thrillwiki_new WITH PASSWORD 'new-password'; GRANT ALL PRIVILEGES ON DATABASE thrillwiki TO thrillwiki_new; ``` 2. **Update application:** ```bash export DATABASE_URL="postgis://thrillwiki_new:new-password@host:5432/thrillwiki" ``` 3. **Deploy and verify** 4. **Remove old user:** ```sql DROP USER thrillwiki_old; ``` ### Rotating API Keys For third-party API keys: 1. **Generate new key** in the service's dashboard 2. **Update environment variable** 3. **Deploy** 4. **Revoke old key** in the service's dashboard ## Automated Rotation ### Enable Rotation Monitoring ```bash # In .env SECRET_ROTATION_ENABLED=True SECRET_KEY_VERSION=1 SECRET_EXPIRY_WARNING_DAYS=30 ``` ### Check Rotation Status ```bash python manage.py validate_settings --secrets-only ``` ### Automated Alerts Configure logging to alert on expiry warnings: ```python # In your monitoring setup, watch for: # Logger: security # Level: WARNING # Message contains: "Secret expiry" ``` ## Emergency Procedures ### Suspected Credential Compromise 1. **Immediate Actions:** - Rotate the compromised credential immediately - Check access logs for unauthorized use - Review related systems for compromise 2. **Investigation:** - Identify the source of the leak - Review access patterns - Document the incident 3. **Remediation:** - Fix the vulnerability that caused the leak - Update security procedures - Conduct a post-mortem ### Complete Secret Rotation (Breach Response) If a major breach is suspected, rotate all secrets: ```bash # 1. Generate new SECRET_KEY python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" # 2. Create new database credentials # 3. Regenerate all API keys in respective dashboards # 4. Update all environment variables # 5. Deploy # 6. Clear all caches python manage.py clear_cache # If you have this command redis-cli FLUSHALL # Or clear Redis directly # 7. Invalidate all sessions python manage.py clearsessions # 8. Revoke all old credentials ``` ## Security Best Practices ### Do's - ✅ Use different secrets for each environment - ✅ Rotate secrets regularly (90-180 days) - ✅ Use secret management services in production - ✅ Monitor for secret exposure (git-secrets, truffleHog) - ✅ Log secret access for audit trails - ✅ Use strong, randomly generated secrets ### Don'ts - ❌ Never commit secrets to version control - ❌ Never share secrets via chat or email - ❌ Never use the same secret across environments - ❌ Never use default or example secrets in production - ❌ Never log secret values (even partially) ## Audit and Compliance ### Access Logging Secret access is logged to the security logger: ```python # Logged events: # - Secret validation failures # - Secret rotation warnings # - Invalid secret format detections ``` ### Regular Audits Monthly security checklist: - [ ] Review secret rotation schedule - [ ] Check for exposed secrets in logs - [ ] Verify secret strength requirements - [ ] Audit secret access patterns - [ ] Test secret rotation procedures ## Troubleshooting ### "Secret validation failed" ```bash # Check the specific error python manage.py validate_settings # Common issues: # - Secret too short # - Placeholder value detected # - Missing required secret ``` ### "SECRET_KEY does not meet requirements" ```bash # Generate a proper key python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" ``` ### Secret provider errors ```bash # Test secret provider connectivity python -c " from config.settings.secrets import get_secret_provider provider = get_secret_provider() print(provider.list_secrets()) " ```