D/ DJANGO CON CRITERIO

UNIDAD 8 · AZURE Y DJANGO: CONFIGURACIÓN Y DESPLIEGUE

Seguridad en production.py: HTTPS, proxy y HSTS

Activa las defensas de transporte y verifica la configuración real del despliegue.

Ilustración: El perímetro HTTPS
El perímetro HTTPS

CAPÍTULO 9 · El mismo proyecto llega a Azure

Las opciones de producción adquieren sentido juntas

Al inicio colocamos en base.py la política común. Ahora tenemos un servicio expuesto por HTTPS y una explicación de su proxy, por lo que podemos completar el significado de las opciones específicas de producción. La separación de archivos evita que esas exigencias se confundan con las facilidades del desarrollo local.

Conservamos y estudiamos los valores del proyecto para redirección HTTPS, cookies seguras y HSTS, además de hosts y secretos. Revisamos uno por uno qué hacen y bajo qué condiciones. Por ejemplo, ampliar una política a subdominios obliga a conocer ese alcance; escribir una directiva no reemplaza preparar correctamente la infraestructura que la sostiene.

La configuración queda conectada con el recorrido real de la petición. Pero incluso una aplicación bien configurada puede fallar al acceder a una dependencia. Antes de declarar terminada la publicación necesitamos señales que permitan distinguir un proceso que existe de un servicio que está preparado para atender trabajo útil.

Leer esta parte dentro del relato completo →

DEL RELATO A LA PRÁCTICA

Vamos a desarrollar esta decisión con su mapa, explicación, código y ejercicio.

MIRA · CONECTA · COMPRENDE

El perímetro HTTPS

El perímetro HTTPS1. Proxy TLS: Protege transporte externo; 2. Django: Reconoce protocolo confiable; 3. Cookies Secure: Restringe envío a HTTPS; 4. HSTS: Comprueba alcance y duración01Proxy TLSProtege transporte externo02DjangoReconoce protocolo confiable03Cookies SecureRestringe envío a HTTPS04HSTSComprueba alcance y duración

Las flechas resumen el recorrido conceptual. Los controles y dependencias se detallan debajo.

Selecciona una pieza para destacar su responsabilidad.

Leer la explicación del mapa
  1. Proxy TLS. Protege transporte externo
  2. Django. Reconoce protocolo confiable
  3. Cookies Secure. Restringe envío a HTTPS
  4. HSTS. Comprueba alcance y duración
Descargar gráfico SVG ↓

¿Para qué sirve?

El proxy puede terminar TLS mientras Django recibe HTTP internamente. Si el entorno no reconoce esa arquitectura, puede redirigir en bucle o emitir cookies con una política incorrecta.

El concepto, explicado

production.py conserva los valores de seguridad del proyecto de referencia: redirección HTTPS, confianza del protocolo indicado por proxy, cookies Secure y HSTS de un año con subdominios y preload. Cada ajuste se explica abajo con su finalidad y comprobación.

La política exige un entorno productivo con HTTPS y un proxy que elimina o sobrescribe X-Forwarded-Proto del cliente. El proceso no debe aceptar accesos directos que eludan esa frontera. No actives esta confianza sobre un header que cualquier visitante pueda controlar.

El alcance de HSTS incluye los subdominios. Antes de servir esta política comprueba todo ese alcance bajo HTTPS. PRELOAD no realiza la inscripción externa por sí solo, y HSTS sin precarga efectiva no protege una primera visita que aún no conoce la política.

base.py ya declara las defensas comunes. production.py añade transporte y valores del entorno. development.py conserva su recorrido local HTTP. Los permisos de API, validación y escape se aplican además en sus componentes correspondientes.

Defensas de producción

AjusteObjetivoCómo comprobarlo
DEBUG=False / SECRET_KEYEvitar exposición interna y proteger firmasErrores sin traceback y clave exclusiva del entorno
ALLOWED_HOSTSLimitar Host aceptadosHost permitido y Host ajeno
CSRF_TRUSTED_ORIGINSPermitir solo los orígenes necesariosPOST cruzado autorizado y rechazado
SECURE_SSL_REDIRECTConducir el tráfico a HTTPSHTTP redirige, HTTPS no entra en bucle
SECURE_PROXY_SSL_HEADERReconocer HTTPS tras proxy confiableRevisar saneamiento del header y acceso directo
SESSION_COOKIE_SECURE / CSRF_COOKIE_SECUREEnviar esas cookies por HTTPSInspeccionar flags si se crean
SECURE_HSTS_SECONDSRecordar obligación HTTPSStrict-Transport-Security en HTTPS
SECURE_HSTS_INCLUDE_SUBDOMAINSExtender HSTS al alcance subordinadoTodos los subdominios usan HTTPS
SECURE_HSTS_PRELOADAnunciar intención de precargaRevisar requisitos e incorporación externa

Qué hace cada ajuste

1. DEBUG

DEBUG = False

Para qué y por qué se usa. Evita publicar las páginas detalladas de depuración con contexto interno cuando falla una petición.

Alcance y condiciones. No arregla el error subyacente ni impide registrar secretos indebidamente.

Cómo verificarlo. Provoca un fallo controlado en pruebas y comprueba que la respuesta no muestra el traceback.

2. SECRET_KEY

SECRET_KEY = os.environ["SECRET_KEY"]

Para qué y por qué se usa. Extrae la clave de firma desde el entorno productivo y evita versionarla en el código.

Alcance y condiciones. No cifra la base de datos ni sirve como client secret de MSAL. Usa una clave aleatoria exclusiva y controla su rotación.

Cómo verificarlo. Comprueba que falta de la variable impide arrancar, sin imprimir el valor.

3. ALLOWED_HOSTS

ALLOWED_HOSTS = [host.strip() for host in os.environ["ALLOWED_HOSTS"].split(",") if host.strip()]

Para qué y por qué se usa. Define los hosts que la aplicación acepta y limita manipulación del header Host.

Alcance y condiciones. No controla quién puede ejecutar un caso de uso. En esta academia se rechaza * y se requieren hosts sin esquema ni ruta.

Cómo verificarlo. El host previsto funciona y uno ajeno obtiene rechazo 400 al validarlo Django.

4. CSRF_TRUSTED_ORIGINS

CSRF_TRUSTED_ORIGINS = [origin.strip() for origin in os.environ.get("CSRF_TRUSTED_ORIGINS", "").split(",") if origin.strip()]

Para qué y por qué se usa. Declara orígenes adicionales de confianza para la comprobación CSRF cuando el flujo los necesita.

Alcance y condiciones. No desactiva el token CSRF, no configura CORS ni concede permisos de API. No amplíes la lista sin un caso legítimo.

Cómo verificarlo. Comprueba esquema https:// y un POST protegido con token desde un origen ajeno rechazado.

5. SECURE_SSL_REDIRECT

SECURE_SSL_REDIRECT = True

Para qué y por qué se usa. Redirige peticiones que Django reconoce como HTTP hacia HTTPS. Evita continuar navegaciones inseguras al sitio productivo.

Alcance y condiciones. La infraestructura debe disponer certificado y TLS. Una redirección no protege por sí sola el contenido de la primera solicitud HTTP.

Cómo verificarlo. HTTP devuelve redirección hacia HTTPS y HTTPS llega al sitio sin bucles.

6. SECURE_PROXY_SSL_HEADER

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Para qué y por qué se usa. Permite que Django reconozca HTTPS externo cuando el proxy termina TLS y comunica el protocolo mediante X-Forwarded-Proto.

Alcance y condiciones. Exige que el proxy elimine/sobrescriba valores enviados por el cliente y que no exista acceso directo que eluda esa frontera. Confiar en un header suplantable crea una falla de seguridad.

Cómo verificarlo. Comprueba el recorrido real del proxy, el saneamiento del header y que Django reconoce request.is_secure() en el flujo HTTPS.

7. SECURE_HSTS_SECONDS

SECURE_HSTS_SECONDS = 31536000

Para qué y por qué se usa. Anuncia un año de obligación de HTTPS a navegadores que reciben y conservan la política. Mitiga posteriores intentos de degradar la conexión a HTTP.

Alcance y condiciones. Sin una precarga efectiva no protege la primera visita que todavía no conoce la política. El navegador conserva la duración aunque cambies después el servidor.

Cómo verificarlo. Comprueba Strict-Transport-Security con max-age=31536000 en una respuesta HTTPS.

8. SECURE_HSTS_INCLUDE_SUBDOMAINS

SECURE_HSTS_INCLUDE_SUBDOMAINS = True

Para qué y por qué se usa. Extiende HSTS a los subdominios del host que publica la política. Cubre ese alcance cuando todos soportan HTTPS.

Alcance y condiciones. Todos los subdominios incluidos deben funcionar bajo HTTPS; uno legado puede quedar inaccesible.

Cómo verificarlo. Inspecciona includeSubDomains y verifica inventario, certificados y HTTPS en todo el alcance.

9. SECURE_HSTS_PRELOAD

SECURE_HSTS_PRELOAD = True

Para qué y por qué se usa. Añade la directiva preload para la política destinada a precarga. Expresa una intención que se completa con requisitos y procedimiento externo.

Alcance y condiciones. Este valor no inscribe automáticamente el dominio en las listas de navegadores. La incorporación y retirada tienen efectos de largo plazo.

Cómo verificarlo. Inspecciona preload y revisa por separado elegibilidad e incorporación real del dominio.

10. SESSION_COOKIE_SECURE

SESSION_COOKIE_SECURE = True

Para qué y por qué se usa. Marca la cookie de sesión para que el navegador la envíe solo por HTTPS. Reduce exposición en transporte sin cifrar.

Alcance y condiciones. No impide todo robo de sesión ni crea una sesión si la aplicación no la usa. En local HTTP puede impedir el flujo legítimo.

Cómo verificarlo. Cuando la app emite sessionid, verifica Secure y su envío bajo HTTPS.

11. CSRF_COOKIE_SECURE

CSRF_COOKIE_SECURE = True

Para qué y por qué se usa. Marca la cookie del token CSRF para que se envíe por HTTPS en producción.

Alcance y condiciones. No reemplaza validación del token y del origen. Requiere que el recorrido real use HTTPS.

Cómo verificarlo. Cuando se emite csrftoken, comprueba Secure y el POST protegido bajo HTTPS.

Implementación paso a paso

  1. Prepara HTTPS y el certificado del dominio productivo.
  2. Comprueba la frontera del proxy y todos los subdominios del alcance.
  3. Define SECRET_KEY, ALLOWED_HOSTS y los orígenes CSRF necesarios en el entorno.
  4. Conserva las asignaciones productivas del ejemplo sin trasladarlas a HTTP local.
  5. Ejecuta check --deploy con production.py.
  6. Comprueba cada control de la lista mediante peticiones y cabeceras reales.
  7. Registra la verificación del flujo productivo, incluidos cookies, acceso y retorno de identidad si aplica.

Ejemplo en SensorHub

"""Configuración HTTPS de producción; valores privados desde el entorno."""
from .base import *
from django.core.exceptions import ImproperlyConfigured


DEBUG = False
SECRET_KEY = os.environ['SECRET_KEY']
ALLOWED_HOSTS = [host.strip() for host in os.environ['ALLOWED_HOSTS'].split(',') if host.strip()]
if not ALLOWED_HOSTS or any(host == '*' or '://' in host or '/' in host for host in ALLOWED_HOSTS):
    raise ImproperlyConfigured('ALLOWED_HOSTS requiere hosts explícitos sin esquema ni rutas')
CSRF_TRUSTED_ORIGINS = [origin.strip() for origin in os.environ.get('CSRF_TRUSTED_ORIGINS', '').split(',') if origin.strip()]

# Transporte: el sitio productivo se sirve bajo HTTPS.
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

# El proxy de producción debe eliminar/sobrescribir el header del cliente
# y no permitir acceso directo que eluda esa frontera de confianza.
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# Política HSTS del proyecto de referencia: un año y todo el alcance.
# Requiere HTTPS correcto en todos los subdominios incluidos.
# PRELOAD anuncia la directiva; no realiza la inscripción externa.
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

STORAGES = {
    'default': {'BACKEND': 'django.core.files.storage.FileSystemStorage'},
    'staticfiles': {'BACKEND': 'whitenoise.storage.CompressedManifestStaticFilesStorage'},
}
MIDDLEWARE = [MIDDLEWARE[0], 'whitenoise.middleware.WhiteNoiseMiddleware', *MIDDLEWARE[1:]]

Cómo leer el ejemplo

  • Los valores HSTS son 31536000, True y True: año, subdominios y directiva preload.
  • El proxy HTTPS queda definido por HTTP_X_FORWARDED_PROTO=https; el entorno debe garantizar esa cabecera.
  • SESSION_COOKIE_SECURE y CSRF_COOKIE_SECURE son True en producción.
  • Las variables de secretos, hosts y orígenes siguen fuera del código.
  • WhiteNoise conserva su posición después de SecurityMiddleware.

Error habitual

Confiar en X-Forwarded-Proto sin comprobar que el proxy controle el valor recibido, o publicar HSTS para subdominios que no soportan HTTPS. Comprueba la infraestructura que hace válida la política.

05 / PRACTICAR

Tu turno

El sitio anuncia HSTS con includeSubDomains, pero un subdominio antiguo solo sirve HTTP. Explica el riesgo y qué debes preparar para cumplir esta política.

Ver solución orientativa

Los navegadores que conocen la política pueden forzar HTTPS en ese subdominio y dejarlo inaccesible si no lo admite. Debes inventariar el alcance y preparar HTTPS y certificados para todos los subdominios incluidos. El valor de preload tampoco prueba incorporación a una lista externa.

Cómo sabes que funciona

  • DEBUG=False y secretos no publicados.
  • HTTP redirige a HTTPS y la petición HTTPS real no entra en bucle.
  • La respuesta HTTPS anuncia el HSTS previsto y las cabeceras comunes.
  • Cuando se crean cookies de sesión/CSRF, sus flags son correctos.
  • Un host no autorizado recibe rechazo.

Para profundizar

Documentación oficial para comprobar configuración, permisos y condiciones vigentes. Revisión del tema: 11 de octubre de 2026.

CONTINUAR LA EXPERIENCIA

El siguiente paso del recorrido:

Despliegue, salud y observabilidad →Continuar en modo relato