CDK Infrastructure
AWS CDK is a framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation.
The TypeScript infrastructure generator creates an AWS CDK infrastructure application written in TypeScript. The generated application includes security best practices through Checkov security checks.
Generate an Infrastructure Project
Section titled “Generate an Infrastructure Project”You can generate a new infrastructure project in two ways:
- Install the Nx Console VSCode Plugin if you haven't already
- Open the Nx Console in VSCode
- Click
Generate (UI)in the "Common Nx Commands" section - Search for
@aws/nx-plugin - ts#infra - Fill in the required parameters
- Click
Generate
pnpm nx g @aws/nx-plugin:ts#infrayarn nx g @aws/nx-plugin:ts#infranpx nx g @aws/nx-plugin:ts#infrabunx nx g @aws/nx-plugin:ts#infraYou can also perform a dry-run to see what files would be changed
pnpm nx g @aws/nx-plugin:ts#infra --dry-runyarn nx g @aws/nx-plugin:ts#infra --dry-runnpx nx g @aws/nx-plugin:ts#infra --dry-runbunx nx g @aws/nx-plugin:ts#infra --dry-runOptions
Section titled “Options”| Parameter | Type | Default | Description |
|---|---|---|---|
| name Required | string | - | The name of the application. |
| directory | string | packages | The directory of the new application. |
| enableStageConfig | boolean | Enable centralized stage configuration (credentials, account, region) for multi-environment CDK deployments. |
Generator Output
Section titled “Generator Output”The generator will create the following project structure in the <directory>/<name> directory:
Directorysrc
- main.ts Application entry point instantiating CDK stages to deploy
Directorystages CDK Stage definitions
- application-stage.ts Defines a collection of stacks to deploy in a stage
Directorystacks CDK Stack definitions
- application-stack.ts Main application stack
- cdk.json CDK configuration
- project.json Project configuration and build targets
- checkov.yml Checkov configuration file
If you set the enableStageConfig option, the generator also creates two shared packages for centralized credential management (if they don’t already exist):
Directorypackages/common
Directoryinfra-config Stage configuration types and credential mappings
Directorysrc
- stages.types.ts Type definitions for stage credentials and config
- stages.config.ts Your stage-to-credential mappings (edit this)
- index.ts Re-exports for importing from other packages
Directoryscripts Centralized deploy/destroy scripts
Directorysrc
- infra-deploy.ts Deploy bin script
- infra-destroy.ts Destroy bin script
Directorystage-credentials/ Shared logic (credential lookup, CDK command building)
- …
Implementing your CDK Infrastructure
Section titled “Implementing your CDK Infrastructure”You can start writing your CDK infrastructure inside src/stacks/application-stack.ts, for example:
import { Stack, StackProps } from 'aws-cdk-lib';import { Bucket } from 'aws-cdk-lib/aws-s3'import { Construct } from 'constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props);
// Declare your infrastructure here new Bucket(this, 'MyBucket'); }}Stages and Stacks
Section titled “Stages and Stacks”CDK uses Stages to group stacks that should be deployed together to a specific environment. The generated src/main.ts creates a sandbox stage for your own development and testing:
new ApplicationStage(app, 'my-app-sandbox', { env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION, },});The env property tells CDK which AWS account and region to deploy to. CDK_DEFAULT_ACCOUNT and CDK_DEFAULT_REGION are resolved automatically by the CDK CLI from your active AWS credentials. See the CDK environments documentation for more details.
If you generated with enableStageConfig, the main.ts reads account and region from a centralized config file instead, falling back to environment variables when no config is set:
import stagesConfig from ':my-scope/common-infra-config';
const projectStages = stagesConfig.projects?.['packages/infra']?.stages ?? {};const sandboxConfig = projectStages['my-app-sandbox'];
new ApplicationStage(app, 'my-app-sandbox', { env: { account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT, region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION, },});You can add more stages to deploy to different environments. For example, beta and prod stages targeting separate AWS accounts:
new ApplicationStage(app, 'project-beta', { env: { account: '123456789012', region: 'us-west-2', },});new ApplicationStage(app, 'project-prod', { env: { account: '098765432109', region: 'us-west-2', },});A Stage groups one or more stacks. You can add as many stacks as you need inside a stage:
import { Stage, StageProps } from 'aws-cdk-lib';import { Construct } from 'constructs';import { BackendStack } from '../stacks/backend-stack.js';import { FrontendStack } from '../stacks/frontend-stack.js';
export class ApplicationStage extends Stage { constructor(scope: Construct, id: string, props?: StageProps) { super(scope, id, props);
new BackendStack(this, 'Backend', { crossRegionReferences: true, })
new FrontendStack(this, 'Frontend', { crossRegionReferences: true, }); }}Stage Credential Configuration
Section titled “Stage Credential Configuration”When you have multiple stages targeting different AWS accounts, managing credentials manually can be error-prone, especially as the number of stages grows.
The enableStageConfig option solves this by generating two shared packages:
packages/common/infra-config— A single config file where you map each stage to its AWS credentials, account, and region. This is importable from any package in your workspace, so your CDKmain.tscan read account and region from the same source of truth.packages/common/scripts—infra-deployandinfra-destroycommands that wrap CDK with automatic credential resolution. When you rundeploy, the script reads the config, sets the right AWS environment variables for the CDK child process, and runscdk deploy. Your shell environment is never modified.
Configuring Credentials
Section titled “Configuring Credentials”Edit packages/common/infra-config/src/stages.config.ts to map your stages to AWS credentials:
import type { StagesConfig } from './stages.types.js';
const config: StagesConfig = { projects: { // The key is the project path relative to the workspace root. // This matches the path in project.json and in deploy commands. 'packages/infra': { stages: { // Stage names must match the CDK stage identifiers in main.ts // (the first argument to `new ApplicationStage(app, 'my-app-dev', ...)`). 'my-app-dev': { credentials: { type: 'profile', profile: 'dev-account' }, region: 'us-east-1', }, 'my-app-prod': { credentials: { type: 'assumeRole', assumeRole: 'arn:aws:iam::123456789012:role/DeployRole', }, region: 'us-west-2', account: '123456789012', }, }, }, }, shared: { // Shared stages are available to all infra projects. // Project-specific entries take priority over shared ones. stages: { sandbox: { credentials: { type: 'profile', profile: 'personal-sandbox' }, region: 'us-east-1', }, }, },};
export default config;When you deploy, for example:
pnpm nx run infra:deploy my-app-dev/*yarn nx run infra:deploy my-app-dev/*npx nx run infra:deploy my-app-dev/*bunx nx run infra:deploy my-app-dev/*The deploy script:
- Extracts the stage name
my-app-devfrom the command arguments - Looks up credentials in the config: first under
projects['packages/infra'], then undershared - If found, sets
AWS_PROFILE(or assumes the IAM role) for the CDK child process only - If not found, falls back to whatever AWS credentials are in your environment
This means existing workflows without any config continue to work — the script only applies credentials when it finds a matching entry.
Credential Types
Section titled “Credential Types”Two credential strategies are supported:
profile— Uses a named AWS CLI profile from~/.aws/config. The script setsAWS_PROFILEfor the CDK process.assumeRole— Calls STS AssumeRole with the specified role ARN and passes the temporary credentials to CDK. You can optionally specify aprofileas the source credentials for the AssumeRole call, anexternalIdfor cross-account trust policies, and asessionDurationin seconds.
Account and Region
Section titled “Account and Region”Each stage config includes a required region and an optional account:
region(required) — The AWS region to deploy to (e.g.,us-east-1,eu-west-2).account(optional) — The AWS account ID. If omitted, CDK infers it from the active credentials at deploy time. See the CDK environments documentation for how CDK resolves account and region.
The generated main.ts reads these values from the config so that CDK synthesis and deployment use the same environment settings:
const sandboxConfig = projectStages['my-app-sandbox'];new ApplicationStage(app, 'my-app-sandbox', { env: { account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT, region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION, },});Shared vs Project-Specific Stages
Section titled “Shared vs Project-Specific Stages”Shared stages (under shared.stages) apply to any infra project in the workspace. This is useful when multiple projects deploy to the same sandbox account — you define the credentials once instead of repeating them for each project.
Project-specific stages (under projects['packages/infra'].stages) only apply to that project. When both exist for the same stage name, the project-specific entry takes priority.
API Infrastructure
Section titled “API Infrastructure”If you have used the tRPC API or FastAPI generators to create APIs, you will notice you already have some constructs available in packages/common/constructs to deploy them.
If, for example, you created a tRPC API called my-api, you can simply import and instantiate the construct to add all necessary infrastructure to deploy it:
import * as cdk from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyApi } from ':my-scope/common-constructs';
export class ApplicationStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props);
// Add infrastructure for your API new MyApi(this, 'MyApi', { integrations: MyApi.defaultIntegrations(this).build(), }); }}Website Infrastructure
Section titled “Website Infrastructure”If you have used the CloudScape website generator, you will notice you already have a construct in packages/common/constructs to deploy it. For example:
import * as cdk from 'aws-cdk-lib';import { Construct } from 'constructs';import { MyWebsite } from ':my-scope/common-constructs';
export class ApplicationStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props);
// Add infrastructure for your website new MyWebsite(this, 'MyWebsite'); }}It is important to ensure that the website is declared after any API constructs in order for the website Runtime Config to include all API config.
Synthesizing your Infrastructure
Section titled “Synthesizing your Infrastructure”As part of your build target, as well as running the default compile, lint and test targets, your infrastructure project is synthesized to CloudFormation. This can also be executed in a standalone fashion, by running the synth target:
pnpm nx run <my-infra>:synthyarn nx run <my-infra>:synthnpx nx run <my-infra>:synthbunx nx run <my-infra>:synthYou will find your synthesized cloud assembly in the root dist folder, under dist/packages/<my-infra-project>/cdk.out.
Security Testing
Section titled “Security Testing”A checkov target is added to your project which runs security checks on your infrastructure using Checkov.
pnpm nx run <my-infra>:checkovyarn nx run <my-infra>:checkovnpx nx run <my-infra>:checkovbunx nx run <my-infra>:checkovYou will find your security test results in the root dist folder, under dist/packages/<my-infra-project>/checkov.
Suppressing Checkov Checks
Section titled “Suppressing Checkov Checks”There may be instances where you want to suppress certain rules on resources. You can do this in two ways:
Supress a rule on a given construct
Section titled “Supress a rule on a given construct”import { suppressRules } from ':my-scope/common-constructs';
// suppresses the CKV_AWS_XXX for the given construct.suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');Supress a rule on a descendant construct
Section titled “Supress a rule on a descendant construct”import { suppressRules } from ':my-scope/common-constructs';
// Supresses the CKV_AWS_XXX for the construct or any of its descendants if it is an instance of BucketsuppressRules(construct, ['CKV_AWS_XXX'], 'Reason', (construct) => construct instanceof Bucket);Bootstrapping your AWS Account(s)
Section titled “Bootstrapping your AWS Account(s)”If you are deploying a CDK application to an AWS Account for the first time, it will need to be bootstrapped. Bootstrapping creates the resources CDK needs to manage deployments (an S3 bucket for assets, IAM roles, etc.).
First, ensure that you have configured credentials for your AWS account.
Next, run the bootstrap command for each account and region you plan to deploy to:
npx cdk bootstrap aws://<account-id>/<region>For more details, please refer to the CDK bootstrapping documentation.
Deploying to AWS
Section titled “Deploying to AWS”After a build, you can deploy your infrastructure to AWS using the deploy target.
First, make sure you have AWS credentials configured. If you generated with enableStageConfig and have configured stage credentials in packages/common/infra-config/src/stages.config.ts, the deploy command will automatically resolve and apply the correct credentials for the target stage. Otherwise, ensure your AWS credentials are set in your environment (e.g., via AWS_PROFILE or environment variables). See the AWS credentials documentation for the available options.
Then run the deploy target:
pnpm nx run <my-infra>:deploy <my-infra>-sandbox/*yarn nx run <my-infra>:deploy <my-infra>-sandbox/*npx nx run <my-infra>:deploy <my-infra>-sandbox/*bunx nx run <my-infra>:deploy <my-infra>-sandbox/*Deploying to AWS in a CI/CD Pipeline
Section titled “Deploying to AWS in a CI/CD Pipeline”Use the deploy-ci target if you are deploying to AWS as part of a CI/CD pipeline.
pnpm nx run <my-infra>:deploy-ci my-stage/*yarn nx run <my-infra>:deploy-ci my-stage/*npx nx run <my-infra>:deploy-ci my-stage/*bunx nx run <my-infra>:deploy-ci my-stage/*This target differs slightly from the regular deploy target in that it deploys a pre-synthesized cloud assembly rather than synthesizing on the fly. This avoids potential non-determinism from package version changes, ensuring that every pipeline stage deploys using the same cloud assembly.
Tearing Down AWS Infrastructure
Section titled “Tearing Down AWS Infrastructure”Use the destroy target to tear down your resources:
pnpm nx run <my-infra>:destroy <my-infra>-sandbox/*yarn nx run <my-infra>:destroy <my-infra>-sandbox/*npx nx run <my-infra>:destroy <my-infra>-sandbox/*bunx nx run <my-infra>:destroy <my-infra>-sandbox/*More Information
Section titled “More Information”For more information about CDK, please refer to the CDK Developer Guide and API Reference.