How to get Secrets Manager Values in AWS CDK

avatar

Borislav Hadzhiev

Sat Apr 24 20214 min read

banner

Photo by Jeremy Bishop

Updated on Sat Apr 24 2021

In order to get a Value from Secrets Manager in CDK we have to use the `fromSecretNameV2` static method exposed by the `Secret` construct.

Getting Secrets Manager Values in AWS CDK #

The AWS Secrets Manager service allows us to store, manage and rotate secrets that we need to use to access databases, APIs, etc.

For the purposes of this demo I'll create a secret using the AWS CLI:

shell
aws secretsmanager create-secret --name databasePassword \
  --description "The password for a database" \
  --secret-string "dogsandcats123"

If we look at the Secrets manager console, we can see that the secret has been provisioned:

secrets manager console

Getting Secret Manager Values by Secret Name in CDK #

The easiest way to get a Secrets Manager value in AWS CDK is via the fromSecretNameV2 static method on the Secret construct.

The code for this article is available on GitHub

I'll provision a CDK stack, consisting of a single Lambda function and I'll pass the secret to the Lambda as an environment variable:

lib/cdk-starter-stack.ts
import * as lambda from '@aws-cdk/aws-lambda';
import {NodejsFunction} from '@aws-cdk/aws-lambda-nodejs';
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
import * as cdk from '@aws-cdk/core';
import * as path from 'path';

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

    // ๐Ÿ‘‡ get access to the secret object
    const dbPasswordSecret = secretsmanager.Secret.fromSecretNameV2(
      this,
      'db-pwd-id',
      'databasePassword',
    );

    const myFunction = new NodejsFunction(this, 'my-function', {
      // ๐Ÿ‘‡ set secret value as ENV variable
      environment: {
        SECRET_NAME: dbPasswordSecret.secretName,
        SECRET_VALUE: dbPasswordSecret.secretValue.toString(),
      },
      runtime: lambda.Runtime.NODEJS_14_X,
      memorySize: 1024,
      timeout: cdk.Duration.seconds(5),
      handler: 'main',
      entry: path.join(__dirname, `/../src/my-lambda/index.js`),
    });
  }
}

The code of the lambda function could be as simple as:

src/my-lambda/index.js
async function main(event) {
  console.log('SECRET_NAME ๐Ÿ‘‰', process.env.SECRET_NAME);
  console.log('SECRET_VALUE ๐Ÿ‘‰', process.env.SECRET_VALUE);

  return {body: JSON.stringify({message: 'SUCCESS'}), statusCode: 200};
}

In the code snippet we invoked the fromSecretNameV2 static method on the Secret construct to get access to the object that represents a Secrets Manager secret.

The fromSecretNameV2 static method takes 3 parameters:

  1. the scope in which the method is invoked
  2. the id of the secret in the construct tree
  3. the name of the secret

We also defined a Lambda function and passed it two environment variables - SECRET_NAME and SECRET_VALUE.

I'll now deploy the CDK stack:

shell
npx cdk deploy

Next, I'll invoke the Lambda function by using the Test functionality in the Lambda console. If we look at the log output from the lambda invocation we can see that we successfully accessed the Secrets Manager value:

lambda secret logs

Getting Secret Manager values by Secret ARN in CDK #

The most flexible way to get Secrets Manager values by ARN is using the fromSecretAttributes method on the Secret construct.

lib/cdk-starter-stack.ts
import * as lambda from '@aws-cdk/aws-lambda';
import {NodejsFunction} from '@aws-cdk/aws-lambda-nodejs';
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
import * as cdk from '@aws-cdk/core';
import * as path from 'path';

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

    // ๐Ÿ‘‡ get secret by partial ARN
    const dbPasswordSecret = secretsmanager.Secret.fromSecretAttributes(
      this,
      'db-pwd-id',
      {
        secretPartialArn:
          'arn:aws:secretsmanager:us-east-1:123456789:secret:databasePassword',
      },
    );

    const myFunction = new NodejsFunction(this, 'my-function', {
      // ๐Ÿ‘‡ set secret value as ENV variable
      environment: {
        SECRET_NAME: dbPasswordSecret.secretName,
        SECRET_VALUE: dbPasswordSecret.secretValue.toString(),
      },
      runtime: lambda.Runtime.NODEJS_14_X,
      memorySize: 1024,
      timeout: cdk.Duration.seconds(5),
      handler: 'main',
      entry: path.join(__dirname, `/../src/my-lambda/index.js`),
    });
  }
}

In the code snippet we used the fromSecretAttributes static method to get the Secret value. The method takes 3 parameters:

  1. the scope in which the method is invoked
  2. the id of the imported Secret in the construct tree
  3. an attributes object, which has 3 properties:
    • secretPartialArn - the ARN of the secret, without the 6 character Secrets Manager suffix
    • secretCompleteArn - the complete ARN of the secret, including the 6 character Secrets Manager suffix
    • encryptionKey - the encryption key used to encrypt the secret, in case we don't use the default Secrets Manager key

Get Secrets Manager Value by ARN - Alternative #

A more direct approach to get a Secrets Manager value by ARN is to use the fromSecretCompleteArn or fromSecretPartialArn static methods on the Secret class.

The complete arn includes the 6 character suffix added by the secrets manager service, whereas the partial arn does not.

An example of using the fromSecretPartialArn static method looks like:

lib/cdk-starter-stack.ts
const dbPasswordSecret = secretsmanager.Secret.fromSecretPartialArn(
  this,
  'db-pwd-id',
  'arn:aws:secretsmanager:us-east-1:123456789:secret:databasePassword',
);

The third parameter the function takes is the partial arn of the Secret.

Here is an example of using the fromSecretCompleteArn static method:

lib/cdk-starter-stack.ts
const dbPasswordSecret = secretsmanager.Secret.fromSecretCompleteArn(
  this,
  'db-pwd-id',
  'arn:aws:secretsmanager:us-east-1:123456789:secret:databasePassword-bmst1b',
);

The third parameter the function takes is the complete Secret ARN with the 6 character suffix.

If we try to synth a stack, where we didn't provide the complete arn, with the 6 character suffix to fromSecretCompleteArn we get an error:

Error: `secretCompleteArn` does not appear to be complete; missing 6-character suffix

complete arn error

Clean up #

In order to delete a secret using the AWS CLI, we can issue the delete-secret command:

shell
aws secretsmanager delete-secret \
  --secret-id databasePassword \
  --recovery-window-in-days 7

Where the --secret-id flag can be either the ARN of the secret or the secret's name.

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