How to import existing AWS resources into CDK stack

Maria Verbenko
5 min readMar 31, 2020

--

If you are not creating your account from scratch at the same time when you’re starting to work with CDK, you might need to import existing resources to CDK stack to be able to manage them. This is especially true for S3 buckets, since their names are unique and you might not want to delete them or recreate them under another name. Or maybe you have an SNS topic that other teams or external organizations subscribe to?

In November 2019 AWS introduced importing mechanism for CloudFormation. Even though it’s not yet supported natively in CDK, there is a workaround that allows to do pretty much the same.

Resource identifiers in CDK

First of all, let’s talk about how CDK identifies resources. For all resources that it manages, CDK appends a unique string to the end of the resource identifier. For instance, if you create a bucket

import { Construct, Stack, StackProps } from ‘@aws-cdk/core’;
import { Bucket } from ‘@aws-cdk/aws-s3’;
export class ImportStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const bucket = new Bucket(this, ‘my-bucket’, {
bucketName: ‘my-unique-bucket-name’
});
}
}

The CloudFormation template resource name for the bucket will be something like

{
“Resources”: {
“mybucket15D133BF”: {
….
}
}
}

This is important because without this string “mybucket15D133BF” CDK won’t be able to identify your resource.

Good thing is that you don’t need to actually deploy the stack to be able to find out the name, it also stays consistent even when deploying the same resource to another account.

Generating a template for import

Let’s say we have a simple stack with an SNS topic:

import { Construct, Stack, StackProps } from ‘@aws-cdk/core’;
import { Topic } from ‘@aws-cdk/aws-sns’;
export class ImportStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const topic = new Topic(this, ‘my-topic’);
}
}

To be able to import an existing bucket to this stack, we need to first create an import template for CloudFormation to understand what we want to import. This template should include both existing resources and resources we want to import.

In our case template for existing resources looks like this:

{
“Resources”: {
“mytopicA51922FD”: {
“Type”: “AWS::SNS::Topic”,
“Metadata”: {
“aws:cdk:path”: “ImportStack/my-topic/Resource”
}
}
}
}

You can find it either in your cdk.out/ folder or in deployed CloudFormation stack in the tab “Template”.

Now we need to generate a CloudFormation resource configuration for our bucket and add it to our template. Instead of doing it manually, let’s do it with CDK itself! I have an existing bucket in my account, but I will add it to the stack code as if it doesn’t exist.

import { Construct, Stack, StackProps } from ‘@aws-cdk/core’;
import { Bucket } from ‘@aws-cdk/aws-s3’;
import { Topic } from ‘@aws-cdk/aws-sns’;
export class ImportStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const topic = new Topic(this, ‘my-topic’); const bucket = new Bucket(this, ‘test-bucket’, {
bucketName: ‘acast-maria-test-bucket’
});
}
}

If I try to deploy this stack, it will obviously fail, but I don’t need to do it actually. It’s enough to run

cdk synth

This will overwrite template in my cdk.out/ directory:

{
“Resources”: {
“mytopicA51922FD”: {
“Type”: “AWS::SNS::Topic”,
“Metadata”: {
“aws:cdk:path”: “ImportStack/my-topic/Resource”
}
},
“testbucketE6E05ABE”: {
“Type”: “AWS::S3::Bucket”,
“Properties”: {
“BucketName”: “acast-maria-test-bucket”
},
“UpdateReplacePolicy”: “Retain”,
“DeletionPolicy”: “Retain”,
“Metadata”: {
“aws:cdk:path”: “ImportStack/test-bucket/Resource”
}
},
“CDKMetadata”: {
“Type”: “AWS::CDK::Metadata”,
“Properties”: {
“Modules”: “aws-cdk=1.29.0,@aws-cdk/aws-cloudwatch=1.29.0,@aws-cdk/aws-iam=1.29.0,@aws-cdk/aws-sns=1.29.0,@aws-cdk/core=1.29.0,@aws-cdk/cx-api=1.29.0,@aws-cdk/region-info=1.29.0,jsii-runtime=node.js/v12.16.1”
}
}
}
}

We’re going to use this file in the next step.

Note: CDKMetadata resource is created automatically by CDK in your stack, you can copy it from your deployed stack template and add it to your generated template.

Let’s import the bucket!

For this part you will need to go to the AWS Console > CloudFormation.

Find your stack, open it and click “Stack Actions” / “Import resources into stack”.

Upload the template you created in the previous part.

Enter the identifiers for all the resources you want to import, in our case only the bucket.

Click through the rest of the wizard.

As soon as you’re done, your stack will start importing the bucket.​

Now you can manage your bucket with CDK.

Detecting drifts

After import is done, you can detect whether some of the resources have drifted. This means that actual configuration of the resource does not correspond to your stack’s template.

This can be useful for double-checking that you haven’t forgotten any configuration when you were creating your template.​​

--

--

Maria Verbenko

Backend developer interested in infrastructure as code, AWS, K8s, Lambdas. In my free time I paint.