Fix security vulnerabilities and improve environment configuration

- Remove hardcoded SECRET_KEY from settings.py (now requires env var)
- Remove hardcoded database credentials from PostgreSQL config
- Add environment variable validation on Django startup
- Fix Stripe API key logging to prevent credential exposure
- Update .env.example to match Railway deployment structure
- Replace exposed API key in documentation with placeholder
- Maintain compatibility with existing Railway deployment setup

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude 2025-07-13 12:30:00 +05:30
parent 74e851b996
commit a6e9ca54d6
4 changed files with 63 additions and 30 deletions

View File

@ -1,25 +1,48 @@
SECRET_KEY=your-secret-key-here # Django
DEBUG=False SECRET_KEY=your-secret-key-here-generate-50-random-characters
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com DEBUG=True
CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com ALLOWED_HOSTS=localhost,127.0.0.1,your-domain.com
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
# Database # Database Configuration
DB_NAME=netcop_hub # Default: SQLite (simple, reliable, no setup required)
DB_USER=netcop_user # Railway: Automatically uses PostgreSQL via DATABASE_URL
DB_PASSWORD=your-db-password
DB_HOST=localhost
DB_PORT=5432
# Stripe # To use PostgreSQL locally (optional - for production parity):
STRIPE_SECRET_KEY=sk_live_your_stripe_secret_key # 1. Set up PostgreSQL (see docs/POSTGRESQL_SETUP.md)
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret # 2. Uncomment one of these options:
# AI Assistant Webhooks # Option 1: Use DATABASE_URL (explicit)
N8N_WEBHOOK_DATA_ANALYZER=your_n8n_webhook_url DATABASE_URL=postgresql://user:password@host:port/database
N8N_WEBHOOK_FIVE_WHYS=your_n8n_webhook_url
N8N_WEBHOOK_JOB_POSTING=your_n8n_webhook_url
N8N_WEBHOOK_FAQ_GENERATOR=your_n8n_webhook_url
N8N_WEBHOOK_SOCIAL_ADS=your_n8n_webhook_url
# OpenWeather API # Option 2: Use PostgreSQL flag (uses default credentials)
OPENWEATHER_API_KEY=your_openweather_api_key # USE_POSTGRESQL=True
# Option 3: Force SQLite (override auto-detection)
# DATABASE_URL=sqlite:///db.sqlite3
# External API Keys
NEXT_PUBLIC_OPENWEATHER_API_KEY=your_openweather_api_key_here
OPENWEATHER_API_KEY=your_openweather_api_key_here
# Stripe Configuration
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_publishable_key_here
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_stripe_webhook_secret_here
# N8N Webhook URLs (Frontend)
NEXT_PUBLIC_N8N_WEBHOOK_DATA_ANALYZER=https://your-n8n-instance.com/webhook/data-analyzer
NEXT_PUBLIC_N8N_WEBHOOK_FIVE_WHYS=https://your-n8n-instance.com/webhook/five-whys
NEXT_PUBLIC_N8N_WEBHOOK_JOB_POSTING=https://your-n8n-instance.com/webhook/job-posting
NEXT_PUBLIC_N8N_WEBHOOK_SOCIAL_ADS=https://your-n8n-instance.com/webhook/social-ads
NEXT_PUBLIC_N8N_WEBHOOK_FAQ_GENERATOR=https://your-n8n-instance.com/webhook/faq-generator
# Django N8N Webhook URLs (Backend)
N8N_WEBHOOK_DATA_ANALYZER=https://your-n8n-instance.com/webhook/data-analyzer
N8N_WEBHOOK_FIVE_WHYS=https://your-n8n-instance.com/webhook/five-whys
N8N_WEBHOOK_JOB_POSTING=https://your-n8n-instance.com/webhook/job-posting
N8N_WEBHOOK_SOCIAL_ADS=https://your-n8n-instance.com/webhook/social-ads
N8N_WEBHOOK_FAQ_GENERATOR=https://your-n8n-instance.com/webhook/faq-generator
# Security
CSRF_TRUSTED_ORIGINS=https://your-domain.com,https://www.your-domain.com

View File

@ -150,7 +150,7 @@ print("Agent created:", BaseAgent.objects.filter(slug='pdf-analyzer').exists())
**Add API credentials for your agent:** **Add API credentials for your agent:**
```bash ```bash
# Existing variables... # Existing variables...
OPENWEATHER_API_KEY=15befe6bac7b1cd0268900fb97d31482 OPENWEATHER_API_KEY=your_openweather_api_key_here
# Add your new agent's API key # Add your new agent's API key
DOCPARSER_API_KEY=your_actual_api_key_here DOCPARSER_API_KEY=your_actual_api_key_here

View File

@ -25,7 +25,17 @@ sys.path.insert(0, str(BASE_DIR / 'apps'))
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY', default='django-insecure-thdd^re4==p$4geq^$52w7%egd0xxrj#fpgk1c+$xt-jrr5d7%') SECRET_KEY = config('SECRET_KEY')
# Validate required environment variables
required_env_vars = ['SECRET_KEY']
missing_vars = [var for var in required_env_vars if not config(var, default='')]
if missing_vars:
import sys
print(f"❌ Missing required environment variables: {', '.join(missing_vars)}")
print("💡 Please create a .env file based on .env.example")
print("💡 For local development, copy .env.example to .env and fill in the values")
sys.exit(1)
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', default=True, cast=bool) DEBUG = config('DEBUG', default=True, cast=bool)
@ -129,11 +139,11 @@ else:
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql', 'ENGINE': 'django.db.backends.postgresql',
'NAME': 'netcop_hub', 'NAME': config('PGDATABASE', default='netcop_hub'),
'USER': 'netcop_user', 'USER': config('PGUSER', default='netcop_user'),
'PASSWORD': 'netcop_pass', 'PASSWORD': config('PGPASSWORD'),
'HOST': 'localhost', 'HOST': config('PGHOST', default='localhost'),
'PORT': '5432', 'PORT': config('PGPORT', default='5432'),
} }
} }
except ImportError: except ImportError:

View File

@ -35,7 +35,7 @@ class StripePaymentHandler:
print(f"🚀 [STRIPE DEBUG] Starting checkout session creation...") print(f"🚀 [STRIPE DEBUG] Starting checkout session creation...")
print(f"👤 User: {user.id} ({user.email})") print(f"👤 User: {user.id} ({user.email})")
print(f"💰 Amount: {amount} AED") print(f"💰 Amount: {amount} AED")
print(f"🔑 Stripe API Key (last 4): ...{settings.STRIPE_SECRET_KEY[-4:]}") print(f"🔑 Stripe API Key configured: {bool(settings.STRIPE_SECRET_KEY)}")
print(f"🔑 API Version: {stripe.api_version}") print(f"🔑 API Version: {stripe.api_version}")
print(f"📍 Success URL: {success_url}") print(f"📍 Success URL: {success_url}")
print(f"📍 Cancel URL: {cancel_url}") print(f"📍 Cancel URL: {cancel_url}")
@ -147,7 +147,7 @@ class StripePaymentHandler:
"""Verify payment directly from Stripe (bypasses webhook issues)""" """Verify payment directly from Stripe (bypasses webhook issues)"""
try: try:
print(f"🔍 [STRIPE DEBUG] Starting payment verification...") print(f"🔍 [STRIPE DEBUG] Starting payment verification...")
print(f"🔑 Using Stripe API Key (last 4): ...{settings.STRIPE_SECRET_KEY[-4:]}") print(f"🔑 Stripe API Key configured: {bool(settings.STRIPE_SECRET_KEY)}")
print(f"🔑 API Version: {stripe.api_version}") print(f"🔑 API Version: {stripe.api_version}")
print(f"💳 Session ID to verify: {session_id}") print(f"💳 Session ID to verify: {session_id}")