globaldatanetmenu

.CDK Best Practices

May 17th 2022-5 min read

In this post i want to show you my best practices while developing and deploying infrastructure using CDK. Let's start with a short intro about CDK. CDK - AWS Cloud Development Kit is a tool to manage AWS resources in a fully programmatic way. It is available in different popular programming languages like TypeScript, JavaScript, Python, C#/.NET and Java.

Key concepts

In the following picture you can see the anatomy of CDK.

Blog Content
  • Apps are the final artifact of code that define one or more Stacks.
  • Stacks are equivalent to CloudFormation stacks and are made up of Constructs.
  • Constructs define one or more concrete AWS resources, such as the S3 Bucket or your Lambda Function.

If you want to learn more about how to get started with CDK take a look at the AWS CDK Developer Guide or take a look at the CDK workshop.

Best Practices

Now let's jump into my Best Practices i am using on daily bases to build my automations with CDK. Just as a side note i am using CDK with Typescript.

Validation of your CDK APP variables

Whenever you want your user to pass information to your CDK app ensure to validate the variables. I want my users to pass the information via JSON files always so I can use typescript-json-schema for my app. Here is an example how my config-validator looks like.

import Ajv, {JSONSchemaType} from "ajv";
import {Config} from "../types/config";
import { resolve } from "path";
import * as TJS from "typescript-json-schema";

const settings: TJS.PartialArgs = {
  required: true,
  noExtraProps: true
};

const compilerOptions: TJS.CompilerOptions = {
  strictNullChecks: true,
};

const program = TJS.getProgramFromFiles(
  [resolve("lib/types/config.ts")],
  compilerOptions
);

const schema = TJS.generateSchema(program, "Config", settings);

const ajv = new Ajv();

export const validate = ajv.compile(schema as JSONSchemaType<Config>);

Use Regex to check the CDK App variables

Whenever you need specific information in a variable like an AWS AccountId or VPCId you should use annotations with regex to validate the content of your variable before the deployment. Here is an example how your types could look like.

interface CrossAccountVpc{
  /**
   * @TJS-pattern "^vpc-[0-9A-Za-z]{13}$"
   */
  readonly VPCId: string,
  /**
   * @TJS-pattern "^[0-9]{12}$"
   */
  readonly AccountId: string,
}

If the content of the variable is not correct the following error can be shown if you are using the schema validation:

Blog Content

Clean your cdk.out directory before deployment

When ever you want to deploy your cdk app to a new account or stage i can recommend you to clean your cdk.out directory before the next deployment. I am using taskfiles for deployment so I created a small clean task which will be invoked before my deployment task.

tasks:
  deploy:
    desc: Deploy Stack
    cmds:
      - task: clean
      - task: cdkdeploy  
  clean:
    desc: Clean CDK Out
    cmds:
      - rm -rf ./cdk.out
    silent: true
  cdkdeploy:
    desc: CDK Deploy
    cmds:
      - cdk deploy --require-approval never {{.TAGS}} --strict
    vars:
      ACCOUNT:
        sh: aws sts get-caller-identity |jq -r .Account
      TAGS:
        sh: cat tags/tags.json | jq -j '.[]|"--tags " + (.Key)+"="+(.Value)+" "'
    silent: true
    interactive: true

Structurize your app in multiple stacks

When building a CDK App which contains a lot of constructs it make sense to structurize your project and set up multiple stacks when creating the Infrastructure. Therefore it's good to know how you can reference resources across stacks in AWS CDK. If you want to learn how to do this - look at this blogpost.

Use Grants

AWS CDK help you to easily manage roles and security groups. The construct library grant() allows you to quick and simple create AWS Identity and Access Management roles granting access to one resource by another using minimally-scoped permissions. If you want to learn more about grants look at the aws cdk documentation<