Asegurando Aplicaciones Serverless: Gestión de Secretos con AWS Secrets Manager
Este tutorial te guiará a través de la gestión segura de secretos en tus aplicaciones serverless utilizando AWS Secrets Manager. Descubrirás cómo almacenar, rotar y recuperar credenciales de forma eficiente y segura, minimizando la exposición de datos sensibles. Ideal para desarrolladores y arquitectos que buscan fortalecer la postura de seguridad de sus sistemas serverless.
🚀 Introducción a la Seguridad Serverless y la Gestión de Secretos
En el mundo del Cloud Computing y, más específicamente, en la arquitectura Serverless, la seguridad es una preocupación primordial. Las funciones serverless, como AWS Lambda, a menudo necesitan acceder a bases de datos, APIs de terceros, o servicios con credenciales sensibles. La forma en que manejamos estos secretos (contraseñas, claves API, tokens de autenticación) es crítica para evitar brechas de seguridad.
Tradicionalmente, las credenciales se manejaban a menudo como variables de entorno o incrustadas directamente en el código. Sin embargo, estas prácticas son altamente inseguras. Las variables de entorno pueden ser accedidas si la infraestructura es comprometida, y el código con credenciales incrustadas es un riesgo si el repositorio es expuesto.
Aquí es donde entra en juego AWS Secrets Manager, un servicio de AWS diseñado para ayudarte a almacenar, administrar y recuperar secretos de forma segura. Permite proteger el acceso a tus aplicaciones, servicios y recursos de TI sin la necesidad de incrustar las credenciales directamente en el código.
¿Por qué AWS Secrets Manager? 🤔
AWS Secrets Manager ofrece una serie de ventajas clave para la gestión de secretos en entornos serverless:
- Seguridad Mejorada: Los secretos se cifran en reposo utilizando AWS Key Management Service (KMS) y en tránsito utilizando TLS.
- Rotación Automática: Permite la rotación automática de secretos, lo que reduce el riesgo de credenciales comprometidas y cumple con las mejores prácticas de seguridad.
- Control de Acceso Fino: Integración con AWS Identity and Access Management (IAM) para controlar quién puede acceder a qué secreto y bajo qué condiciones.
- Auditoría: Se integra con AWS CloudTrail para registrar todos los eventos de acceso a los secretos, proporcionando un rastro de auditoría completo.
- Reducción de la Deuda Técnica: Elimina la necesidad de escribir código personalizado para manejar la rotación de credenciales.
🛠️ Conceptos Clave de AWS Secrets Manager
Antes de sumergirnos en la implementación, es crucial entender los componentes principales de AWS Secrets Manager.
📖 Secretos (Secrets)
Un secreto en Secrets Manager es un registro de credenciales (o cualquier otra información sensible) que deseas proteger. Puede ser una contraseña, una clave API, un par de claves SSH, etc. Un secreto puede contener múltiples valores (por ejemplo, nombre de usuario y contraseña) y se almacena como texto sin formato o binario.
🔄 Rotación (Rotation)
La rotación de secretos es el proceso de cambiar las credenciales de un secreto periódicamente. Secrets Manager puede automatizar este proceso para bases de datos (como Amazon RDS, Amazon Aurora, Amazon Redshift), servicios (como Amazon DocumentDB) y otros secretos personalizados. Esto es fundamental para la seguridad, ya que las credenciales de larga duración son un riesgo.
🔑 AWS KMS (Key Management Service)
Secrets Manager utiliza AWS KMS para cifrar los secretos en reposo. Cuando creas un secreto, puedes elegir una clave KMS administrada por AWS o una clave KMS personalizada que tú administras. Esto añade una capa extra de seguridad y control.
🛡️ Políticas de Recursos (Resource Policies)
Al igual que con otros recursos de AWS, puedes adjuntar políticas de recursos a tus secretos en Secrets Manager. Estas políticas, junto con las políticas de IAM, determinan quién puede realizar qué acciones sobre un secreto específico.
Diagrama de Flujo General 📈
🚀 Primeros Pasos: Almacenar un Secreto en AWS Secrets Manager
Vamos a empezar por la tarea más básica: almacenar un secreto. Para este tutorial, asumiremos que tienes una cuenta de AWS y acceso a la consola de AWS.
Paso 1: Navegar a AWS Secrets Manager
- Inicia sesión en la Consola de AWS.
- En la barra de búsqueda, escribe
Secrets Managery selecciona el servicio. - Haz clic en el botón
Almacenar un nuevo secreto.
Paso 2: Configurar el Tipo de Secreto
Secrets Manager ofrece plantillas para diferentes tipos de secretos. Selecciona el que mejor se adapte a tus necesidades. Para nuestro ejemplo, vamos a almacenar credenciales para una base de datos PostgreSQL.
- Tipo de Secreto: Selecciona
Credenciales para base de datos RDS, Redshift o DocumentDB. - Credenciales: Ingresa el
Nombre de usuario(ej:admin) y laContraseña(ej:SuperSecretP@ssw0rd!). - Base de datos: Puedes elegir una instancia RDS existente o dejarlo sin especificar si es para una DB externa o si no quieres asociarlo aún.
- Haz clic en
Siguiente.
Paso 3: Detalles del Secreto
Ahora, proporciona un nombre y una descripción para tu secreto.
- Nombre del Secreto: Ingresa un nombre descriptivo, por ejemplo,
/my-serverless-app/db-credentials.- Importante: Es una buena práctica usar una convención de nomenclatura que incluya el nombre de la aplicación o entorno.
- Descripción: Añade una descripción útil (ej:
Credenciales de la base de datos para la aplicación serverless). - Haz clic en
Siguiente.
Paso 4: Configurar la Rotación (Opcional por ahora)
La rotación es una característica poderosa, pero la configuraremos más adelante en detalle. Por ahora, desactívala.
- Configurar rotación automática: Selecciona
Deshabilitar la rotación automática. - Haz clic en
Siguiente.
Paso 5: Revisar y Almacenar
Revisa todos los detalles y luego almacena el secreto.
- Verifica la configuración del secreto.
- Haz clic en
Almacenar.
¡Felicidades! Has almacenado tu primer secreto en AWS Secrets Manager. Ahora, veremos cómo recuperarlo desde una función AWS Lambda.
💻 Recuperando Secretos desde AWS Lambda
Una vez que el secreto está almacenado, el siguiente paso es que nuestra aplicación serverless (en este caso, una función AWS Lambda) pueda acceder a él de forma segura. Para esto, usaremos el SDK de AWS.
Paso 1: Crear una Función Lambda
Vamos a crear una función Lambda sencilla que intente recuperar el secreto.
- En la Consola de AWS, navega a Lambda.
- Haz clic en
Crear función. - Nombre de la función:
MySecretReaderFunction. - Runtime: Selecciona
Python 3.9(o la versión que prefieras). - Permisos: En
Cambiar el rol de ejecución predeterminado, seleccionaCrear un rol nuevo con permisos básicos de Lambda. - Haz clic en
Crear función.
Paso 2: Actualizar la Política de Permisos del Rol de Lambda
La función Lambda necesitará permisos para llamar a la API de Secrets Manager (secretsmanager:GetSecretValue).
- Una vez creada la función, ve a la pestaña
Configuracióny luego aPermisos. - Haz clic en el
Nombre del rol de ejecución(ej:MySecretReaderFunction-role-xxxxxx). Esto te llevará a la consola de IAM. - En la página del rol de IAM, haz clic en
Agregar permisos->Crear política insertada. - Selecciona la pestaña
JSONy pega la siguiente política:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:<YOUR_REGION>:<YOUR_ACCOUNT_ID>:secret:/my-serverless-app/db-credentials-*"
}
]
}
- ¡Importante! Reemplaza
<YOUR_REGION>y<YOUR_ACCOUNT_ID>con tu región y ID de cuenta reales. El*al final del ARN del secreto permite que la función acceda a diferentes versiones del secreto, lo cual es útil para la rotación. - Haz clic en
Revisar política. - Nombre: Dale un nombre a la política, por ejemplo,
SecretsManagerAccessPolicy. - Haz clic en
Crear política.
Paso 3: Escribir el Código de la Función Lambda
Ahora, actualizaremos el código de la función Lambda para recuperar el secreto.
- Vuelve a la consola de Lambda, en la pestaña
Códigode tu funciónMySecretReaderFunction. - Reemplaza el código existente con el siguiente código Python:
import json
import boto3
from botocore.exceptions import ClientError
def get_secret():
secret_name = "/my-serverless-app/db-credentials"
region_name = "<YOUR_REGION>" # Asegúrate de que esta sea tu región
# Crea un cliente de Secrets Manager
client = boto3.client(service_name='secretsmanager', region_name=region_name)
try:
get_secret_value_response = client.get_secret_value(SecretId=secret_name)
except ClientError as e:
# Maneja diferentes errores posibles
if e.response['Error']['Code'] == 'DecryptionFailureException':
# Secrets Manager no puede descifrar el secreto usando la clave KMS especificada.
raise e
elif e.response['Error']['Code'] == 'InternalServiceErrorException':
# Ocurrió un error en el servidor de Secrets Manager.
raise e
elif e.response['Error']['Code'] == 'InvalidParameterException':
# Parámetro de solicitud inválido.
raise e
elif e.response['Error']['Code'] == 'InvalidRequestException':
# La solicitud no es válida para el estado actual del secreto.
raise e
elif e.response['Error']['Code'] == 'ResourceNotFoundException':
# El secreto solicitado no fue encontrado.
raise e
else:
# Decodifica el secreto para poder usarlo
if 'SecretString' in get_secret_value_response:
secret = get_secret_value_response['SecretString']
return json.loads(secret)
else:
# Si el secreto es binario, tendrás que decodificarlo de base64
decoded_binary_secret = base64.b64decode(get_secret_value_response['SecretBinary'])
return decoded_binary_secret
def lambda_handler(event, context):
try:
db_credentials = get_secret()
username = db_credentials['username']
password = db_credentials['password']
print(f"Usuario de la base de datos: {username}")
print(f"Contraseña de la base de datos: {password}") # ¡En un entorno real, no imprimas esto!
# Aquí es donde usarías las credenciales para conectar a tu base de datos o servicio
# Ejemplo: db_connection = connect_to_db(username, password)
return {
'statusCode': 200,
'body': json.dumps('Credenciales recuperadas y usadas (ver logs).')
}
except Exception as e:
print(f"Error al recuperar o usar el secreto: {e}")
return {
'statusCode': 500,
'body': json.dumps(f'Error: {str(e)}')
}
- ¡Importante! Reemplaza
<YOUR_REGION>con tu región de AWS. - Haz clic en
Deploypara guardar los cambios.
Paso 4: Probar la Función Lambda
- En la consola de Lambda, haz clic en
Test. - Crea un nuevo evento de prueba con cualquier nombre (ej:
MyTestEvent) y usa la plantillahello-worldpredeterminada. - Haz clic en
Guardary luego enTest. - Verás los resultados de la ejecución. En la pestaña
Log output, deberías ver las credenciales impresas (recuerda: NO hagas esto en producción).
🔄 Configurando la Rotación Automática de Secretos
La rotación automática es una de las características más potentes de AWS Secrets Manager. Reduce significativamente la superficie de ataque al asegurar que las credenciales cambian regularmente.
¿Cómo funciona la rotación? 🤔
Secrets Manager utiliza una función Lambda para rotar los secretos. Cuando configuras la rotación, Secrets Manager crea y gestiona esta función Lambda de rotación, y establece un disparador de CloudWatch Events para invocarla periódicamente.
Paso 1: Habilitar la Rotación para un Secreto Existente
- Navega a la consola de Secrets Manager.
- Selecciona el secreto que creaste anteriormente (ej:
/my-serverless-app/db-credentials). - En la sección
Detalles del secreto, haz clic enEditar rotación. - Habilitar rotación automática: Marca la casilla
Habilitar rotación automática. - Frecuencia de rotación: Establece la frecuencia deseada (ej:
cada 30 días). - Función de rotación: Selecciona
Crear una nueva función de rotación Lambda. Esto creará una función Lambda preconfigurada para rotar las credenciales. - Rol de ejecución: Deja la opción para que Secrets Manager cree un nuevo rol de IAM para la función de rotación.
- Base de datos: Aquí es donde especificarás la instancia de base de datos a la que pertenecen las credenciales. Si seleccionaste
Credenciales para base de datos RDS...al crear el secreto, verás un desplegable con tus instancias RDS. Selecciona la instanciadb-instance-1(o la que corresponda a tu secreto). - Haz clic en
Guardar.
Secrets Manager ahora creará la función Lambda de rotación y configurará todo lo necesario. Este proceso puede tardar unos minutos.
Paso 2: Probar la Rotación (Opcional)
Puedes probar la rotación inmediatamente para verificar que funciona correctamente:
- En la página de detalles del secreto, haz clic en el botón
Rotar secreto ahora. - Esto invocará la función de rotación y cambiará las credenciales en la base de datos y en Secrets Manager.
- Puedes monitorear el progreso en los logs de la función Lambda de rotación (disponible en CloudWatch Logs).
🔐 Mejores Prácticas y Consideraciones Adicionales
Para maximizar la seguridad y la eficiencia al usar AWS Secrets Manager en tus arquitecturas serverless, considera estas mejores prácticas:
1. Principio de Mínimo Privilegio (Least Privilege) ✅
- Otorga solo los permisos necesarios a tus funciones Lambda para acceder a los secretos específicos que requieren. Evita
Resource: "*"siempre que sea posible. - Utiliza políticas de IAM detalladas para
secretsmanager:GetSecretValuecon el ARN exacto del secreto.
2. Caching de Secretos 💨
- Recuperar un secreto de Secrets Manager implica una llamada a la API, lo que añade latencia y puede generar costos adicionales en invocaciones frecuentes.
- Considera implementar un mecanismo de caching para los secretos dentro de tu función Lambda si los secretos no cambian con cada invocación.
- Ejemplo: Almacena el secreto recuperado en una variable global fuera del
lambda_handlerpara que se reutilice en invocaciones en caliente (warm invocations).
- Ejemplo: Almacena el secreto recuperado en una variable global fuera del
import json
import boto3
from botocore.exceptions import ClientError
# Variable global para cachear el secreto
CACHED_SECRET = None
def get_secret():
global CACHED_SECRET
if CACHED_SECRET:
return CACHED_SECRET
secret_name = "/my-serverless-app/db-credentials"
region_name = "<YOUR_REGION>"
client = boto3.client(service_name='secretsmanager', region_name=region_name)
try:
get_secret_value_response = client.get_secret_value(SecretId=secret_name)
if 'SecretString' in get_secret_value_response:
secret_dict = json.loads(get_secret_value_response['SecretString'])
CACHED_SECRET = secret_dict # Cachea el secreto
return secret_dict
else:
# Manejo para secretos binarios
pass # ...
except ClientError as e:
# Manejo de errores
raise e
def lambda_handler(event, context):
# ... (resto de la lógica usa get_secret() )
pass
3. Monitoreo y Auditoría 🕵️♂️
- Configura alarmas de Amazon CloudWatch para monitorear los eventos de Secrets Manager (ej: fallos de rotación, intentos de acceso no autorizados).
- Utiliza AWS CloudTrail para auditar todas las API calls realizadas a Secrets Manager. Esto te permite saber quién accedió a qué secreto y cuándo.
4. Gestión del Ciclo de Vida del Secreto 🗑️
- Cuando un secreto ya no es necesario, elimínalo de Secrets Manager. Secrets Manager ofrece un período de recuperación configurable (predeterminado de 30 días) antes de la eliminación permanente, lo que te da tiempo para restaurarlo si fue eliminado por error.
5. Uso de Tags 🏷️
- Aplica tags a tus secretos para organizarlos, gestionarlos y aplicar políticas basadas en tags (por ejemplo, para controlar quién puede rotar secretos de producción).
6. Integración con CI/CD 🚀
- Integra la creación y gestión de secretos en tus pipelines de CI/CD para automatizar el aprovisionamiento y asegurarte de que los secretos se manejan de forma coherente y segura en todos los entornos.
📊 Comparativa con AWS Systems Manager Parameter Store
Es común confundir AWS Secrets Manager con AWS Systems Manager Parameter Store. Ambos servicios almacenan información de configuración y credenciales, pero tienen propósitos ligeramente diferentes.
| Característica | AWS Secrets Manager | AWS Systems Manager Parameter Store |
|---|---|---|
| --- | --- | --- |
| Propósito Principal | Almacenamiento y rotación de secretos (credenciales) | Almacenamiento de datos de configuración y valores no sensibles |
| Rotación Automática | ✅ Sí (para DBs, servicios, personalizados) | ❌ No |
| --- | --- | --- |
| Costo | Basado en el número de secretos y API calls (más caro) | Niveles Estándar (gratuito), Avanzado (costo) |
| Cifrado | Siempre cifrado con KMS | Opcionalmente cifrado con KMS |
| --- | --- | --- |
| Auditoría | CloudTrail | CloudTrail |
| Tipo de Datos Típico | Contraseñas, claves API, tokens | URLs de bases de datos, nombres de usuario, flags de características, strings de conexión |
| --- | --- | --- |
| Uso Ideal | Credenciales de BD, tokens OAuth, claves API | Nombres de base de datos, puertos, niveles de log |
En resumen, si la información es sensible y necesita rotación periódica, AWS Secrets Manager es la elección correcta. Si es configuración general o datos menos sensibles que no requieren rotación, Parameter Store es una alternativa más económica y adecuada.
Conclusión ✨
La gestión segura de secretos es un pilar fundamental en cualquier arquitectura, y más aún en los entornos serverless donde la inmutabilidad y la efimeridad son la norma. AWS Secrets Manager proporciona una solución robusta y escalable para proteger tus credenciales, automatizar su rotación y auditar su acceso, permitiéndote construir aplicaciones serverless más seguras y resilientes.
Al integrar Secrets Manager en tus funciones Lambda, no solo cumples con las mejores prácticas de seguridad, sino que también reduces la complejidad operativa y te aseguras de que tus datos más sensibles estén protegidos en todo momento.
¡Esperamos que este tutorial te haya sido de gran utilidad para empezar a asegurar tus aplicaciones serverless con AWS Secrets Manager! Si tienes alguna pregunta, no dudes en explorar la documentación oficial de AWS.
Tutoriales relacionados
- Monitoreo y Observabilidad Serverless con Amazon CloudWatch: Una Guía Esencialintermediate15 min
- Optimización de Costos en Funciones Serverless con AWS Lambda: Estrategias Avanzadasadvanced18 min
- Orquestación de Flujos de Trabajo Serverless con AWS Step Functions: Guía Completaintermediate18 min
- Implementando Contenedores Serverless con AWS Fargate: Una Guía Detalladaintermediate25 min
- Desarrollo de Microservicios Serverless con AWS Lambda y la Arquitectura Hexagonalintermediate25 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!