Security Hardening Guide
This guide provides comprehensive security best practices for deploying DataTruth in production.
Table of Contents
- Pre-Production Security Checklist
- Authentication and Authorization
- Database Security
- API Security
- Network Security
- Data Protection
- Monitoring and Logging
- Incident Response
Pre-Production Security Checklist
Before deploying to production, ensure all items are completed:
Critical (Must Do)
- Change all default passwords
- Generate strong SECRET_KEY and JWT_SECRET_KEY
- Enable HTTPS with valid SSL certificate
- Restrict CORS origins to your domain only
- Disable DEBUG mode in production
- Configure firewall rules
- Set up database backups
- Enable rate limiting
- Review and restrict file permissions
- Set secure password policy
Recommended
- Enable database encryption at rest
- Set up WAF (Web Application Firewall)
- Configure log monitoring and alerts
- Implement IP whitelisting for admin access
- Set up VPN for database access
- Enable MFA for admin accounts
- Regular security scanning
- Penetration testing
Authentication and Authorization
Password Security
1. Change Default Passwords
# Default users (CHANGE IMMEDIATELY!)
# admin / admin123
# analyst / analyst123
# Login and change passwords via API:
curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "admin123"}'
# Change password
curl -X PUT http://localhost:8000/api/v1/users/me/password \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"current_password": "admin123",
"new_password": "YourStr0ng!P@ssw0rd"
}'
2. Password Requirements
Configure in .env:
# Minimum password length
PASSWORD_MIN_LENGTH=12
# Password complexity requirements
PASSWORD_REQUIRE_UPPERCASE=true
PASSWORD_REQUIRE_LOWERCASE=true
PASSWORD_REQUIRE_NUMBERS=true
PASSWORD_REQUIRE_SPECIAL=true
# Password expiration (days)
PASSWORD_EXPIRATION_DAYS=90
# Failed login lockout
MAX_LOGIN_ATTEMPTS=5
LOCKOUT_DURATION_MINUTES=30
3. JWT Token Security
# Generate strong secret keys
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
JWT_SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
# Add to .env
echo "SECRET_KEY=$SECRET_KEY" >> .env
echo "JWT_SECRET_KEY=$JWT_SECRET_KEY" >> .env
# Token expiration
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
Role-Based Access Control (RBAC)
User Roles:
- Admin: Full system access
- Analyst: Query and create metrics
- Viewer: Read-only access
Best Practices:
- Use least privilege principle
- Regularly audit user permissions
- Remove unused accounts
- Implement periodic access reviews
Database Security
PostgreSQL Security
1. Strong Passwords
# Generate strong database passwords
INTERNAL_DB_PASSWORD=$(openssl rand -base64 32)
INTERNAL_DB_ADMIN_PASSWORD=$(openssl rand -base64 32)
# Update .env
sed -i "s/INTERNAL_DB_PASSWORD=.*/INTERNAL_DB_PASSWORD=$INTERNAL_DB_PASSWORD/" .env
sed -i "s/INTERNAL_DB_ADMIN_PASSWORD=.*/INTERNAL_DB_ADMIN_PASSWORD=$INTERNAL_DB_ADMIN_PASSWORD/" .env
2. Network Access
# Restrict PostgreSQL to local network only
# In docker-compose.prod.yml:
services:
postgres:
ports:
- "127.0.0.1:5432:5432" # Bind to localhost only
3. Connection Encryption
Enable SSL for PostgreSQL connections:
# In .env
INTERNAL_DB_SSL_MODE=require
INTERNAL_DB_SSL_CERT=/path/to/client-cert.pem
INTERNAL_DB_SSL_KEY=/path/to/client-key.pem
INTERNAL_DB_SSL_ROOT_CERT=/path/to/ca-cert.pem
4. Backup Encryption
Encrypt database backups:
# Encrypted backup
./bin/backup.sh
openssl enc -aes-256-cbc -salt -pbkdf2 \
-in backups/datatruth_backup_*.sql.gz \
-out backups/datatruth_backup_*.sql.gz.enc
# Encrypted restore
openssl enc -aes-256-cbc -d -pbkdf2 \
-in backups/datatruth_backup_*.sql.gz.enc \
-out backups/datatruth_backup_*.sql.gz
./bin/restore.sh backups/datatruth_backup_*.sql.gz
5. Audit Logging
Enable PostgreSQL audit logging:
-- Enable logging
ALTER SYSTEM SET log_statement = 'all';
ALTER SYSTEM SET log_connections = on;
ALTER SYSTEM SET log_disconnections = on;
ALTER SYSTEM SET log_duration = on;
ALTER SYSTEM SET log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ';
SELECT pg_reload_conf();
API Security
HTTPS Configuration
1. Obtain SSL Certificate
Using Let’s Encrypt:
# Install certbot
sudo apt-get install certbot
# Obtain certificate
sudo certbot certonly --standalone -d yourdomain.com
# Certificates will be in:
# /etc/letsencrypt/live/yourdomain.com/fullchain.pem
# /etc/letsencrypt/live/yourdomain.com/privkey.pem
2. Configure Nginx for HTTPS
Update nginx/nginx.conf:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Strong SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Other security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
location / {
proxy_pass http://api:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
CORS Configuration
Restrict CORS to your domain:
# In .env
CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
CORS_ALLOW_CREDENTIALS=true
Rate Limiting
Enable and configure rate limiting:
# In .env
ENABLE_RATE_LIMITING=true
RATE_LIMIT_PER_MINUTE=60
RATE_LIMIT_PER_HOUR=1000
RATE_LIMIT_PER_DAY=10000
# Stricter limits for auth endpoints
AUTH_RATE_LIMIT_PER_MINUTE=5
AUTH_RATE_LIMIT_PER_HOUR=20
API Key Security
For external integrations:
# Generate API keys
API_KEY=$(python3 -c "import secrets; print(f'dt_{secrets.token_urlsafe(32)}')")
# Store securely (use secrets manager in production)
# e.g., AWS Secrets Manager, HashiCorp Vault
Network Security
Firewall Configuration
Using UFW (Ubuntu):
# Default deny
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH
sudo ufw allow 22/tcp
# Allow HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable firewall
sudo ufw enable
Using iptables:
# Flush existing rules
sudo iptables -F
# Default policies
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
# Allow loopback
sudo iptables -A INPUT -i lo -j ACCEPT
# Allow established connections
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP/HTTPS
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Save rules
sudo iptables-save > /etc/iptables/rules.v4
VPN Access
For administrative access:
# Install OpenVPN or WireGuard
# Route admin traffic through VPN only
# Restrict admin endpoints to VPN IP range
# In nginx.conf:
location /admin {
allow 10.8.0.0/24; # VPN subnet
deny all;
proxy_pass http://api:8000;
}
DDoS Protection
CloudFlare (Recommended):
- Enable CloudFlare proxy
- Configure rate limiting rules
- Enable bot protection
- Use page rules for sensitive endpoints
AWS Shield:
- Enable AWS Shield Standard (free)
- Consider AWS Shield Advanced for critical apps
Data Protection
Sensitive Data Handling
1. Database Credentials
Never store database credentials in code:
# ❌ BAD
conn = psycopg2.connect(
host="localhost",
password="mypassword" # Never hardcode!
)
# ✅ GOOD
from src.config import settings
conn = psycopg2.connect(
host=settings.INTERNAL_DB_HOST,
password=settings.INTERNAL_DB_PASSWORD
)
2. API Keys
Protect API keys:
# Use environment variables
OPENAI_API_KEY=sk-...
# Or use secrets manager
# AWS Secrets Manager
aws secretsmanager get-secret-value --secret-id datatruth/openai-api-key
# HashiCorp Vault
vault kv get secret/datatruth/openai-api-key
3. Sensitive Data Masking
Mask sensitive data in logs:
import re
def mask_sensitive_data(text: str) -> str:
"""Mask sensitive data in logs."""
# Mask API keys
text = re.sub(r'sk-[a-zA-Z0-9]{48}', 'sk-***', text)
# Mask passwords
text = re.sub(r'password["\']:\s*["\'][^"\']+["\']', 'password":"***"', text)
# Mask tokens
text = re.sub(r'Bearer\s+[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+', 'Bearer ***', text)
return text
Data Encryption
1. Encryption at Rest
Enable disk encryption:
# Linux: Use LUKS
sudo cryptsetup luksFormat /dev/sdX
sudo cryptsetup luksOpen /dev/sdX encrypted_volume
# Mount encrypted volume
sudo mount /dev/mapper/encrypted_volume /data
2. Encryption in Transit
Always use HTTPS for all API calls:
# Force HTTPS
if request.url.scheme != "https" and not settings.DEBUG:
return RedirectResponse(
url=request.url.replace(scheme="https")
)
Monitoring and Logging
Security Monitoring
1. Failed Login Attempts
Monitor and alert on failed logins:
-- Query failed login attempts
SELECT username, COUNT(*) as failed_attempts, MAX(created_at) as last_attempt
FROM user_activity
WHERE activity_type = 'failed_login'
AND created_at > NOW() - INTERVAL '1 hour'
GROUP BY username
HAVING COUNT(*) > 5
ORDER BY failed_attempts DESC;
2. Unusual Activity
Alert on unusual patterns:
- Login from new location/IP
- Bulk data exports
- Multiple failed queries
- Unusual time-of-day access
3. Log Aggregation
Use centralized logging:
ELK Stack:
# docker-compose.prod.yml
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
logstash:
image: docker.elastic.co/logstash/logstash:8.11.0
kibana:
image: docker.elastic.co/kibana/kibana:8.11.0
CloudWatch Logs:
# Install CloudWatch agent
sudo yum install amazon-cloudwatch-agent
# Configure log streaming
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config \
-m ec2 \
-s \
-c file:/opt/aws/amazon-cloudwatch-agent/etc/config.json
Audit Logging
Log all critical actions:
# Log admin actions
@app.post("/admin/users/{user_id}/delete")
async def delete_user(user_id: str, current_user: dict = Depends(require_admin)):
logger.info(f"Admin {current_user['username']} deleted user {user_id}")
# ... delete user
Incident Response
Response Plan
1. Identify
- Monitor alerts
- Investigate anomalies
- Confirm incident
2. Contain
- Isolate affected systems
- Block malicious IPs
- Revoke compromised credentials
3. Eradicate
- Remove malware
- Patch vulnerabilities
- Reset passwords
4. Recover
- Restore from backup
- Verify system integrity
- Monitor for recurrence
5. Learn
- Document incident
- Update security measures
- Train team
Emergency Procedures
Compromised API Key:
# 1. Revoke old key
# 2. Generate new key
NEW_API_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
# 3. Update .env
sed -i "s/OPENAI_API_KEY=.*/OPENAI_API_KEY=$NEW_API_KEY/" .env
# 4. Restart services
docker-compose -f docker-compose.prod.yml restart api
# 5. Notify users if needed
Database Breach:
# 1. Immediately change all database passwords
# 2. Rotate encryption keys
# 3. Force password reset for all users
# 4. Review audit logs
# 5. Restore from backup if necessary
DDoS Attack:
# 1. Enable CloudFlare "Under Attack" mode
# 2. Implement aggressive rate limiting
# 3. Block attacking IP ranges
sudo ufw deny from 192.168.1.0/24
# 4. Scale up infrastructure if needed
Contact Information
Maintain emergency contacts:
- Security team lead
- System administrator
- Cloud provider support
- Legal/compliance team
Security Checklist
Use this checklist for regular security audits:
Monthly
- Review user access and permissions
- Check for failed login attempts
- Review audit logs
- Verify backups are running
- Update dependencies
- Scan for vulnerabilities
Quarterly
- Rotate passwords
- Review and update firewall rules
- Penetration testing
- Security training for team
- Review incident response plan
- Update SSL certificates
Annually
- Full security audit
- Compliance review
- Disaster recovery drill
- Review and update security policies
- Third-party security assessment
Need Help?
For security concerns or questions:
- Email: security@datatruth.com
- Emergency: +1-XXX-XXX-XXXX
- Bug Bounty: https://datatruth.com/security/bug-bounty