from urllib.parse import urlparse from django.core.exceptions import ImproperlyConfigured from .base import * # noqa DEBUG = False # Traefik / reverse proxy terminates TLS and forwards HTTP with X-Forwarded-Proto. SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') USE_X_FORWARDED_HOST = env.bool('USE_X_FORWARDED_HOST', default=True) CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True SECURE_SSL_REDIRECT = True CSRF_TRUSTED_ORIGINS = env.list('CSRF_TRUSTED_ORIGINS', default=[]) # Общий кэш между gunicorn-воркерами (троттлинг логина). Отдельная Redis DB # от Celery broker (/0). Задайте CACHE_URL с requirepass в .env. CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': env('CACHE_URL', default='redis://127.0.0.1:6379/1'), } } def _redis_url_has_password(url: str) -> bool: if not url or not str(url).startswith(('redis://', 'rediss://')): return True # non-redis backends are out of scope here return bool(urlparse(str(url)).password) def _assert_redis_auth(name: str, url: str) -> None: if _redis_url_has_password(url): return # Temporary escape for cutover only — remove after requirepass is set. if env.bool('REDIS_ALLOW_UNAUTHENTICATED', default=False): import logging logging.getLogger(__name__).warning( '%s has no Redis password; set requirepass and remove ' 'REDIS_ALLOW_UNAUTHENTICATED', name, ) return raise ImproperlyConfigured( f'{name} must include a Redis password in production ' f'(redis://:PASSWORD@127.0.0.1:6379/N). ' f'Set requirepass on redis-server, or temporarily ' f'REDIS_ALLOW_UNAUTHENTICATED=1 during cutover.' ) # В production ключ шифрования полей обязан быть задан явно (не fallback на SECRET_KEY). if not FIELD_ENCRYPTION_KEY: raise ImproperlyConfigured( 'FIELD_ENCRYPTION_KEY must be set in production (.env). ' 'Use a value distinct from SECRET_KEY when rotating secrets.' ) # Redis без пароля + reachable broker = enqueue Celery (в т.ч. bulk identity). _assert_redis_auth('CACHE_URL', CACHES['default']['LOCATION']) _assert_redis_auth('CELERY_BROKER_URL', CELERY_BROKER_URL) if CELERY_RESULT_BACKEND: _assert_redis_auth('CELERY_RESULT_BACKEND', CELERY_RESULT_BACKEND)