Módulo 10 · Operación y automatización/Lección 65
Infraestructura como código a escala
StackSets para varias cuentas y regiones, Hooks y políticas como código para impedir lo indebido antes de desplegarlo.
⏱ 12 min
Al terminar podrás
- →Desplegar en muchas cuentas y regiones con StackSets
- →Validar antes de desplegar con CloudFormation Hooks y Guard
- →Corregir desvíos con políticas como código
Con una cuenta, un stack de CloudFormation basta. Con cuarenta cuentas en tres regiones, el problema cambia: necesitas el mismo rol de auditoría, el mismo trail y las mismas alarmas en las 120 combinaciones, y necesitas que nadie despliegue un bucket público o una base de datos sin cifrar, aunque tenga permisos para hacerlo.
Las bases de infraestructura como código siguen igual. Lo nuevo es cómo repartir plantillas a muchas cuentas y cómo poner controles antes, durante y después de cada despliegue.
StackSets: una plantilla, muchas cuentas y regiones
Un StackSet es un contenedor de stacks creados desde la misma plantilla en varias cuentas y regiones. Cada stack concreto (cuenta + región) es una instancia de stack. Cambias la plantilla una vez y el cambio llega a todas las instancias. Hay dos modelos de permisos:
| Criterio | ||
|---|---|---|
| Roles | Tú creas el rol de administración y un rol de ejecución en cada cuenta destino | StackSets crea los roles por ti |
| Destinos | Cualquier cuenta donde puedas crear esos roles, incluso fuera de tu organización | Cuentas y unidades organizativas (OU) de AWS Organizations |
| Cuentas nuevas | Las agregas tú | Despliegue automático al entrar a la OU; opcionalmente borra o conserva el stack si la cuenta sale |
| Quién lo administra | La cuenta donde creas el StackSet | La cuenta de administración o una cuenta de administrador delegado |
Los destinos de despliegue se definen por OU, por lista de cuentas o con un filtro que combina ambos (por ejemplo, «toda la OU Workloads menos esta cuenta»). Al crear o actualizar eliges cómo avanza la operación:
- Máximo de cuentas concurrentes: cuántas cuentas a la vez, en número o porcentaje.
- Tolerancia a fallos: cuántos stacks pueden fallar por región antes de detener la operación.
- Concurrencia de regiones: secuencial (por defecto, en el orden que indiques) o en paralelo.
- Modo de concurrencia: estricto, donde la concurrencia baja si aparecen fallos, o flexible, donde se mantiene mientras no se supere la tolerancia.
Validar antes de desplegar: Hooks y Guard
Un CloudFormation Hook es código que corre justo antes de que CloudFormation cree, actualice o borre algo. Si encuentra una configuración que incumple tus reglas, hace una de dos cosas según su modo: FAIL detiene la operación; WARN deja seguir con una advertencia. Lo normal es activarlo primero en WARN, ver qué rompería y luego pasarlo a FAIL. Puede evaluar cuatro objetivos:
La lógica del Hook se escribe de cuatro formas: activando controles proactivos de AWS Control Tower (ya escritos), con reglas de Guard, con una función Lambda o como Hook propio con la CloudFormation CLI.
AWS CloudFormation Guard es un lenguaje de políticas como código, abierto, para validar datos estructurados. Esta regla exige versionado y bloqueo de acceso público en cada bucket:
# reglas/s3.guard
let buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]
rule s3_versionado when %buckets !empty {
%buckets.Properties.VersioningConfiguration.Status == 'Enabled'
<<
Violación: el bucket debe tener versionado.
Arreglo: agrega VersioningConfiguration con Status: Enabled.
>>
}
rule s3_sin_acceso_publico when %buckets !empty {
%buckets.Properties.PublicAccessBlockConfiguration exists
%buckets.Properties.PublicAccessBlockConfiguration.BlockPublicAcls == true
%buckets.Properties.PublicAccessBlockConfiguration.RestrictPublicBuckets == true
}La misma regla corre en el pipeline, contra la plantilla, antes de que exista un stack:
cfn-guard validate --data plantilla.yaml --rules reglas/s3.guardSi usas CDK, los Aspects recorren todos los constructos del árbol antes de sintetizar y pueden agregar errores o advertencias. El proyecto abierto cdk-nag usa Aspects para aplicar paquetes de reglas de seguridad.
Detectar y corregir lo que ya existe
Lo preventivo no cubre todo: recursos creados antes de la regla, cambios manuales, servicios que no pasan por CloudFormation. Ahí entran los controles detectivos de AWS Config:
- Reglas de Config: evalúan la configuración real y marcan cada recurso como
COMPLIANToNON_COMPLIANT. Algunas reglas administradas también tienen modo proactivo, pero ese modo solo informa: no bloquea ni corrige. - Paquetes de conformidad (conformance packs): un conjunto de reglas y acciones de remediación que despliegas como una unidad, en una cuenta o en toda la organización.
- Remediación: cada regla puede asociarse a un documento de Systems Manager Automation que corrige el recurso, de forma manual o automática.
- Detección de drift: compara stacks e instancias de StackSets con la realidad y te dice qué se cambió a mano.
- 1
En el pull request
El pipeline correcfn-guardocdk-nag. El error aparece en minutos, antes de desplegar. - 2
Al desplegar
Un Hook en FAIL, activado en todas las cuentas, rechaza lo que se salte el pipeline pero pase por CloudFormation. - 3
Siempre
Las SCP de Organizations niegan acciones prohibidas, vengan de donde vengan. - 4
Después
Config detecta lo que no cumple y Systems Manager Automation lo corrige. El drift se lleva de vuelta a la plantilla.
Secretos en la plantilla
Una contraseña escrita en la plantilla queda en Git, en el historial del pipeline y en la consola de CloudFormation. Con referencias dinámicas, la plantilla solo nombra dónde vive el valor y CloudFormation lo busca al desplegar:
{{resolve:ssm:nombre}}para parámetros normales de Parameter Store.{{resolve:ssm-secure:nombre}}para parámetrosSecureString, solo en las propiedades de recursos que lo admiten.{{resolve:secretsmanager:secreto:SecretString:clave}}para secretos de Secrets Manager.
Resources:
Reportes:
Type: AWS::Lambda::Function
Properties:
# ...
Environment:
Variables:
# Parámetro normal de Parameter Store: se resuelve al desplegar
NIVEL_LOG: '{{resolve:ssm:/reportes/prod/nivel-log}}'
Bodega:
Type: AWS::RDS::DBInstance
Properties:
# ...
MasterUsername: '{{resolve:secretsmanager:prod/bodega:SecretString:usuario}}'
MasterUserPassword: '{{resolve:secretsmanager:prod/bodega:SecretString:clave}}'Mejor aún, deja que el servicio maneje el secreto. En RDS y Aurora, ManageMasterUserPassword: true crea la contraseña en Secrets Manager y la rota sin que la plantilla la mencione.
Quiz
Pon a prueba lo que aprendiste
0 de 5 correctas · 5 sin responder
1.Una empresa crea cuentas nuevas cada semana con AWS Organizations. Cada cuenta debe tener un rol de auditoría en cuanto entra a la OU Workloads, sin pasos manuales. ¿Qué haces?
2.Seguridad quiere que ningún stack de CloudFormation pueda crear un bucket S3 sin cifrado, y quiere ver primero cuántos equipos romperían la regla. ¿Qué propones?
3.Un StackSet actualiza 200 cuentas en 4 regiones. Quieres que la operación pare si fallan más de 2 stacks en una región. ¿Qué configuras?
4.Activaste controles proactivos de Control Tower. Un administrador crea desde la consola una tabla de DynamoDB que incumple uno de ellos. ¿Qué pasa?
5.Una plantilla necesita la contraseña de una base de datos guardada en Secrets Manager. ¿Cuál es la mejor forma de pasarla?