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:
pacnpal
2025-12-23 16:41:42 -05:00
parent ae31e889d7
commit edcd8f2076
155 changed files with 22046 additions and 4645 deletions

View 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())
"
```