AWSCDK::SecretsManager

35 types

AWS Secrets Manager Construct Library

require 'aws-cdk-lib'

Create a new Secret in a Stack

To have SecretsManager generate a new secret value automatically, follow this example:

vpc = nil # AWSCDK::EC2::IVPC


instance1 = AWSCDK::RDS::DatabaseInstance.new(self, "PostgresInstance1", {
    engine: AWSCDK::RDS::DatabaseInstanceEngine.POSTGRES,
    # Generate the secret with admin username `postgres` and random password
    credentials: AWSCDK::RDS::Credentials.from_generated_secret("postgres"),
    vpc: vpc,
})
# Templated secret with username and password fields
templated_secret = AWSCDK::SecretsManager::Secret.new(self, "TemplatedSecret", {
    generate_secret_string: {
        secret_string_template: JSON[:stringify]({username: "postgres"}),
        generate_string_key: "password",
        exclude_characters: "/@\"",
    },
})
# Using the templated secret as credentials
instance2 = AWSCDK::RDS::DatabaseInstance.new(self, "PostgresInstance2", {
    engine: AWSCDK::RDS::DatabaseInstanceEngine.POSTGRES,
    credentials: {
        username: templated_secret.secret_value_from_json("username").to_string,
        password: templated_secret.secret_value_from_json("password"),
    },
    vpc: vpc,
})

If you need to use a pre-existing secret, the recommended way is to manually provision the secret in AWS SecretsManager and use the Secret.fromSecretArn or Secret.fromSecretAttributes method to make it available in your CDK Application:

encryption_key = nil # AWSCDK::KMS::Key

secret = AWSCDK::SecretsManager::Secret.from_secret_attributes(self, "ImportedSecret", {
    secret_arn: "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>",
    encryption_key: encryption_key,
})

SecretsManager secret values can only be used in select set of properties. For the list of properties, see the CloudFormation Dynamic References documentation.

A secret can set RemovalPolicy. If it set to RETAIN, removing that secret will fail.

Grant permission to use the secret to a role

You must grant permission to a resource for that resource to be allowed to use a secret. This can be achieved with the Secret.grantRead and/or Secret.grantWrite method, depending on your need:

role = AWSCDK::IAM::Role.new(self, "SomeRole", {assumed_by: AWSCDK::IAM::AccountRootPrincipal.new})
secret = AWSCDK::SecretsManager::Secret.new(self, "Secret")
secret.grant_read(role)
secret.grant_write(role)

If, as in the following example, your secret was created with a KMS key:

role = nil # AWSCDK::IAM::Role

key = AWSCDK::KMS::Key.new(self, "KMS")
secret = AWSCDK::SecretsManager::Secret.new(self, "Secret", {encryption_key: key})
secret.grant_read(role)
secret.grant_write(role)

then Secret.grantRead and Secret.grantWrite will also grant the role the relevant encrypt and decrypt permissions to the KMS key through the SecretsManager service principal.

The principal is automatically added to Secret resource policy and KMS Key policy for cross account access:

 = AWSCDK::IAM::AccountPrincipal.new("1234")
key = AWSCDK::KMS::Key.new(self, "KMS")
secret = AWSCDK::SecretsManager::Secret.new(self, "Secret", {encryption_key: key})
secret.grant_read()

Rotating a Secret

Using a Custom Lambda Function

A rotation schedule can be added to a Secret using a custom Lambda function:

require 'aws-cdk-lib'

fn = nil # AWSCDK::Lambda::Function

secret = AWSCDK::SecretsManager::Secret.new(self, "Secret")

secret.add_rotation_schedule("RotationSchedule", {
    rotation_lambda: fn,
    automatically_after: AWSCDK::Duration.days(15),
    rotate_immediately_on_update: false,
})

Note: The required permissions for Lambda to call SecretsManager and the other way round are automatically granted based on AWS Documentation as long as the Lambda is not imported.

See Overview of the Lambda Rotation Function on how to implement a Lambda Rotation Function.

Using a Hosted Lambda Function

Use the hosted_rotation prop to rotate a secret with a hosted Lambda function:

secret = AWSCDK::SecretsManager::Secret.new(self, "Secret")

secret.add_rotation_schedule("RotationSchedule", {
    hosted_rotation: AWSCDK::SecretsManager::HostedRotation.mysql_single_user,
})

Hosted rotation is available for secrets representing credentials for MySQL, PostgreSQL, Oracle, MariaDB, SQLServer, Redshift and MongoDB (both for the single and multi user schemes).

When deployed in a VPC, the hosted rotation implements ec2.IConnectable:

my_vpc = nil # AWSCDK::EC2::IVPC
db_connections = nil # AWSCDK::EC2::Connections
secret = nil # AWSCDK::SecretsManager::Secret


my_hosted_rotation = AWSCDK::SecretsManager::HostedRotation.mysql_single_user({vpc: my_vpc})
secret.add_rotation_schedule("RotationSchedule", {hosted_rotation: my_hosted_rotation})
db_connections.allow_default_port_from(my_hosted_rotation)

Use the exclude_characters option to customize the characters excluded from the generated password when it is rotated. By default, the rotation excludes the same characters as the ones excluded for the secret. If none are defined then the following set is used: % +~#$&*()|[]{}:;<>?!'/@"`.

See also Automating secret creation in AWS CloudFormation.

Rotating database credentials

Define a SecretRotation to rotate database credentials:

my_secret = nil # AWSCDK::SecretsManager::Secret
my_database = nil # AWSCDK::EC2::IConnectable
my_vpc = nil # AWSCDK::EC2::VPC


AWSCDK::SecretsManager::SecretRotation.new(self, "SecretRotation", {
    application: AWSCDK::SecretsManager::SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER,
     # MySQL single user scheme
    secret: my_secret,
    target: my_database,
     # a Connectable
    vpc: my_vpc,
     # The VPC where the secret rotation application will be deployed
    exclude_characters: " %+:;{}",
})

The secret must be a JSON string with the following format:

{
  "engine": "<required: database engine>",
  "host": "<required: instance host name>",
  "username": "<required: username>",
  "password": "<required: password>",
  "dbname": "<optional: database name>",
  "port": "<optional: if not specified, default port will be used>",
  "masterarn": "<required for multi user rotation: the arn of the master secret which will be used to create users/change passwords>"
}

For the multi user scheme, a master_secret must be specified:

my_user_secret = nil # AWSCDK::SecretsManager::Secret
my_master_secret = nil # AWSCDK::SecretsManager::Secret
my_database = nil # AWSCDK::EC2::IConnectable
my_vpc = nil # AWSCDK::EC2::VPC


AWSCDK::SecretsManager::SecretRotation.new(self, "SecretRotation", {
    application: AWSCDK::SecretsManager::SecretRotationApplication.MYSQL_ROTATION_MULTI_USER,
    secret: my_user_secret,
     # The secret that will be rotated
    master_secret: my_master_secret,
     # The secret used for the rotation
    target: my_database,
    vpc: my_vpc,
})

By default, any stack updates will cause AWS Secrets Manager to rotate a secret immediately. To prevent this behavior and wait until the next scheduled rotation window specified via the automatically_after property, set the rotate_immediately_on_update property to false:

my_user_secret = nil # AWSCDK::SecretsManager::Secret
my_master_secret = nil # AWSCDK::SecretsManager::Secret
my_database = nil # AWSCDK::EC2::IConnectable
my_vpc = nil # AWSCDK::EC2::VPC


AWSCDK::SecretsManager::SecretRotation.new(self, "SecretRotation", {
    application: AWSCDK::SecretsManager::SecretRotationApplication.MYSQL_ROTATION_MULTI_USER,
    secret: my_user_secret,
     # The secret that will be rotated
    master_secret: my_master_secret,
     # The secret used for the rotation
    target: my_database,
    vpc: my_vpc,
    automatically_after: AWSCDK::Duration.days(7),
    rotate_immediately_on_update: false,
})

See also aws-rds where credentials generation and rotation is integrated.

Importing Secrets

Existing secrets can be imported by ARN, name, and other attributes (including the KMS key used to encrypt the secret). Secrets imported by name should use the short-form of the name (without the SecretsManager-provided suffix); the secret name must exist in the same account and region as the stack. Importing by name makes it easier to reference secrets created in different regions, each with their own suffix and ARN.

secret_complete_arn = "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret-f3gDy9"
secret_partial_arn = "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret" # No Secrets Manager suffix
encryption_key = AWSCDK::KMS::Key.from_key_arn(self, "MyEncKey", "arn:aws:kms:eu-west-1:111111111111:key/21c4b39b-fde2-4273-9ac0-d9bb5c0d0030")
my_secret_from_complete_arn = AWSCDK::SecretsManager::Secret.from_secret_complete_arn(self, "SecretFromCompleteArn", secret_complete_arn)
my_secret_from_partial_arn = AWSCDK::SecretsManager::Secret.from_secret_partial_arn(self, "SecretFromPartialArn", secret_partial_arn)
my_secret_from_name = AWSCDK::SecretsManager::Secret.from_secret_name_v2(self, "SecretFromName", "MySecret")
my_secret_from_attrs = AWSCDK::SecretsManager::Secret.from_secret_attributes(self, "SecretFromAttributes", {
    secret_complete_arn: secret_complete_arn,
    encryption_key: encryption_key,
})

Replicating secrets

Secrets can be replicated to multiple regions by specifying replica_regions:

my_key = nil # AWSCDK::KMS::Key

AWSCDK::SecretsManager::Secret.new(self, "Secret", {
    replica_regions: [
        {
            region: "eu-west-1",
        },
        {
            region: "eu-central-1",
            encryption_key: my_key,
        },
    ],
})

Alternatively, use add_replica_region():

secret = AWSCDK::SecretsManager::Secret.new(self, "Secret")
secret.add_replica_region("eu-west-1")

Creating JSON Secrets

Sometimes it is necessary to create a secret in SecretsManager that contains a JSON object. For example:

{
  "username": "myUsername",
  "database": "foo",
  "password": "mypassword"
}

In order to create this type of secret, use the secret_object_value input prop.

stack = nil # AWSCDK::Stack
user = AWSCDK::IAM::User.new(self, "User")
access_key = AWSCDK::IAM::AccessKey.new(self, "AccessKey", {user: user})

AWSCDK::SecretsManager::Secret.new(self, "Secret", {
    secret_object_value: {
        username: AWSCDK::SecretValue.unsafe_plain_text(user.user_name),
        database: AWSCDK::SecretValue.unsafe_plain_text("foo"),
        password: access_key.secret_access_key,
    },
})

In this case both the username and database are not a Secret so SecretValue.unsafePlainText needs to be used. This means that they will be rendered as plain text in the template, but in this case neither of those are actual "secrets".

API Reference

Classes 13

CfnResourcePolicyAttaches a resource-based permission policy to a secret. CfnRotationScheduleConfigure the rotation schedule and Lambda rotation function for a secret. For more inform CfnSecretCreates a new secret. CfnSecretTargetAttachmentThe `AWS::SecretsManager::SecretTargetAttachment` resource completes the final link betwee HostedRotationA hosted rotation. HostedRotationTypeHosted rotation type. ResourcePolicyResource Policy for SecretsManager Secrets. RotationScheduleA rotation schedule. SecretCreates a new secret in AWS SecretsManager. SecretRotationSecret rotation for a service or database. SecretRotationApplicationA secret rotation serverless application. SecretStringValueBeta1An experimental class used to specify an initial secret value for a Secret. SecretTargetAttachmentAn attached secret.

Interfaces 21

AttachedSecretOptionsOptions to add a secret attachment to a secret. CfnResourcePolicyPropsProperties for defining a `CfnResourcePolicy`. CfnRotationSchedulePropsProperties for defining a `CfnRotationSchedule`. CfnSecretPropsProperties for defining a `CfnSecret`. CfnSecretTargetAttachmentPropsProperties for defining a `CfnSecretTargetAttachment`. ISecretA secret in AWS Secrets Manager. ISecretAttachmentTargetA secret attachment target. ISecretTargetAttachment MultiUserHostedRotationOptionsMulti user hosted rotation options. ReplicaRegionSecret replica region. ResourcePolicyPropsConstruction properties for a ResourcePolicy. RotationScheduleOptionsOptions to add a rotation schedule to a secret. RotationSchedulePropsConstruction properties for a RotationSchedule. SecretAttachmentTargetPropsAttachment target specifications. SecretAttributesAttributes required to import an existing secret into the Stack. SecretPropsThe properties required to create a new secret in AWS Secrets Manager. SecretRotationApplicationOptionsOptions for a SecretRotationApplication. SecretRotationPropsConstruction properties for a SecretRotation. SecretStringGeneratorConfiguration to generate secrets such as passwords automatically. SecretTargetAttachmentPropsConstruction properties for an AttachedSecret. SingleUserHostedRotationOptionsSingle user hosted rotation options.

Enums 1

AttachmentTargetTypeThe type of service or database that's being associated with the secret.