Claude Code con AWS CloudFormation y CDK: guía práctica para revisar IaC
Revisa AWS CDK y CloudFormation con Claude Code: IAM mínimo, diffs, drift, rollback y guardrails prácticos.
Hacer clic en la consola de AWS parece rápido hasta que alguien pregunta por qué producción no coincide con staging. CloudFormation y AWS CDK ayudan a dejar la infraestructura como código, pero IaC no elimina el riesgo: una política IAM demasiado amplia, un reemplazo de DynamoDB o un NAT Gateway olvidado pueden convertirse en un problema de seguridad o coste.
Uso Claude Code como compañero de redacción y revisión, no como operador autónomo de despliegue. Le pido que genere un primer borrador, explique cdk diff, detecte permisos ampliados y convierta eventos de CloudFormation en una lista de rollback. La aprobación final sigue siendo humana.
Para principiantes: CloudFormation es el servicio nativo de AWS que aplica plantillas; CDK permite escribir infraestructura en TypeScript y sintetizarla a CloudFormation; un stack es la unidad de despliegue; drift significa que el recurso real ya no coincide con el código.
Este artículo se basa en documentación oficial de AWS consultada el 3 de junio de 2026:
- AWS CDK Developer Guide
- AWS CDK CLI deploy command
- AWS CDK CLI diff command
- CloudFormation change sets
- CloudFormation drift detection
- CloudFormation stack failure options
- IAM security best practices
- AWS CDK security best practices
Define el límite de Claude Code
| Trabajo | Claude Code ayuda con | El humano aprueba |
|---|---|---|
| Requisitos | Recursos, entornos y dependencias | Si el recurso hace falta |
| Borrador | Plantillas CloudFormation/CDK | Nombres, eliminación, coste |
| IAM | Acciones y recursos candidatos | Mínimo privilegio real |
| Diff | Resumen de cdk diff o change set | Eliminaciones y reemplazos |
| Incidentes | Lectura de eventos y posibles arreglos | Plan de rollback |
flowchart LR
A["Escribir requisitos"] --> B["Borrador IaC con Claude Code"]
B --> C["Revisión humana de coste y nombres"]
C --> D["cdk diff o change set"]
D --> E["Claude Code revisa riesgos"]
E --> F["Aprobar y desplegar"]
F --> G["Registrar drift y rollback"]
Caso 1: Pasar una parte pequeña a CloudFormation
Empieza con una porción de bajo riesgo. Esta plantilla crea un bucket S3 privado y un rol IAM asumible por Lambda que solo puede leer ese bucket. Como crea un rol con nombre, requiere CAPABILITY_NAMED_IAM.
mkdir cfn-iac-review-demo
cd cfn-iac-review-demo
# Guarda el siguiente YAML como cfn-safe-iac-demo.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "ClaudeCodeLab safe IaC review demo: private S3 bucket and least-privilege Lambda role"
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
ProjectName:
Type: String
Default: cclab-iac-demo
AllowedPattern: "^[a-z0-9][a-z0-9-]{2,24}$"
Resources:
DemoBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
BucketName: !Sub "${ProjectName}-${Environment}-${AWS::AccountId}-${AWS::Region}"
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Tags:
- Key: Project
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
DemoReaderRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${ProjectName}-${Environment}-reader-${AWS::Region}"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: ReadOnlyDemoBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: ListOnlyThisBucket
Effect: Allow
Action:
- s3:ListBucket
Resource: !GetAtt DemoBucket.Arn
- Sid: ReadObjectsOnly
Effect: Allow
Action:
- s3:GetObject
Resource: !Sub "${DemoBucket.Arn}/*"
Outputs:
BucketName:
Value: !Ref DemoBucket
ReaderRoleArn:
Value: !GetAtt DemoReaderRole.Arn
Pide una revisión estricta:
claude -p "
Revisa cfn-safe-iac-demo.yaml como plantilla CloudFormation.
Devuelve una tabla con:
1. acceso público accidental
2. alcance de IAM Resource
3. riesgo de borrado o reemplazo
4. posible coste mensual
5. qué mirar en un change set de producción
"
Crea y revisa el change set antes de ejecutar:
aws cloudformation create-change-set \
--stack-name cclab-iac-demo-dev \
--change-set-name review-20260603-001 \
--template-body file://cfn-safe-iac-demo.yaml \
--capabilities CAPABILITY_NAMED_IAM \
--parameters ParameterKey=Environment,ParameterValue=dev ParameterKey=ProjectName,ParameterValue=cclab-iac-demo
aws cloudformation describe-change-set \
--stack-name cclab-iac-demo-dev \
--change-set-name review-20260603-001
Busca Add, Modify, Remove y Replacement. Replacement en S3, RDS, DynamoDB, KMS o redes debe frenar la aprobación hasta entender el impacto.
Caso 2: Stack mínimo con CDK TypeScript
En proyectos nuevos, CDK TypeScript suele ser más mantenible. Este ejemplo crea DynamoDB, S3 y Lambda sin API Gateway para mantener bajo el coste de prueba.
mkdir cdk-iac-review-demo
cd cdk-iac-review-demo
npm init -y
npm install aws-cdk-lib constructs
npm install --save-dev aws-cdk typescript ts-node @types/node
mkdir bin lib
{
"app": "npx ts-node --prefer-ts-exts bin/app.ts"
}
// bin/app.ts
import * as cdk from "aws-cdk-lib";
import { IacReviewDemoStack } from "../lib/iac-review-demo-stack";
const app = new cdk.App();
new IacReviewDemoStack(app, "IacReviewDemoStack", {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION ?? "us-east-1",
},
});
// lib/iac-review-demo-stack.ts
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as iam from "aws-cdk-lib/aws-iam";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as logs from "aws-cdk-lib/aws-logs";
import * as s3 from "aws-cdk-lib/aws-s3";
export class IacReviewDemoStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const stage = this.node.tryGetContext("stage") ?? "dev";
const isProd = stage === "prod";
const table = new dynamodb.Table(this, "AppTable", {
partitionKey: { name: "pk", type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
pointInTimeRecovery: isProd,
deletionProtection: isProd,
removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
});
const bucket = new s3.Bucket(this, "PrivateAssetsBucket", {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
enforceSSL: true,
encryption: s3.BucketEncryption.S3_MANAGED,
versioned: true,
removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: !isProd,
});
const fn = new lambda.Function(this, "ApiHandler", {
runtime: lambda.Runtime.NODEJS_20_X,
handler: "index.handler",
code: lambda.Code.fromInline(`
exports.handler = async () => ({
statusCode: 200,
body: JSON.stringify({
tableName: process.env.TABLE_NAME,
bucketName: process.env.BUCKET_NAME
})
});
`),
environment: {
TABLE_NAME: table.tableName,
BUCKET_NAME: bucket.bucketName,
STAGE: stage,
},
timeout: cdk.Duration.seconds(10),
memorySize: 256,
logRetention: logs.RetentionDays.ONE_WEEK,
});
table.grantReadWriteData(fn);
bucket.grantPut(fn);
fn.addToRolePolicy(
new iam.PolicyStatement({
sid: "DenyInsecureS3Transport",
effect: iam.Effect.DENY,
actions: ["s3:*"],
resources: [bucket.bucketArn, bucket.arnForObjects("*")],
conditions: { Bool: { "aws:SecureTransport": "false" } },
}),
);
cdk.Tags.of(this).add("Project", "ClaudeCodeLab");
cdk.Tags.of(this).add("Stage", stage);
new cdk.CfnOutput(this, "FunctionName", { value: fn.functionName });
new cdk.CfnOutput(this, "BucketName", { value: bucket.bucketName });
new cdk.CfnOutput(this, "TableName", { value: table.tableName });
}
}
Antes de desplegar:
npx cdk synth -c stage=dev
npx cdk diff -c stage=dev
claude -p "
Revisa este cdk diff.
Solo marca borrados, reemplazos, ampliación IAM, exposición S3, coste DynamoDB y fuga de variables Lambda.
$(npx cdk diff -c stage=dev 2>&1)
"
autoDeleteObjects: !isProd es cómodo en desarrollo, pero peligroso en producción. Ese tipo de guardrail por entorno debe aparecer en la revisión.
Caso 3: Explicar diffs de producción
claude -p "
Resume este cdk diff para una persona de producto que no es especialista AWS.
Usa columnas:
- tipo de cambio
- recurso
- impacto usuario
- impacto seguridad
- impacto coste
- pregunta antes de aprobar
$(npx cdk diff -c stage=prod 2>&1)
"
Los puntos de mayor riesgo son IAM Action/Resource, security groups abiertos a 0.0.0.0/0, falta de deletion protection, S3 público, alta de CloudFront o NAT Gateway y reemplazos de recursos con estado.
Caso 4: Rollback y drift
aws cloudformation describe-stacks --stack-name cclab-iac-demo-dev
aws cloudformation detect-stack-drift --stack-name cclab-iac-demo-dev
aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id YOUR_DETECTION_ID
claude -p "
Este stack está en UPDATE_ROLLBACK_FAILED.
Lee los eventos y separa causas probables, recursos que se pueden tocar, recursos que no se deben tocar y pasos a verificar en la documentación AWS.
$(aws cloudformation describe-stack-events --stack-name cclab-iac-demo-dev 2>&1)
"
Errores frecuentes
IAM demasiado amplio. No aceptes Action: "*" ni Resource: "*" porque “funciona”. Acota acciones, ARN y condiciones.
Desplegar sin leer el diff. Producción necesita synth, diff y change set. Si aparece Replacement, se revisa antes de aprobar.
No mirar costes fijos. ALB, NAT Gateway, RDS, OpenSearch y ECS siempre encendido cuestan incluso con poco tráfico.
Dejar cambios manuales como solución permanente. La consola sirve para emergencias, pero el arreglo final debe volver a CloudFormation o CDK.
Escribir secretos en código. Usa Secrets Manager o SSM Parameter Store y pide a Claude Code que no imprima valores secretos.
Prompt de revisión
Eres un revisor estricto de AWS CloudFormation/CDK.
Revisa este diff de IaC antes de producción.
Comprueba:
- IAM Action/Resource/Condition con mínimo privilegio
- exposición accidental por security groups o S3
- borrado o reemplazo de recursos con estado
- coste fijo nuevo como ALB, NAT Gateway, RDS u OpenSearch
- posible CloudFormation drift
- recursos que requieren pasos manuales de rollback
Salida:
1. problemas que corregir ahora
2. preguntas para aprobar
3. comandos antes de deploy
4. comandos después de deploy
Más recursos
Para IAM, lee Claude Code y AWS IAM. Para la capa de ejecución y datos, combina este artículo con AWS Lambda, AWS API Gateway y AWS DynamoDB.
ClaudeCodeLab ofrece productos prácticos y training para equipos para convertir estos prompts en plantillas de Pull Request y checklists de release.
Resumen
Claude Code funciona mejor con CloudFormation/CDK como segundo revisor estricto. Deja que redacte, pero exige que explique IAM, coste, reemplazos, rollback y drift antes de desplegar. El resultado práctico es claro: revisar cdk diff y change sets con Claude Code descubre más riesgos que usarlo solo para generar plantillas.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Workflow de Obsidian a CLAUDE.md con Claude Code
Convierte notas de trabajo de Obsidian en notas operativas de CLAUDE.md para no repetir contexto.
Claude Code Revenue CTA Routing: de artículos a PDF, Gumroad y consulta
Un flujo con Claude Code para dirigir lectores a PDF gratis, Gumroad o consulta según intención.
Reglas de handoff para equipos con Claude Code: evidencia, permisos, rollback e ingresos
Formato práctico para entregar trabajo de Claude Code con pruebas, permisos, rollback, PDF gratis, Gumroad y consulta.