Claude Code for CDK Aspects Workflow Tutorial
AWS CDK Aspects are one of the most powerful yet underutilized features in the CDK ecosystem. They enable you to apply cross-cutting concerns across your entire infrastructure stack during synthesis, making them ideal for enforcement, validation, and governance. Combined with Claude Code’s AI-assisted development capabilities, you can build robust CDK projects with automated compliance checks and consistent infrastructure patterns.
This tutorial walks you through practical workflows for creating, testing, and maintaining CDK Aspects using Claude Code.
Understanding CDK Aspects
Before diving into the workflow, it’s essential to understand what Aspects do and why they matter for your CDK projects.
How Aspects Work
Aspects operate at synthesis time, traversing the CDK construct tree and applying modifications or validations to constructs. Unlike CloudFormation guards or policies that run after deployment, Aspects intervene during the synthesis phase, allowing you to catch issues before they reach AWS.
The core interface consists of visit() method that receives each construct in the tree:
import { IAspect, IConstruct } from 'constructs';
export class MyAspect implements IAspect {
visit(node: IConstruct): void {
// Apply logic to each construct
console.log(`Visiting: ${node.node.id}`);
}
}
When you apply an aspect to a stack, CDK automatically traverses all children and invokes your visitor on each:
import { App, Stack, Aspects } from 'aws-cdk-lib';
const app = new App();
const myStack = new Stack(app, 'MyStack');
// Apply aspect to entire stack
Aspects.of(myStack).add(new MyAspect());
Common Use Cases
CDK Aspects excel at several scenarios:
- Tag enforcement: Apply mandatory tags to all resources
- Compliance validation: Check for required security configurations
- Cost governance: Enforce budget tags or prevent expensive resource configurations
- Naming conventions: Validate resource naming patterns
- Logging setup: Automatically enable CloudWatch logging
Setting Up Claude Code for CDK Projects
Start by ensuring Claude Code understands your CDK project structure and organizational standards.
Creating Project Context
When you begin a CDK project session with Claude Code, provide a CLAUDE.md file with your infrastructure standards:
# CDK Project Context
## Naming Conventions
- All stack names: {Project}-{Environment}-{Component}
- Resource names: PascalCase with descriptive purpose
- Tags: Environment, CostCenter, Owner required on all resources
## Compliance Requirements
- All S3 buckets must have versioning enabled
- All EC2 instances require specific IAM role
- VPCs must flow logs enabled
- RDS must have deletion protection in prod
## Common Patterns
- Use standardized VPC construct from ./lib/common/
- All buckets use server-side encryption
- ALB redirect HTTP to HTTPS always
This context helps Claude Code generate Aspects that align with your existing infrastructure.
Building Your First CDK Aspect
Let’s create a practical aspect that enforces tagging requirements across your stack.
Tag Enforcement Aspect
Create a new file for your aspect:
// lib/aspects/tag-enforcement.ts
import { IAspect, IConstruct, TagManager, TagType } from 'constructs';
import { CfnResource } from 'aws-cdk-lib';
export interface TagRule {
key: string;
allowedValues?: string[];
required?: boolean;
}
export class TagEnforcement implements IAspect {
private rules: TagRule[];
constructor(rules: TagRule[]) {
this.rules = rules;
}
visit(node: IConstruct): void {
// Only apply to CloudFormation resources
if (!(node instanceof CfnResource)) {
return;
}
const tags = node.cfnProperties.Tags || [];
const tagMap = new Map(tags.map((t: any) => [t.Key, t.Value]));
// Check required tags
for (const rule of this.rules) {
if (rule.required && !tagMap.has(rule.key)) {
console.error(
`Missing required tag '${rule.key}' on ${node.node.path}`
);
}
// Check allowed values
if (rule.allowedValues && tagMap.has(rule.key)) {
const value = tagMap.get(rule.key)!;
if (!rule.allowedValues.includes(value)) {
console.error(
`Invalid tag value '${value}' for '${rule.key}' on ${node.node.path}. ` +
`Allowed values: ${rule.allowedValues.join(', ')}`
);
}
}
}
}
}
Applying the Aspect
Use the aspect in your stack:
import { Stack, App, Aspects } from 'aws-cdk-lib';
import { TagEnforcement, TagRule } from './aspects/tag-enforcement';
const app = new App();
const stack = new Stack(app, 'ProductionStack', {
env: { region: 'us-east-1', account: '123456789012' }
});
// Define your tagging rules
const requiredTags: TagRule[] = [
{ key: 'Environment', required: true, allowedValues: ['dev', 'staging', 'prod'] },
{ key: 'CostCenter', required: true },
{ key: 'Owner', required: true },
{ key: 'ComplianceLevel', allowedValues: ['low', 'medium', 'high', 'critical'] }
];
// Apply the aspect
Aspects.of(stack).add(new TagEnforcement(requiredTags));
When you run cdk synth, the aspect validates tags and reports violations.
Advanced Aspect: Security Compliance Checker
Build a more sophisticated aspect that checks for security configurations.
S3 Bucket Security Aspect
// lib/aspects/security-checker.ts
import { IAspect, IConstruct } from 'constructs';
import { CfnResource, CfnBucket } from 'aws-cdk-lib';
interface SecurityViolation {
resource: string;
issue: string;
severity: 'high' | 'medium' | 'low';
}
export class SecurityChecker implements IAspect {
private violations: SecurityViolation[] = [];
visit(node: IConstruct): void {
if (node instanceof CfnBucket) {
this.checkS3Bucket(node);
}
}
private checkS3Bucket(bucket: CfnBucket): void {
// Check versioning
if (!bucket.versioningStatus) {
this.violations.push({
resource: bucket.node.path,
issue: 'S3 bucket versioning not enabled',
severity: 'high'
});
}
// Check encryption
if (!bucket.bucketEncryption) {
this.violations.push({
resource: bucket.node.path,
issue: 'S3 bucket encryption not configured',
severity: 'high'
});
}
// Check public access block
const publicAccessBlock = bucket.publicAccessBlockConfiguration;
if (!publicAccessBlock ||
!publicAccessBlock.blockPublicAcls ||
!publicAccessBlock.blockPublicPolicy) {
this.violations.push({
resource: bucket.node.path,
issue: 'S3 bucket public access not fully blocked',
severity: 'high'
});
}
}
report(): SecurityViolation[] {
return this.violations;
}
}
Using with Claude Code
When working with Claude Code, you can describe your security requirements in natural language and have it generate the appropriate aspect:
Prompt to Claude Code:
Create a CDK aspect that validates:
1. All EC2 instances have IAM roles attached
2. All RDS instances have deletion protection enabled
3. All security groups have descriptive names
4. All ALBs redirect HTTP to HTTPS
5. VPCs have flow logs enabled
Report violations at different severity levels.
Claude Code will generate a comprehensive security checker aspect matching your requirements.
CI/CD Integration Workflow
Integrate Aspects into your continuous deployment pipeline.
GitHub Actions Example
name: CDK Deploy
on:
push:
branches: [main]
jobs:
synth:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: |
npm ci
- name: Run CDK synth
run: npx cdk synth
env:
AWS_REGION: us-east-1
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Check for Aspect violations
run: |
# Aspects should have already reported violations during synth
# Exit with error if there were critical issues
if grep -q "CRITICAL" cdk.out/aspect-report.txt; then
echo "Critical compliance violations detected"
cat cdk.out/aspect-report.txt
exit 1
fi
Creating a Synth Hook
For more control, create a synth step that runs Aspects explicitly:
import { App, Aspects, SynthesisMessage } from 'aws-cdk-lib';
const app = new App();
// Apply aspects
Aspects.of(app).add(new TagEnforcement(rules));
Aspects.of(app).add(new SecurityChecker());
// Hook into synth to capture messages
app.synth({
skipValidation: false,
strict: true,
onSynthesis: (session) => {
const messages = session.messages;
const errors = messages.filter(m => m.level === 'error');
if (errors.length > 0) {
console.error('Aspect validation errors:');
errors.forEach(e => console.error(e.message));
throw new Error('Aspect validation failed');
}
}
});
Best Practices for CDK Aspects
Follow these guidelines when building and maintaining Aspects with Claude Code.
Keep Aspects Focused
Each aspect should handle one concern. Don’t try to do everything in a single aspect:
// ❌ Don't: One aspect doing too much
class EverythingAspect implements IAspect {
visit(node: IConstruct): void {
// Tagging
// Security checks
// Naming validation
// Cost tracking
// ... 500 lines later
}
}
// ✅ Do: Focused, composable aspects
class TagEnforcement implements IAspect { /* tagging only */ }
class SecurityChecker implements IAspect { /* security only */ }
class NamingValidator implements IAspect { /* naming only */ }
class CostTagger implements IAspect { /* cost only */ }
// Apply individually
Aspects.of(stack)
.add(new TagEnforcement(tags))
.add(new SecurityChecker())
.add(new NamingValidator())
.add(new CostTagger());
Test Your Aspects
Claude Code can help generate tests for your aspects:
// test/tag-enforcement.test.ts
import { Stack } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { TagEnforcement } from '../lib/aspects/tag-enforcement';
import { CfnBucket } from 'aws-cdk-lib';
describe('TagEnforcement', () => {
test('reports missing required tags', () => {
const stack = new Stack();
// Create bucket without tags
new CfnBucket(stack, 'TestBucket', {
bucketName: 'test-bucket'
});
const aspect = new TagEnforcement([
{ key: 'Environment', required: true }
]);
Aspects.of(stack).add(aspect);
// Synth will trigger the aspect
expect(() => stack.synth()).toThrow();
});
});
Conclusion
CDK Aspects combined with Claude Code create a powerful workflow for infrastructure governance. By automating compliance checks, tagging enforcement, and security validation at synthesis time, you catch issues before deployment and maintain consistent infrastructure standards across your organization.
Start with simple tag enforcement, then gradually add more sophisticated Aspects as your governance needs grow. Claude Code can help you build and maintain these aspects efficiently, allowing you to focus on your application logic while ensuring your infrastructure meets organizational standards.
Related Reading
- Claude Code for Terraform AWS Provider Guide
- Best Claude Skills for DevOps and Deployment
- Claude Skills Guides Hub
Built by theluckystrike — More at zovo.one