From chogos
AWS infrastructure best practices. Use when creating, modifying, or reviewing CloudFormation templates, CDK stacks, IAM policies, Lambda functions, ECS task definitions, VPC configurations, or any AWS resource definitions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/chogos:writing-aws-infrastructureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Never use `*` in Action or Resource. Every policy must scope to the minimum actions and resources required.
Never use * in Action or Resource. Every policy must scope to the minimum actions and resources required.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadInvoiceBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::acme-invoices",
"arn:aws:s3:::acme-invoices/*"
],
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-abc123"
}
}
}
]
}
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:lambda:eu-west-1:111111111111:function:my-func"
}
}
}
AmazonDynamoDBReadOnlyAccess), then tighten with inline.Sid — readable identifier per statement.Deny statements override any Allow.Block public access at the account level. Repeat at the bucket level for defense-in-depth.
AWSTemplateFormatVersion: "2010-09-09"
Resources:
InvoiceBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub "${AWS::AccountId}-invoices"
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
KMSMasterKeyID: !Ref BucketKey
VersioningConfiguration:
Status: Enabled
LifecycleConfiguration:
Rules:
- Id: TransitionToIA
Status: Enabled
Transitions:
- StorageClass: STANDARD_IA
TransitionInDays: 30
- StorageClass: GLACIER
TransitionInDays: 90
LoggingConfiguration:
DestinationBucketName: !Ref AccessLogsBucket
LogFilePrefix: invoices/
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
InvoiceBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref InvoiceBucket
PolicyDocument:
Statement:
- Sid: DenyInsecureTransport
Effect: Deny
Principal: "*"
Action: "s3:*"
Resource:
- !GetAtt InvoiceBucket.Arn
- !Sub "${InvoiceBucket.Arn}/*"
Condition:
Bool:
"aws:SecureTransport": "false"
AES256) for default encryption, SSE-KMS when you need key rotation control or cross-account access.Pin the runtime version. Use provided.al2023 for custom runtimes.
// CDK — Lambda with best practices
import { Duration, RemovalPolicy } from "aws-cdk-lib";
import { Runtime, Architecture, Tracing } from "aws-cdk-lib/aws-lambda";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import { RetentionDays } from "aws-cdk-lib/aws-logs";
import { Secret } from "aws-cdk-lib/aws-secretsmanager";
const apiSecret = Secret.fromSecretNameV2(this, "ApiSecret", "prod/api-key");
const processOrder = new NodejsFunction(this, "ProcessOrder", {
entry: "src/handlers/process-order.ts",
handler: "handler",
runtime: Runtime.NODEJS_22_X,
architecture: Architecture.ARM_64,
memorySize: 512,
timeout: Duration.seconds(30),
tracing: Tracing.ACTIVE,
reservedConcurrentExecutions: 100,
environment: {
TABLE_NAME: ordersTable.tableName,
REGION: this.region,
},
logRetention: RetentionDays.TWO_WEEKS,
bundling: {
minify: true,
sourceMap: true,
},
});
apiSecret.grantRead(processOrder);
ordersTable.grantReadWriteData(processOrder);
{
"family": "api-service",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::111111111111:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::111111111111:role/api-service-task-role",
"containerDefinitions": [
{
"name": "api",
"image": "111111111111.dkr.ecr.eu-west-1.amazonaws.com/api:1.2.3",
"portMappings": [{ "containerPort": 8080, "protocol": "tcp" }],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/api-service",
"awslogs-region": "eu-west-1",
"awslogs-stream-prefix": "api"
}
},
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:eu-west-1:111111111111:secret:prod/db-password"
}
],
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
]
}
latest.awsvpc network mode on Fargate.executionRoleArn (ECR pull, log writes) from taskRoleArn (app-level AWS access).secrets block — they resolve at task start, not baked into the image.deploymentCircuitBreaker: { enable: true, rollback: true }.maximumPercent: 200, minimumHealthyPercent: 100 for zero-downtime rolling deploys.LATEST or specific version (1.4.0)./16 VPC, /20 subnets. Leave room for expansion.EcsSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ECS tasks
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
SourceSecurityGroupId: !Ref AlbSecurityGroup
0.0.0.0/0 ingress except ALB ports 80/443.ecr.api, ecr.dkr), Secrets Manager, CloudWatch Logs, STS.Parameters for environment-specific values. Default nothing that varies per environment.DeletionPolicy: Retain on stateful resources (S3, RDS, DynamoDB).Fn::Sub over Fn::Join for readability:
Value: !Sub "arn:aws:s3:::${BucketName}/*"
api-gateway.ts → ApiGateway.Props interface extending StackProps for every stack:
interface ApiStackProps extends StackProps {
vpcId: string;
certificateArn: string;
}
RemovalPolicy.RETAIN on stateful resources. RemovalPolicy.DESTROY only in dev stacks.App level:
Tags.of(app).add("Project", "acme");
Tags.of(app).add("Environment", props.environment);
cdk-nag in CI. Add suppressions with justification, never disable globally.Test infrastructure the same way you test application code. CDK provides assertion utilities via aws-cdk-lib/assertions.
import { Template, Match } from "aws-cdk-lib/assertions";
import { App } from "aws-cdk-lib";
import { ApiStack } from "../lib/api-stack";
const app = new App();
const stack = new ApiStack(app, "Test");
const template = Template.fromStack(stack);
// Fine-grained: verify specific resource properties
template.hasResourceProperties("AWS::Lambda::Function", {
Runtime: "nodejs22.x",
Timeout: 30,
MemorySize: 512,
});
// Count resources of a type
template.resourceCountIs("AWS::SQS::Queue", 2);
// Verify no public S3 buckets
template.hasResourceProperties("AWS::S3::Bucket", {
PublicAccessBlockConfiguration: {
BlockPublicAcls: true,
BlockPublicPolicy: true,
},
});
hasResourceProperties, resourceCountIs) over snapshot tests — snapshots break on CDK version bumps and unrelated changes.template.toJSON() with your test framework's snapshot matcher.| Feature | HTTP API (v2) | REST API (v1) |
|---|---|---|
| Cost | ~$1/million requests | ~$3.50/million requests |
| Latency | Lower (~10ms added) | Higher (~30ms added) |
| Auth | JWT, Lambda, IAM | JWT (via Lambda), Lambda, IAM, Cognito, API keys |
| Request validation | No | Yes (JSON Schema) |
| WAF integration | No | Yes |
| Usage plans / throttling | Route-level only | Per-client API keys with quotas |
| Caching | No | Yes (0.5–237 GB) |
| WebSocket | No | Separate WebSocket API |
Default to HTTP API. Use REST API when you need request validation, WAF, caching, or per-client usage plans.
// JWT authorizer (HTTP API) — validates tokens without a Lambda invocation
import { HttpJwtAuthorizer } from "aws-cdk-lib/aws-apigatewayv2-authorizers";
const jwtAuth = new HttpJwtAuthorizer("JwtAuth", "https://cognito-idp.eu-west-1.amazonaws.com/eu-west-1_xxx", {
jwtAudience: ["api-client-id"],
});
httpApi.addRoutes({
path: "/orders",
methods: [HttpMethod.GET],
integration: new HttpLambdaIntegration("GetOrders", getOrders),
authorizer: jwtAuth,
});
import { DomainName } from "aws-cdk-lib/aws-apigatewayv2";
const domain = new DomainName(this, "ApiDomain", {
domainName: "api.example.com",
certificate: cert, // ACM certificate in us-east-1 for edge, same region for regional
});
Create a Route 53 alias record pointing to the API Gateway domain. Use stage mapping for versioning (api.example.com/v1).
Lambda integrates natively with SQS, SNS, EventBridge, Kinesis, and DynamoDB Streams. For event-driven patterns — fan-out, choreography, CQRS, event sourcing — see patterns/serverless-patterns.md.
Project, Environment, Owner. Use tag policies in AWS Organizations.arm64) for ~20% cost reduction. Minimize cold starts to reduce wasted execution time.aws:SecureTransport condition in bucket policy.ELBSecurityPolicy-TLS13-1-2-2021-06 or newer.- [ ] Define resource requirements and naming convention
- [ ] Choose region(s) and multi-AZ strategy
- [ ] Design VPC layout (CIDR, subnets, connectivity)
- [ ] Write IAM roles with least privilege
- [ ] Define encryption strategy (KMS keys, TLS)
- [ ] Write CloudFormation/CDK with DeletionPolicy on stateful resources
- [ ] Add monitoring: CloudWatch alarms, dashboards, log groups
- [ ] Add tagging: Project, Environment, Owner on all resources
- [ ] Run validation loop (below)
- [ ] Peer review the template
- [ ] Deploy to staging, verify, then production
cfn-lint template.yaml or cdk synth — catch syntax errors, invalid property values, missing required fields.npx jest or npx vitest — run fine-grained assertions and cdk-nag checks.cfn_nag_scan --input-path template.yaml or cdk-nag — flag overly permissive policies, missing encryption, public access.checkov -f template.yaml — broader compliance checks (CIS, SOC2, HIPAA benchmarks).aws accessanalyzer validate-policy --policy-document file://policy.json — detect unused permissions, overly broad resources, missing conditions.npx claudepluginhub chogos/claude-skills --plugin chogosEnforces CDK/CloudFormation best practices for immutable infrastructure, environment parity, least privilege, tagging, and cost optimization. Use when provisioning or modifying AWS infrastructure.
Provides deep AWS expertise for IAM policies, VPC networking, EKS/ECS/Lambda compute, RDS/DynamoDB/S3 storage, security hardening, monitoring, and multi-account production strategies.
Builds well-architected AWS infrastructure with CDK and CloudFormation using docs, samples, cfn-lint validation, cfn-guard compliance, best practices, and troubleshooting. Use for CDK, CloudFormation, cfn-lint, cfn-guard, AWS IaC.