mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-24 12:11:08 -05:00
Add secret management guide, client-side performance monitoring, and search accessibility enhancements
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols. - Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage. - Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
This commit is contained in:
330
docs/configuration/secret-management.md
Normal file
330
docs/configuration/secret-management.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# 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())
|
||||
"
|
||||
```
|
||||
Reference in New Issue
Block a user