Last updated: Jan 26, 2024
Reading timeยท4 min
The AWS Secrets Manager service allows us to store, manage and rotate secrets that we need to use to access databases, APIs, etc.
For this demo, I'll create a secret using the AWS CLI:
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.
The easiest way to get a Secrets Manager value in AWS CDK is via the fromSecretNameV2 static method on the Secret construct.
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:
import * as lambda from 'aws-cdk-lib/aws-lambda'; import {NodejsFunction} from 'aws-cdk-lib/aws-lambda-nodejs'; import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'; import * as cdk from 'aws-cdk-lib'; 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_18_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 follows.
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 sample, 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:
scope
in which the method is invoked.id
of the secret in the construct tree.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.
npx aws-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.
The most flexible way to get Secrets Manager values by ARN is using the fromSecretAttributes method on the Secret construct.
import * as lambda from 'aws-cdk-lib/aws-lambda'; import {NodejsFunction} from 'aws-cdk-lib/aws-lambda-nodejs'; import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'; import * as cdk from 'aws-cdk-lib'; 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_18_X, memorySize: 1024, timeout: cdk.Duration.seconds(5), handler: 'main', entry: path.join(__dirname, `/../src/my-lambda/index.js`), }); } }
In the code sample, we used the fromSecretAttributes
static method to get the
Secret value. The method takes 3 parameters:
scope
in which the method is invoked.id
of the imported Secret in the construct tree.secretPartialArn
- the ARN of the secret, without the 6-character Secrets
Manager suffixsecretCompleteArn
- the complete ARN of the secret, including the 6
character Secrets Manager suffixencryptionKey
- the encryption key used to encrypt the secret, in case we
don't use the default Secrets Manager keyA 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 as follows.
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.
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:
secretCompleteArn
does not appear to be complete; missing 6-character suffixIn order to delete a secret using the AWS CLI, we can issue the delete-secret
command.
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.
You can learn more about the related topics by checking out the following tutorials: