Skip to content

CDK Snippets

Bootstrap with trusted account

bash
cdk bootstrap aws://${accountId}/ap-southeast-1 --trust ${trustedAccountId}

Get stack name

typescript
console.log('stackName 👉', cdk.Stack.of(this).stackName);

Read and Store value into Parameter Store

typescript
import { StringParameter } from 'aws-cdk-lib/aws-ssm';

// retrieve value
const domainName = StringParameter.valueForStringParameter(this, '/kmp/config/domain-name');

// store into parameter store
new StringParameter(this, 'BucketName', {
  parameterName: '/kmp/tenant/bucket-name',
  stringValue: bucket.bucketName,
});

Get Certificate and HostedZone

typescript
const domainName = StringParameter.valueForStringParameter(this, '/kmp/config/domain-name');
const certificateArn = StringParameter.valueForStringParameter(
  this,
  '/kmp/config/certificate-arn-ap-southeast-1'
);
const hostedZoneId = StringParameter.valueForStringParameter(this, '/kmp/config/hosted-zone-id');

const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
  hostedZoneId,
  zoneName: domainName,
});
const certificate = Certificate.fromCertificateArn(this, 'Certificate', certificateArn);

Create S3 Bucket that gets deleted when destroyed

typescript
const bucket = new Bucket(this, 'TenantBucket', {
  removalPolicy: cdk.RemovalPolicy.DESTROY,
  autoDeleteObjects: true,
});

Create DynamoDB Table

typescript
const table = new TableV2(this, 'TenantTable', {
  partitionKey: { name: 'tenantName', type: AttributeType.STRING },
  sortKey: { name: 'createdAt', type: AttributeType.STRING },
  // destroy table when stack is destroyed
  removalPolicy: cdk.RemovalPolicy.DESTROY,
});

table.addGlobalSecondaryIndex({
  indexName: 'userNameIndex',
  partitionKey: { name: 'userName', type: AttributeType.STRING },
  projectionType: ProjectionType.ALL,
});

Create Lambda using NodejsFunction

typescript
const apiHandler = new NodejsFunction(this, 'TenantApiHandler', {
  memorySize: 1024,
  timeout: cdk.Duration.seconds(5),
  runtime: Runtime.NODEJS_18_X,
  entry: path.join(__dirname, '../src/api/index.ts'),
  bundling: {
    minify: true,
    externalModules: ['@aws-sdk/*'],
  },
  environment: {
    table: table.tableName,
  },
});

Create HTTP Api with Custom Domain

typescript
import { CorsHttpMethod, DomainName, HttpApi, HttpMethod } from '@aws-cdk/aws-apigatewayv2-alpha';
import { HttpLambdaIntegration } from '@aws-cdk/aws-apigatewayv2-integrations-alpha';
import { ARecord, HostedZone, RecordTarget } from 'aws-cdk-lib/aws-route53';
import { ApiGatewayv2DomainProperties } from 'aws-cdk-lib/aws-route53-targets';

const hostname = 'tenant-api';

const customDomain = new DomainName(this, `TenantCustomDomain`, {
  domainName: `${hostname}.${domainName}`,
  certificate,
});

new ARecord(this, 'TenantCustomDomainRecord', {
  recordName: hostname,
  zone: hostedZone,
  target: RecordTarget.fromAlias(
    new ApiGatewayv2DomainProperties(
      customDomain.regionalDomainName,
      customDomain.regionalHostedZoneId
    )
  ),
});

const httpApi = new HttpApi(this, 'TenantHttpApi', {
  corsPreflight: {
    allowOrigins: ['*'],
    allowCredentials: false,
    allowHeaders: ['Content-Type', 'X-Amz-Date', 'Authorization', 'X-Api-Key'],
    allowMethods: [CorsHttpMethod.ANY],
  },
  defaultDomainMapping: {
    domainName: customDomain,
  },
});

httpApi.addRoutes({
  path: '/',
  methods: [HttpMethod.ANY],
  integration: new HttpLambdaIntegration('TenantApiIntegration', apiHandler),
});

Use CfnParameter

Deploy myStack:

bash
npx aws-cdk deploy MyStack --parameters databasePort=5000

Inside the CDK:

typescript
const databasePort = new cdk.CfnParameter(this, 'databasePort', {
  type: 'Number',
  description: 'The database port to open for ingress connections',
  minValue: 1,
  maxValue: 10000,
  default: 5432,
  allowedValues: ['1000', '3000', '5000', '5432'],
});
console.log('database port 👉', databasePort.valueAsString);

Made with ❤️ by Bagubagu Studio