# Security Checklist - mockupAWS v0.5.0 > **Version:** 0.5.0 > **Purpose:** Pre-deployment security verification > **Last Updated:** 2026-04-07 --- ## Pre-Deployment Security Checklist Use this checklist before deploying mockupAWS to any environment. ### ๐Ÿ” Environment Variables #### Required Security Variables ```bash # JWT Configuration JWT_SECRET_KEY= # [REQUIRED] Min 32 chars, use: openssl rand -hex 32 JWT_ALGORITHM=HS256 # [REQUIRED] Must be HS256 ACCESS_TOKEN_EXPIRE_MINUTES=30 # [REQUIRED] Max 60 recommended REFRESH_TOKEN_EXPIRE_DAYS=7 # [REQUIRED] Max 30 recommended # Password Security BCRYPT_ROUNDS=12 # [REQUIRED] Min 12, higher = slower # Database DATABASE_URL= # [REQUIRED] Use strong password POSTGRES_PASSWORD= # [REQUIRED] Use: openssl rand -base64 32 # API Keys API_KEY_PREFIX=mk_ # [REQUIRED] Do not change ``` #### Checklist - [ ] `JWT_SECRET_KEY` is at least 32 characters - [ ] `JWT_SECRET_KEY` is unique per environment - [ ] `JWT_SECRET_KEY` is not the default/placeholder value - [ ] `BCRYPT_ROUNDS` is set to 12 or higher - [ ] Database password is strong (โ‰ฅ20 characters, mixed case, symbols) - [ ] No secrets are hardcoded in source code - [ ] `.env` file is in `.gitignore` - [ ] `.env` file has restrictive permissions (chmod 600) --- ### ๐ŸŒ HTTPS Configuration #### Production Requirements - [ ] TLS 1.3 is enabled - [ ] TLS 1.0 and 1.1 are disabled - [ ] Valid SSL certificate (not self-signed) - [ ] HTTP redirects to HTTPS - [ ] HSTS header is configured - [ ] Certificate is not expired #### Nginx Configuration Example ```nginx server { listen 443 ssl http2; server_name api.mockupaws.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; ssl_protocols TLSv1.3; ssl_ciphers 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256'; ssl_prefer_server_ciphers off; # HSTS add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; location / { proxy_pass http://backend:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } # Redirect HTTP to HTTPS server { listen 80; server_name api.mockupaws.com; return 301 https://$server_name$request_uri; } ``` --- ### ๐Ÿ›ก๏ธ Rate Limiting Verification #### Test Commands ```bash # Test auth rate limiting (should block after 5 requests) for i in {1..7}; do curl -X POST http://localhost:8000/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"test@test.com","password":"wrong"}' \ -w "Status: %{http_code}\n" -o /dev/null -s done # Expected: First 5 = 401, 6th+ = 429 # Test general rate limiting (should block after 100 requests) for i in {1..105}; do curl http://localhost:8000/health \ -w "Status: %{http_code}\n" -o /dev/null -s done # Expected: First 100 = 200, 101st+ = 429 ``` #### Checklist - [ ] Auth endpoints return 429 after 5 failed attempts - [ ] Rate limit headers are present in responses - [ ] Rate limits reset after time window - [ ] Different limits for different endpoint types - [ ] Burst allowance for legitimate traffic --- ### ๐Ÿ”‘ JWT Security Verification #### Secret Generation ```bash # Generate a secure JWT secret openssl rand -hex 32 # Example output: # a3f5c8e9d2b1f4a7c6e8d9b0a2c4e6f8a1b3d5c7e9f2a4b6c8d0e2f4a6b8c0d # Verify length (should be 64 hex chars = 32 bytes) openssl rand -hex 32 | wc -c # Expected: 65 (64 chars + newline) ``` #### Token Validation Tests ```bash # 1. Test valid token curl http://localhost:8000/api/v1/auth/me \ -H "Authorization: Bearer " # Expected: 200 with user data # 2. Test expired token curl http://localhost:8000/api/v1/auth/me \ -H "Authorization: Bearer " # Expected: 401 {"error": "token_expired"} # 3. Test invalid signature curl http://localhost:8000/api/v1/auth/me \ -H "Authorization: Bearer invalid.token.here" # Expected: 401 {"error": "invalid_token"} # 4. Test missing token curl http://localhost:8000/api/v1/auth/me # Expected: 401 {"error": "missing_token"} ``` #### Checklist - [ ] JWT secret is โ‰ฅ32 characters - [ ] Access tokens expire in 30 minutes - [ ] Refresh tokens expire in 7 days - [ ] Token rotation is implemented - [ ] Expired tokens are rejected - [ ] Invalid signatures are rejected - [ ] Token payload doesn't contain sensitive data --- ### ๐Ÿ—๏ธ API Keys Validation #### Creation Flow Test ```bash # 1. Create API key curl -X POST http://localhost:8000/api/v1/api-keys \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Test Key", "scopes": ["read:scenarios"], "expires_days": 30 }' # Response should include: {"key": "mk_xxxx...", ...} # โš ๏ธ Save this key - it won't be shown again! # 2. List API keys (should NOT show full key) curl http://localhost:8000/api/v1/api-keys \ -H "Authorization: Bearer " # Response should show: prefix, name, scopes, but NOT full key # 3. Use API key curl http://localhost:8000/api/v1/scenarios \ -H "X-API-Key: mk_xxxxxxxx..." # Expected: 200 with scenarios list # 4. Test revoked key curl http://localhost:8000/api/v1/scenarios \ -H "X-API-Key: " # Expected: 401 {"error": "invalid_api_key"} ``` #### Storage Verification ```sql -- Connect to database \c mockupaws -- Verify API keys are hashed (not plaintext) SELECT key_prefix, key_hash, LENGTH(key_hash) as hash_length FROM api_keys LIMIT 5; -- Expected: key_hash should be 64 chars (SHA-256 hex) -- Should NOT see anything like 'mk_' in key_hash column ``` #### Checklist - [ ] API keys use `mk_` prefix - [ ] Full key shown only at creation - [ ] Keys are hashed (SHA-256) in database - [ ] Only prefix is stored plaintext - [ ] Scopes are validated on each request - [ ] Expired keys are rejected - [ ] Revoked keys return 401 - [ ] Keys have associated user_id --- ### ๐Ÿ“ Input Validation Tests #### SQL Injection Test ```bash # Test SQL injection in scenario ID curl "http://localhost:8000/api/v1/scenarios/1' OR '1'='1" # Expected: 422 (validation error) or 404 (not found) # Should NOT return data or server error # Test in query parameters curl "http://localhost:8000/api/v1/scenarios?name='; DROP TABLE users; --" # Expected: 200 with empty list or validation error # Should NOT execute the DROP statement ``` #### XSS Test ```bash # Test XSS in scenario creation curl -X POST http://localhost:8000/api/v1/scenarios \ -H "Content-Type: application/json" \ -d '{ "name": "", "region": "us-east-1" }' # Expected: Script tags are escaped or rejected in response ``` #### Checklist - [ ] SQL injection attempts return errors (not data) - [ ] XSS payloads are escaped in responses - [ ] Input length limits are enforced - [ ] Special characters are handled safely - [ ] File uploads validate type and size --- ### ๐Ÿ”’ CORS Configuration #### Test CORS Policy ```bash # Test preflight request curl -X OPTIONS http://localhost:8000/api/v1/scenarios \ -H "Origin: http://localhost:5173" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: Content-Type,Authorization" \ -v # Expected response headers: # Access-Control-Allow-Origin: http://localhost:5173 # Access-Control-Allow-Methods: GET, POST, PUT, DELETE # Access-Control-Allow-Headers: Content-Type, Authorization # Test disallowed origin curl -X GET http://localhost:8000/api/v1/scenarios \ -H "Origin: http://evil.com" \ -v # Expected: No Access-Control-Allow-Origin header (or 403) ``` #### Checklist - [ ] CORS only allows configured origins - [ ] Credentials header is set correctly - [ ] Preflight requests work for allowed origins - [ ] Disallowed origins are rejected - [ ] CORS headers are present on all responses --- ### ๐Ÿšจ Security Headers #### Verify Headers ```bash curl -I http://localhost:8000/health # Expected headers: # X-Content-Type-Options: nosniff # X-Frame-Options: DENY # X-XSS-Protection: 1; mode=block # Strict-Transport-Security: max-age=31536000; includeSubDomains ``` #### Checklist - [ ] `X-Content-Type-Options: nosniff` - [ ] `X-Frame-Options: DENY` - [ ] `X-XSS-Protection: 1; mode=block` - [ ] `Strict-Transport-Security` (in production) - [ ] Server header doesn't expose version --- ### ๐Ÿ—„๏ธ Database Security #### Connection Security ```bash # Verify database uses SSL (production) psql "postgresql://user:pass@host/db?sslmode=require" # Check for SSL connection SHOW ssl; # Expected: on ``` #### User Permissions ```sql -- Verify app user has limited permissions \du app_user -- Should have: CONNECT, USAGE, SELECT, INSERT, UPDATE, DELETE -- Should NOT have: SUPERUSER, CREATEDB, CREATEROLE ``` #### Checklist - [ ] Database connections use SSL/TLS - [ ] Database user has minimal permissions - [ ] No default passwords in use - [ ] Database not exposed to public internet - [ ] Regular backups are encrypted --- ### ๐Ÿ“Š Logging and Monitoring #### Security Events to Log | Event | Log Level | Alert | |-------|-----------|-------| | Authentication failure | WARNING | After 5 consecutive | | Rate limit exceeded | WARNING | After 10 violations | | Invalid API key | WARNING | After 5 attempts | | Suspicious pattern | ERROR | Immediate | | Successful admin action | INFO | - | #### Checklist - [ ] Authentication failures are logged - [ ] Rate limit violations are logged - [ ] API key usage is logged - [ ] Sensitive data is NOT logged - [ ] Logs are stored securely - [ ] Log retention policy is defined --- ### ๐Ÿงช Final Verification Commands Run this complete test suite: ```bash #!/bin/bash # security-tests.sh BASE_URL="http://localhost:8000" JWT_TOKEN="your-test-token" API_KEY="your-test-api-key" echo "=== Security Verification Tests ===" # 1. HTTPS Redirect (production only) echo "Testing HTTPS redirect..." curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/health" # 2. Rate Limiting echo "Testing rate limiting..." for i in {1..6}; do CODE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/health") echo "Request $i: $CODE" done # 3. JWT Validation echo "Testing JWT validation..." curl -s "$BASE_URL/api/v1/auth/me" -H "Authorization: Bearer invalid" # 4. API Key Security echo "Testing API key validation..." curl -s "$BASE_URL/api/v1/scenarios" -H "X-API-Key: invalid_key" # 5. SQL Injection echo "Testing SQL injection protection..." curl -s "$BASE_URL/api/v1/scenarios/1%27%20OR%20%271%27%3D%271" # 6. XSS Protection echo "Testing XSS protection..." curl -s -X POST "$BASE_URL/api/v1/scenarios" \ -H "Content-Type: application/json" \ -d '{"name":"","region":"us-east-1"}' echo "=== Tests Complete ===" ``` --- ## Sign-off | Role | Name | Date | Signature | |------|------|------|-----------| | Security Lead | | | | | DevOps Lead | | | | | QA Lead | | | | | Product Owner | | | | --- ## Post-Deployment After deployment: - [ ] Verify all security headers in production - [ ] Test authentication flows in production - [ ] Verify API key generation works - [ ] Check rate limiting is active - [ ] Review security logs for anomalies - [ ] Schedule security review (90 days) --- *This checklist must be completed before any production deployment.* *For questions, contact the security team.*