Tag Archives: CDK

Scan standalone CDK constructs for misconfiguration

Vulnerability scanners like checkov have become a de facto standard for scanning IaC for possible misconfigurations. They can scan terraform configs, AWS CloudFormation templates, even – in a sense – CDK stacks, because they synthesize into CloudFormation templates that can be scanned.

In order to produce synthesized templates from stacks you have to have a full-blown CDK application. But what if you’re developing a standalone CDK construct as a library, to be used as a dependency in a CDK app? There is a way to scan it for vulnerabilities as well. Continue reading →

Synthesize only stacks you need in CDK

CDK documentation states that if you supply stack name(s) to CLI commands like cdk synth, cdk list, or cdk deploy – it will synthesize only the stacks you requested. But in reality this is not the case, CDK will always synthesize all stacks – and it may lead to unintended consequences.

Let’s say you have following stack declarations in your lib/my-stacks.ts code:

import * as cdk from 'aws-cdk-lib';
 
export class Stack1 extends cdk.Stack {};
export class Stack2 extends cdk.Stack {};
export class AnotherStack extends cdk.Stack {};
export class YerAnotherStack extends cdk.Stack {};

And in your app’s entry point bin/my-stacks.ts you instantiate those stacks:

import * as cdk from 'aws-cdk-lib';
import * as stacks from '../lib/my-stacks'
 
const app = new cdk.App();
 
new stacks.Stack1(app, "Stack1");
new stacks.Stack2(app, "Stack2");
new stacks.AnotherStack(app, "AnotherStack");
new stacks.YerAnotherStack(app, "YetAnotherStack");

And then issue a CLI command to synthesize stacks, but you only want to synthesize “Stack1” and “AnotherStack”: Continue reading →

CDK pipeline won’t restart after mutation

CDK Pipeline is a clever construct that makes continuously deploying your application and infrastructure super easy. The pipeline even has the ability to update itself or “mutate” if your commits include changes to the pipeline itself. This behavior is controlled by selfMutation property of the pipeline constructor and is true by default. Once the pipeline updates itself – it also restarts itself, so that new changes can take effect.

But if you create your CDK pipeline with regular AWS Pipeline as a base e.g.

const rawPipeline = new Pipeline(this, 'RawPipeline', {
   ...
 });
 
const pipeline = new CodePipeline(this, 'Pipeline', {
   codePipeline: rawPipeline,
   ...
});

suddenly the pipeline won’t auto-restart after the mutation. What is happening? Continue reading →

Share node_modules between CDK CodeBuildSteps

CDK makes it pretty easy and straightforward to create CodePipelines – define the pipeline, add build steps as needed, add deployment stages and you’re done. But imagine a scenario where you install Node dependencies in one step and then need to run some NPM scripts in another down the line. In order to avoid reinstalling the dependencies every time you can pass output of one step as an input of another:

const installStep = new CodeBuildStep("install-step", {
   input: sourceStep,
   commands: ["npm ci"],
   primaryOutputDirectory: ".",
});
 
const testStep = new CodeBuildStep("test-step", {
   input: installStep,
   commands: ["npm run test"],
   primaryOutputDirectory: ".",
});

Passing output of the installStep as input of the testStep copies everything created in the installStep – files, directory structure – including all dependencies installed into node_modules folder to the testStep, so any npm command in theory should work. But in reality they’d fail, telling you that some module or other is not found. The reason is that in addition to installing dependencies npm ci command also creates symlinks between some of them. Copying files from one step to another loses those symlinks. In order to rebuild them you need to run npm rebuild before running any npm commands in the consecutive steps. So the test step becomes

const testStep = new CodeBuildStep("test-step", {
   input: installStep,
   commands: ["npm rebuild", "npm run test"],
   primaryOutputDirectory: ".",
});

And this will throw no errors.