How to get ARN of resources in AWS CDK

avatar

Borislav Hadzhiev

Sat Apr 24 20214 min read

Updated on Sat Apr 24 2021

In order to access the Arn of resources in CDK we have to use the resource-specific `resourceNameArn` property on the construct

Getting ARNs of Resources in AWS CDK #

ARNs (Amazon Resource Names) are used to uniquely identify AWS resources across all regions, accounts and services.

In order to get the Arn of a resource we have to use the resource-specific resourceNameArn property, for example:

The code for this article is available on GitHub

Let's look at an example of accessing the Arn of an S3 bucket:

lib/cdk-starter-stack.ts
import * as s3 from '@aws-cdk/aws-s3';
import * as cdk from '@aws-cdk/core';

export class MyCdkStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    const s3Bucket = new s3.Bucket(this, 'avatars-bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    // ๐Ÿ‘‡ assign the arn to a variable
    const s3BucketArn = s3Bucket.bucketArn;
    console.log('bucketArn ๐Ÿ‘‰ ', s3BucketArn);

    new cdk.CfnOutput(this, 'myBucketArn', {
      value: s3BucketArn,
      description: 'The arn of the s3 bucket',
    });
  }
}

In the code snippet:

  1. We've used the Bucket construct to create a bucket resource

  2. We've accessed the bucketArn property and stored the value in the s3BucketArn variable

  3. We've passed the bucket arn in a call to console.log and wrote the value to an Output

I'll now run the synth command to execute my CDK code and generate the CloudFormation template:

shell
npx cdk synth

The output shows that the bucket arn is a token at synthesis time:

token arn

Tokens in CDK are encoded values, that will get resolved at deployment time by CloudFormation. This means that we can't access the resolved resource Arn in our CDK code.

When we run the cdk synth command a CloudFormation template gets generated in the cdk.out directory of our project.

If we take a look at the Outputs section, we can see that our reference to the bucket Arn has been replaced by the GetAtt intrinsic function.

cdk out arn

I'll deploy via the cdk deploy command, so we can see the Arn value resolved in the Outputs section of the CloudFormation console:

shell
npx cdk deploy

The resolved Arn is visible in the Value column of our Outputs section:

arn resolved

The value for the Arn of resources gets resolved by CloudFormation at deployment time, rather than synthesis time. We only have access to the encoded token value in our code.

If you are working with CfnResources instead of Level 2 Constructs

Getting ARN of Cfn Resources in CDK #

Sometimes we have to work with the lower level Cfn resources, which don't expose the resourceNameArn properties.

In order to access the Arn of a Cfn Resource we have to use the attrArn property on the resource.

lib/cdk-starter-stack.ts
import * as s3 from '@aws-cdk/aws-s3';
import * as cdk from '@aws-cdk/core';

export class MyCdkStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    const s3Bucket = new s3.Bucket(this, 'avatars-bucket');

    // ๐Ÿ‘‡ Get access to the Cfn Resource
    const cfnBucket = s3Bucket.node.defaultChild as s3.CfnBucket;

    // ๐Ÿ‘‡ access the arn
    const cfnArn = cfnBucket.attrArn;
  }
}

In the code snippet, we've used the attrArn property. The name of the attrArn property is consistent, for example getting the arn of a Dynamodb CfnTable looks like:

lib/cdk-starter-stack.ts
const table = new dynamodb.Table(this, 'my-table', {
  partitionKey: {name: 'todoId', type: dynamodb.AttributeType.NUMBER},
  removalPolicy: cdk.RemovalPolicy.DESTROY,
});

console.log('on Level 2 Construct ๐Ÿ‘‰', table.tableArn);

// ๐Ÿ‘‡ get access to the Level 1 Cfn resource
const cfnTable = table.node.defaultChild as dynamodb.CfnTable;

// ๐Ÿ‘‡ access the arn
const cfnTableArn = cfnTable.attrArn;

Getting ARNs via the GetAtt Function in CDK #

The third method to get the Arn of a resource is very close to how we would do it in CloudFormation.

We have to use the getAtt method on the Fn class and get the Arn attribute:

lib/cdk-starter-stack.ts
import * as s3 from '@aws-cdk/aws-s3';
import * as cdk from '@aws-cdk/core';

export class MyCdkStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    const s3Bucket = new s3.Bucket(this, 'avatars-bucket');

    // ๐Ÿ‘‡ Get access to the Cfn Resource
    const cfnBucket = s3Bucket.node.defaultChild as s3.CfnBucket;

    // ๐Ÿ‘‡ access the arn
    const bucketArn = cdk.Fn.getAtt(cfnBucket.logicalId, 'Arn').toString();
  }
}

In the code snippet we've used the getAtt method on the Fn class. The method takes two parameters:

  1. the logical ID of the resource
  2. the name of the attribute we're trying to access

The getAtt method returns an object that exposes a toString() function, which we use in order to get a string representation of the value.

This approach is very similar to how we would do this in CloudFormation, via the GetAtt intrinsic function:

template.json
{
  "Outputs": {
    "myCfnBucketArn": {
      "Value": {
        // ๐Ÿ‘‡
        "Fn::GetAtt": [
          "avatarsbucketE3043F49",
          "Arn"
        ]
      }
    }
  }
}

Summary #

The best way to access an Arn in CDK is by using the resource-specific resourceNameArn property on the Level 2 Construct.

lib/cdk-starter-stack.ts
const s3Bucket = new s3.Bucket(this, 'avatars-bucket', {
  removalPolicy: cdk.RemovalPolicy.DESTROY,
});

const bucketArn = s3Bucket.bucketArn;

When working with Cfn Resources (Level 1 Constructs), we have to use the attrArn property:

lib/cdk-starter-stack.ts
const s3Bucket = new s3.Bucket(this, 'avatars-bucket', {
  removalPolicy: cdk.RemovalPolicy.DESTROY,
});

// ๐Ÿ‘‡ Get access to the Cfn Resource
const cfnBucket = s3Bucket.node.defaultChild as s3.CfnBucket;

const cfnArn = cfnBucket.attrArn;

The ARN values are just encoded Tokens at synthesis time, they are resolved by CloudFormation at deployment time.

Further Reading #

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee