Cómo conectar Django de forma segura a AWS S3 — Dos enfoques recomendados

Cómo conectar Django de forma segura a AWS S3 — Dos enfoques recomendados

Cuando despliegas aplicaciones Django en AWS, manejar el acceso a S3 de forma segura es fundamental. Dejar las credenciales expuestas en el código es un gran riesgo. Por suerte, AWS ofrece dos formas seguras y efectivas para autenticar tu backend cuando trabaja con S3:

🔐 Dos opciones seguras para acceder a S3 desde Django

OpciónDescripciónIdeal paraSeguridad
1. Variables de entorno en Elastic BeanstalkDefines tus claves de AWS directamente como variables en EBConfiguración rápida, entornos de staging o desarrolloSegura (si tu consola está protegida)
2. IAM Role asignado a EC2EC2 recibe credenciales temporales automáticamenteProducción, cumplimiento normativo, escalabilidadLa mejor práctica

Opción 1: Usar variables de entorno

1. El problema: Credenciales escritas en el código

Evita hacer esto en tu settings.py:

AWS_ACCESS_KEY_ID = "AKIA123..."
AWS_SECRET_ACCESS_KEY = "abcd123..."

2. Cargar las credenciales desde variables de entorno

import os

AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME")

3. Crear un script de carga: set_env.sh

#!/bin/bash
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="abcd..."
export AWS_STORAGE_BUCKET_NAME="nombre-de-tu-bucket"

Luego:

chmod +x set_env.sh

4. Agregarlo a .gitignore

# Secretos del entorno
set_env.sh

5. Automatizar la carga al activar el entorno virtual

# Al final del archivo envs/bin/activate
source /ruta/completa/a/tu/proyecto/set_env.sh

6. Prueba final

source envs/bin/activate
echo $AWS_ACCESS_KEY_ID

💡 ¿Por qué es importante?

Las variables de entorno mantienen tus claves fuera del código y evitan filtraciones accidentales. Es una excelente solución para desarrollo o staging.

Opción 2: Usar IAM Roles (recomendado para producción)

Con IAM Roles, AWS gestiona la autenticación automáticamente mediante credenciales temporales, sin necesidad de guardar nada.

Paso 1: Crear un IAM Role

  1. Ve a AWS Console > IAM > Roles
  2. Haz clic en Crear rol
  3. Selecciona: AWS Service → EC2
  4. Asocia la política AmazonS3FullAccess (o una personalizada)
  5. Asigna un nombre como DjangoStarsUp-InstanceRole-S3Only
  6. Haz clic en Crear rol

Paso 2: Asignar el rol a Elastic Beanstalk

  1. Ve a Elastic Beanstalk > tu entorno > Configuration
  2. Edita la sección Service access
  3. Selecciona el rol creado en EC2 instance profile
  4. Haz clic en Apply

Problema común: Falla en el health check

Elastic Beanstalk valida la salud de las instancias accediendo a /. Si Django no responde con 200 OK, marcará la instancia como fallida.

Paso 3: Agregar un endpoint de health check en Django

from django.http import JsonResponse
from django.urls import path

urlpatterns += [
    path("health/", lambda request: JsonResponse({"status": "ok"})),
]

Paso 4: Cambiar el health check path en EB

  1. Ve a Configuration > Instance traffic and scaling
  2. Edita el proceso llamado default
  3. Cambia el campo Health check path a /health/
  4. Guarda los cambios

Paso 5: Ajustar settings.py para usar IAM Role

import os

AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_STORAGE_BUCKET_NAME")

AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID", None)
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY", None)

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_S3_REGION_NAME = 'us-east-1'
AWS_QUERYSTRING_AUTH = False

if not AWS_ACCESS_KEY_ID or not AWS_SECRET_ACCESS_KEY:
    print("Usando IAM Role desde el perfil de instancia EC2")

Resultado final

Tu backend Django ahora se conecta a S3 de forma totalmente segura:

  • Sin claves en el código ni en disco
  • Con credenciales rotadas automáticamente
  • Escalable y en línea con buenas prácticas de AWS
  • Con un health check funcional para EB

Política personalizada de ejemplo

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::nombre-de-tu-bucket",
        "arn:aws:s3:::nombre-de-tu-bucket/*"
      ]
    }
  ]
}

¿Qué sigue?

En la Parte 3 te mostraremos cómo almacenar secretos y claves de forma segura usando AWS Secrets Manager en producción.