Claude Code dengan AWS CloudFormation dan CDK: panduan review IaC praktis
Review AWS CDK dan CloudFormation dengan Claude Code: IAM minimum, diff, drift, rollback, dan guardrail.
Klik-klik di AWS Console memang terasa cepat sampai seseorang bertanya mengapa production berbeda dari staging. CloudFormation dan AWS CDK membantu menaruh infrastruktur ke dalam kode, tetapi IaC tidak otomatis aman. Policy IAM yang terlalu luas, penggantian resource stateful, atau NAT Gateway yang lupa dimatikan bisa menjadi masalah keamanan dan biaya.
Saya memakai Claude Code sebagai partner untuk menulis draft dan melakukan review, bukan sebagai operator deploy otomatis. Claude Code cocok untuk membuat draft CloudFormation/CDK, menjelaskan cdk diff, menandai perluasan permission, dan mengubah event CloudFormation menjadi checklist rollback. Persetujuan akhir tetap harus manusia.
Untuk pemula: CloudFormation adalah layanan AWS yang menjalankan template. CDK memungkinkan kita menulis infrastruktur dengan TypeScript lalu mensintesisnya menjadi CloudFormation. Stack adalah unit deployment. Drift berarti resource AWS yang nyata tidak lagi cocok dengan kode.
Artikel ini mengikuti dokumentasi resmi AWS yang dicek pada 3 Juni 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
Tetapkan batas peran
| Pekerjaan | Claude Code membantu | Manusia menyetujui |
|---|---|---|
| Requirement | Resource, environment, dependency | Apakah resource dibutuhkan |
| Draft | CloudFormation/CDK | Nama, removal policy, biaya |
| IAM | Kandidat Action/Resource/Condition | Least privilege |
| Diff | Ringkasan cdk diff atau change set | Delete, replacement, permission |
| Insiden | Analisis event dan opsi perbaikan | Rencana rollback |
flowchart LR
A["Tulis requirement"] --> B["Draft IaC dengan Claude Code"]
B --> C["Review biaya dan nama"]
C --> D["cdk diff atau change set"]
D --> E["Claude Code review risiko"]
E --> F["Approve dan deploy"]
F --> G["Catat drift dan rollback"]
Use case 1: Pindahkan bagian kecil ke CloudFormation
Jangan mulai dari seluruh production account. Pilih bagian kecil yang risikonya rendah. Template ini membuat private S3 bucket dan IAM role untuk Lambda yang hanya bisa membaca bucket tersebut. Karena membuat named IAM role, perintah deploy membutuhkan CAPABILITY_NAMED_IAM.
mkdir cfn-iac-review-demo
cd cfn-iac-review-demo
# Simpan YAML berikut sebagai 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
Minta review ketat sebelum membuat resource:
claude -p "
Review cfn-safe-iac-demo.yaml sebagai template CloudFormation.
Kembalikan tabel untuk:
1. accidental public access
2. scope IAM Resource
3. risiko delete atau replacement
4. kemungkinan biaya bulanan
5. hal yang harus dicek di production change set
"
Buat dan baca change set:
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
Perhatikan Add, Modify, Remove, dan Replacement. Replacement pada S3, RDS, DynamoDB, KMS, atau network resource harus menghentikan approval sampai dampaknya jelas.
Use case 2: Stack CDK TypeScript minimal
Untuk proyek baru, CDK TypeScript mudah dibaca dan direview. Contoh ini membuat DynamoDB, S3, dan Lambda tanpa API Gateway agar cakupan dan biaya demo tetap kecil.
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 ?? "ap-southeast-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 });
}
}
Review sebelum deploy:
npx cdk synth -c stage=dev
npx cdk diff -c stage=dev
claude -p "
Review cdk diff ini.
Hanya tandai delete, replacement, IAM privilege expansion, S3 exposure, biaya DynamoDB, dan kebocoran environment variable Lambda.
$(npx cdk diff -c stage=dev 2>&1)
"
autoDeleteObjects: !isProd nyaman untuk development, tetapi berbahaya jika masuk production. Guardrail per environment seperti ini wajib terlihat di review.
Use case 3: Jelaskan production diff
claude -p "
Ringkas cdk diff ini untuk product owner yang bukan spesialis AWS.
Gunakan kolom:
- tipe perubahan
- target resource
- dampak user
- dampak security
- dampak cost
- pertanyaan sebelum approval
$(npx cdk diff -c stage=prod 2>&1)
"
Risiko utama biasanya IAM Action/Resource, security group terbuka ke 0.0.0.0/0, deletion protection hilang, S3 public access, tambahan CloudFront/NAT Gateway, dan replacement resource stateful.
Use case 4: Rollback dan 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 "
Stack ini berada di UPDATE_ROLLBACK_FAILED.
Baca events dan pisahkan kemungkinan penyebab, resource yang aman disentuh, resource yang tidak boleh disentuh, dan langkah yang harus diverifikasi di dokumentasi AWS.
$(aws cloudformation describe-stack-events --stack-name cclab-iac-demo-dev 2>&1)
"
Kesalahan umum
IAM terlalu luas. Jangan menerima Action: "*" atau Resource: "*" hanya karena berhasil berjalan. Batasi action, ARN, dan condition sesuai use case.
Deploy tanpa membaca diff. Production perlu synth, diff, dan change set. Jika ada Replacement, berhenti dulu.
Melupakan biaya tetap. ALB, NAT Gateway, RDS, OpenSearch, dan ECS yang selalu hidup tetap menimbulkan biaya walau traffic rendah.
Perubahan console menjadi solusi permanen. Perbaikan manual saat insiden bisa perlu, tetapi perubahan final harus kembali ke CloudFormation atau CDK.
Secret ditulis di kode. Gunakan Secrets Manager atau SSM Parameter Store, dan minta Claude Code tidak mencetak nilai rahasia.
Prompt review
You are a strict AWS CloudFormation/CDK reviewer.
Review this IaC diff before production.
Check:
- least-privilege IAM Action/Resource/Condition
- accidental exposure through security groups or S3
- delete or replacement of stateful resources
- new fixed monthly cost such as ALB, NAT Gateway, RDS, or OpenSearch
- likely CloudFormation drift
- resources requiring manual rollback
Output:
1. issues to fix now
2. questions for approver
3. commands before deploy
4. commands after deploy
Bacaan lanjut
Untuk IAM, baca Claude Code dan AWS IAM. Untuk compute dan data layer, gabungkan dengan AWS Lambda, AWS API Gateway, dan AWS DynamoDB.
ClaudeCodeLab menyediakan produk praktis dan training tim untuk mengubah prompt ini menjadi template Pull Request dan checklist release.
Ringkasan
Claude Code paling berguna dengan CloudFormation/CDK saat menjadi reviewer kedua yang ketat. Biarkan ia membuat draft, tetapi wajib minta penjelasan IAM, biaya, replacement, rollback, dan drift sebelum deploy. Secara praktis, review cdk diff dan change set dengan Claude Code lebih cepat menemukan risiko production daripada sekadar menghasilkan template.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Workflow Obsidian ke CLAUDE.md untuk Claude Code
Ubah catatan kerja Obsidian menjadi operating note CLAUDE.md agar konteks tidak dijelaskan ulang.
Claude Code Revenue CTA Routing: dari artikel ke PDF, Gumroad, dan konsultasi
Workflow Claude Code untuk mengarahkan pembaca ke PDF gratis, Gumroad, atau konsultasi sesuai intent.
Aturan handoff tim Claude Code: bukti review, permission, rollback, dan jalur revenue
Format handoff Claude Code untuk tim: bukti, permission rule, rollback, PDF gratis, Gumroad, dan konsultasi.