Skip to content
v2.273.0

AWS Secrets Manager Construct Library ​

ts
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
python
import aws_cdk.aws_secretsmanager as secretsmanager
java
import software.amazon.awscdk.services.secretsmanager.*;
csharp
using Amazon.CDK.AWS.SecretsManager;
go
import secretsmanager "github.com/aws/aws-cdk-go/awscdk"

Create a new Secret in a Stack ​

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

ts
declare const vpc: ec2.IVpc;

const instance1 = new rds.DatabaseInstance(this, "PostgresInstance1", {
  engine: rds.DatabaseInstanceEngine.POSTGRES,
  // Generate the secret with admin username `postgres` and random password
  credentials: rds.Credentials.fromGeneratedSecret('postgres'),
  vpc
});
// Templated secret with username and password fields
const templatedSecret = new secretsmanager.Secret(this, 'TemplatedSecret', {
  generateSecretString: {
    secretStringTemplate: JSON.stringify({ username: 'postgres' }),
    generateStringKey: 'password',
    excludeCharacters: '/@"',
  },
});
// Using the templated secret as credentials
const instance2 = new rds.DatabaseInstance(this, "PostgresInstance2", {
  engine: rds.DatabaseInstanceEngine.POSTGRES,
  credentials: {
    username: templatedSecret.secretValueFromJson('username').toString(),
    password: templatedSecret.secretValueFromJson('password')
  },
  vpc
});
python
# vpc: ec2.IVpc


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


DatabaseInstance instance1 = DatabaseInstance.Builder.create(this, "PostgresInstance1")
        .engine(DatabaseInstanceEngine.POSTGRES)
        // Generate the secret with admin username `postgres` and random password
        .credentials(Credentials.fromGeneratedSecret("postgres"))
        .vpc(vpc)
        .build();
// Templated secret with username and password fields
Secret templatedSecret = Secret.Builder.create(this, "TemplatedSecret")
        .generateSecretString(SecretStringGenerator.builder()
                .secretStringTemplate(JSON.stringify(Map.of("username", "postgres")))
                .generateStringKey("password")
                .excludeCharacters("/@\"")
                .build())
        .build();
// Using the templated secret as credentials
DatabaseInstance instance2 = DatabaseInstance.Builder.create(this, "PostgresInstance2")
        .engine(DatabaseInstanceEngine.POSTGRES)
        .credentials(Map.of(
                "username", templatedSecret.secretValueFromJson("username").toString(),
                "password", templatedSecret.secretValueFromJson("password")))
        .vpc(vpc)
        .build();
csharp
IVpc vpc;


var instance1 = new DatabaseInstance(this, "PostgresInstance1", new DatabaseInstanceProps {
    Engine = DatabaseInstanceEngine.POSTGRES,
    // Generate the secret with admin username `postgres` and random password
    Credentials = Credentials.FromGeneratedSecret("postgres"),
    Vpc = vpc
});
// Templated secret with username and password fields
var templatedSecret = new Secret(this, "TemplatedSecret", new SecretProps {
    GenerateSecretString = new SecretStringGenerator {
        SecretStringTemplate = JSON.Stringify(new Dictionary<string, string> { { "username", "postgres" } }),
        GenerateStringKey = "password",
        ExcludeCharacters = "/@\""
    }
});
// Using the templated secret as credentials
var instance2 = new DatabaseInstance(this, "PostgresInstance2", new DatabaseInstanceProps {
    Engine = DatabaseInstanceEngine.POSTGRES,
    Credentials = new Dictionary<string, object> {
        { "username", templatedSecret.SecretValueFromJson("username").ToString() },
        { "password", templatedSecret.SecretValueFromJson("password") }
    },
    Vpc = vpc
});
go
var vpc IVpc


instance1 := rds.NewDatabaseInstance(this, jsii.String("PostgresInstance1"), &DatabaseInstanceProps{
	Engine: rds.DatabaseInstanceEngine_POSTGRES(),
	// Generate the secret with admin username `postgres` and random password
	Credentials: rds.Credentials_FromGeneratedSecret(jsii.String("postgres")),
	Vpc: Vpc,
})
// Templated secret with username and password fields
templatedSecret := secretsmanager.NewSecret(this, jsii.String("TemplatedSecret"), &SecretProps{
	GenerateSecretString: &SecretStringGenerator{
		SecretStringTemplate: jSON.stringify(map[string]*string{
			"username": jsii.String("postgres"),
		}),
		GenerateStringKey: jsii.String("password"),
		ExcludeCharacters: jsii.String("/@\""),
	},
})
// Using the templated secret as credentials
instance2 := rds.NewDatabaseInstance(this, jsii.String("PostgresInstance2"), &DatabaseInstanceProps{
	Engine: rds.DatabaseInstanceEngine_POSTGRES(),
	Credentials: map[string]interface{}{
		"username": templatedSecret.secretValueFromJson(jsii.String("username")).toString(),
		"password": templatedSecret.secretValueFromJson(jsii.String("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:

ts
declare const encryptionKey: kms.Key;
const secret = secretsmanager.Secret.fromSecretAttributes(this, 'ImportedSecret', {
  secretArn: 'arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>',
  // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key:
  encryptionKey,
});
python
# encryption_key: kms.Key

secret = secretsmanager.Secret.from_secret_attributes(self, "ImportedSecret",
    secret_arn="arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>",
    # If the secret is encrypted using a KMS-hosted CMK, either import or reference that key:
    encryption_key=encryption_key
)
java
Key encryptionKey;

ISecret secret = Secret.fromSecretAttributes(this, "ImportedSecret", SecretAttributes.builder()
        .secretArn("arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>")
        // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key:
        .encryptionKey(encryptionKey)
        .build());
csharp
Key encryptionKey;

var secret = Secret.FromSecretAttributes(this, "ImportedSecret", new SecretAttributes {
    SecretArn = "arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>",
    // If the secret is encrypted using a KMS-hosted CMK, either import or reference that key:
    EncryptionKey = encryptionKey
});
go
var encryptionKey Key

secret := secretsmanager.Secret_FromSecretAttributes(this, jsii.String("ImportedSecret"), &SecretAttributes{
	SecretArn: jsii.String("arn:aws:secretsmanager:<region>:<account-id-number>:secret:<secret-name>-<random-6-characters>"),
	// If the secret is encrypted using a KMS-hosted CMK, either import or reference that key:
	EncryptionKey: EncryptionKey,
})

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:

ts
const role = new iam.Role(this, 'SomeRole', { assumedBy: new iam.AccountRootPrincipal() });
const secret = new secretsmanager.Secret(this, 'Secret');
secret.grantRead(role);
secret.grantWrite(role);
python
role = iam.Role(self, "SomeRole", assumed_by=iam.AccountRootPrincipal())
secret = secretsmanager.Secret(self, "Secret")
secret.grant_read(role)
secret.grant_write(role)
java
Role role = Role.Builder.create(this, "SomeRole").assumedBy(new AccountRootPrincipal()).build();
Secret secret = new Secret(this, "Secret");
secret.grantRead(role);
secret.grantWrite(role);
csharp
var role = new Role(this, "SomeRole", new RoleProps { AssumedBy = new AccountRootPrincipal() });
var secret = new Secret(this, "Secret");
secret.GrantRead(role);
secret.GrantWrite(role);
go
role := iam.NewRole(this, jsii.String("SomeRole"), &RoleProps{
	AssumedBy: iam.NewAccountRootPrincipal(),
})
secret := secretsmanager.NewSecret(this, jsii.String("Secret"))
secret.grantRead(role)
secret.grantWrite(role)

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

ts
declare const role: iam.Role;
const key = new kms.Key(this, 'KMS');
const secret = new secretsmanager.Secret(this, 'Secret', { encryptionKey: key });
secret.grantRead(role);
secret.grantWrite(role);
python
# role: iam.Role

key = kms.Key(self, "KMS")
secret = secretsmanager.Secret(self, "Secret", encryption_key=key)
secret.grant_read(role)
secret.grant_write(role)
java
Role role;

Key key = new Key(this, "KMS");
Secret secret = Secret.Builder.create(this, "Secret").encryptionKey(key).build();
secret.grantRead(role);
secret.grantWrite(role);
csharp
Role role;

var key = new Key(this, "KMS");
var secret = new Secret(this, "Secret", new SecretProps { EncryptionKey = key });
secret.GrantRead(role);
secret.GrantWrite(role);
go
var role Role

key := kms.NewKey(this, jsii.String("KMS"))
secret := secretsmanager.NewSecret(this, jsii.String("Secret"), &SecretProps{
	EncryptionKey: key,
})
secret.grantRead(role)
secret.grantWrite(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:

ts
const otherAccount = new iam.AccountPrincipal('1234');
const key = new kms.Key(this, 'KMS');
const secret = new secretsmanager.Secret(this, 'Secret', { encryptionKey: key });
secret.grantRead(otherAccount);
python
other_account = iam.AccountPrincipal("1234")
key = kms.Key(self, "KMS")
secret = secretsmanager.Secret(self, "Secret", encryption_key=key)
secret.grant_read(other_account)
java
AccountPrincipal otherAccount = new AccountPrincipal("1234");
Key key = new Key(this, "KMS");
Secret secret = Secret.Builder.create(this, "Secret").encryptionKey(key).build();
secret.grantRead(otherAccount);
csharp
var otherAccount = new AccountPrincipal("1234");
var key = new Key(this, "KMS");
var secret = new Secret(this, "Secret", new SecretProps { EncryptionKey = key });
secret.GrantRead(otherAccount);
go
otherAccount := iam.NewAccountPrincipal(jsii.String("1234"))
key := kms.NewKey(this, jsii.String("KMS"))
secret := secretsmanager.NewSecret(this, jsii.String("Secret"), &SecretProps{
	EncryptionKey: key,
})
secret.grantRead(otherAccount)

Rotating a Secret ​

Using a Custom Lambda Function ​

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

ts
import * as lambda from 'aws-cdk-lib/aws-lambda';

declare const fn: lambda.Function;
const secret = new secretsmanager.Secret(this, 'Secret');

secret.addRotationSchedule('RotationSchedule', {
  rotationLambda: fn,
  automaticallyAfter: Duration.days(15),
  rotateImmediatelyOnUpdate: false, // default is true
});
python
import aws_cdk.aws_lambda as lambda_

# fn: lambda.Function

secret = secretsmanager.Secret(self, "Secret")

secret.add_rotation_schedule("RotationSchedule",
    rotation_lambda=fn,
    automatically_after=Duration.days(15),
    rotate_immediately_on_update=False
)
java
import software.amazon.awscdk.services.lambda.*;

Function fn;

Secret secret = new Secret(this, "Secret");

secret.addRotationSchedule("RotationSchedule", RotationScheduleOptions.builder()
        .rotationLambda(fn)
        .automaticallyAfter(Duration.days(15))
        .rotateImmediatelyOnUpdate(false)
        .build());
csharp
using Amazon.CDK.AWS.Lambda;

Function fn;

var secret = new Secret(this, "Secret");

secret.AddRotationSchedule("RotationSchedule", new RotationScheduleOptions {
    RotationLambda = fn,
    AutomaticallyAfter = Duration.Days(15),
    RotateImmediatelyOnUpdate = false
});
go
import lambda "github.com/aws/aws-cdk-go/awscdk"

var fn Function

secret := secretsmanager.NewSecret(this, jsii.String("Secret"))

secret.addRotationSchedule(jsii.String("RotationSchedule"), &RotationScheduleOptions{
	RotationLambda: fn,
	AutomaticallyAfter: awscdk.Duration_Days(jsii.Number(15)),
	RotateImmediatelyOnUpdate: jsii.Boolean(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 hostedRotation prop to rotate a secret with a hosted Lambda function:

ts
const secret = new secretsmanager.Secret(this, 'Secret');

secret.addRotationSchedule('RotationSchedule', {
  hostedRotation: secretsmanager.HostedRotation.mysqlSingleUser(),
});
python
secret = secretsmanager.Secret(self, "Secret")

secret.add_rotation_schedule("RotationSchedule",
    hosted_rotation=secretsmanager.HostedRotation.mysql_single_user()
)
java
Secret secret = new Secret(this, "Secret");

secret.addRotationSchedule("RotationSchedule", RotationScheduleOptions.builder()
        .hostedRotation(HostedRotation.mysqlSingleUser())
        .build());
csharp
var secret = new Secret(this, "Secret");

secret.AddRotationSchedule("RotationSchedule", new RotationScheduleOptions {
    HostedRotation = HostedRotation.MysqlSingleUser()
});
go
secret := secretsmanager.NewSecret(this, jsii.String("Secret"))

secret.addRotationSchedule(jsii.String("RotationSchedule"), &RotationScheduleOptions{
	HostedRotation: secretsmanager.HostedRotation_MysqlSingleUser(),
})

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:

ts
declare const myVpc: ec2.IVpc;
declare const dbConnections: ec2.Connections;
declare const secret: secretsmanager.Secret;

const myHostedRotation = secretsmanager.HostedRotation.mysqlSingleUser({ vpc: myVpc });
secret.addRotationSchedule('RotationSchedule', { hostedRotation: myHostedRotation });
dbConnections.allowDefaultPortFrom(myHostedRotation);
python
# my_vpc: ec2.IVpc
# db_connections: ec2.Connections
# secret: secretsmanager.Secret


my_hosted_rotation = 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)
java
IVpc myVpc;
Connections dbConnections;
Secret secret;


HostedRotation myHostedRotation = HostedRotation.mysqlSingleUser(SingleUserHostedRotationOptions.builder().vpc(myVpc).build());
secret.addRotationSchedule("RotationSchedule", RotationScheduleOptions.builder().hostedRotation(myHostedRotation).build());
dbConnections.allowDefaultPortFrom(myHostedRotation);
csharp
IVpc myVpc;
Connections dbConnections;
Secret secret;


var myHostedRotation = HostedRotation.MysqlSingleUser(new SingleUserHostedRotationOptions { Vpc = myVpc });
secret.AddRotationSchedule("RotationSchedule", new RotationScheduleOptions { HostedRotation = myHostedRotation });
dbConnections.AllowDefaultPortFrom(myHostedRotation);
go
var myVpc IVpc
var dbConnections Connections
var secret Secret


myHostedRotation := secretsmanager.HostedRotation_MysqlSingleUser(&SingleUserHostedRotationOptions{
	Vpc: myVpc,
})
secret.addRotationSchedule(jsii.String("RotationSchedule"), &RotationScheduleOptions{
	HostedRotation: myHostedRotation,
})
dbConnections.AllowDefaultPortFrom(myHostedRotation)

Use the excludeCharacters 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:

ts
declare const mySecret: secretsmanager.Secret;
declare const myDatabase: ec2.IConnectable;
declare const myVpc: ec2.Vpc;

new secretsmanager.SecretRotation(this, 'SecretRotation', {
  application: secretsmanager.SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER, // MySQL single user scheme
  secret: mySecret,
  target: myDatabase, // a Connectable
  vpc: myVpc, // The VPC where the secret rotation application will be deployed
  excludeCharacters: ' %+:;{}', // characters to never use when generating new passwords;
                                // by default, no characters are excluded,
                                // which might cause problems with some services, like DMS
});
python
# my_secret: secretsmanager.Secret
# my_database: ec2.IConnectable
# my_vpc: ec2.Vpc


secretsmanager.SecretRotation(self, "SecretRotation",
    application=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=" %+:;{}"
)
java
Secret mySecret;
IConnectable myDatabase;
Vpc myVpc;


SecretRotation.Builder.create(this, "SecretRotation")
        .application(SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER) // MySQL single user scheme
        .secret(mySecret)
        .target(myDatabase) // a Connectable
        .vpc(myVpc) // The VPC where the secret rotation application will be deployed
        .excludeCharacters(" %+:;{}")
        .build();
csharp
Secret mySecret;
IConnectable myDatabase;
Vpc myVpc;


new SecretRotation(this, "SecretRotation", new SecretRotationProps {
    Application = SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER,  // MySQL single user scheme
    Secret = mySecret,
    Target = myDatabase,  // a Connectable
    Vpc = myVpc,  // The VPC where the secret rotation application will be deployed
    ExcludeCharacters = " %+:;{}"
});
go
var mySecret Secret
var myDatabase IConnectable
var myVpc Vpc


secretsmanager.NewSecretRotation(this, jsii.String("SecretRotation"), &SecretRotationProps{
	Application: secretsmanager.SecretRotationApplication_MYSQL_ROTATION_SINGLE_USER(),
	 // MySQL single user scheme
	Secret: mySecret,
	Target: myDatabase,
	 // a Connectable
	Vpc: myVpc,
	 // The VPC where the secret rotation application will be deployed
	ExcludeCharacters: jsii.String(" %+:;{}"),
})

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

json
{
  "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 masterSecret must be specified:

ts
declare const myUserSecret: secretsmanager.Secret;
declare const myMasterSecret: secretsmanager.Secret;
declare const myDatabase: ec2.IConnectable;
declare const myVpc: ec2.Vpc;

new secretsmanager.SecretRotation(this, 'SecretRotation', {
  application: secretsmanager.SecretRotationApplication.MYSQL_ROTATION_MULTI_USER,
  secret: myUserSecret, // The secret that will be rotated
  masterSecret: myMasterSecret, // The secret used for the rotation
  target: myDatabase,
  vpc: myVpc,
});
python
# my_user_secret: secretsmanager.Secret
# my_master_secret: secretsmanager.Secret
# my_database: ec2.IConnectable
# my_vpc: ec2.Vpc


secretsmanager.SecretRotation(self, "SecretRotation",
    application=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
)
java
Secret myUserSecret;
Secret myMasterSecret;
IConnectable myDatabase;
Vpc myVpc;


SecretRotation.Builder.create(this, "SecretRotation")
        .application(SecretRotationApplication.MYSQL_ROTATION_MULTI_USER)
        .secret(myUserSecret) // The secret that will be rotated
        .masterSecret(myMasterSecret) // The secret used for the rotation
        .target(myDatabase)
        .vpc(myVpc)
        .build();
csharp
Secret myUserSecret;
Secret myMasterSecret;
IConnectable myDatabase;
Vpc myVpc;


new SecretRotation(this, "SecretRotation", new SecretRotationProps {
    Application = SecretRotationApplication.MYSQL_ROTATION_MULTI_USER,
    Secret = myUserSecret,  // The secret that will be rotated
    MasterSecret = myMasterSecret,  // The secret used for the rotation
    Target = myDatabase,
    Vpc = myVpc
});
go
var myUserSecret Secret
var myMasterSecret Secret
var myDatabase IConnectable
var myVpc Vpc


secretsmanager.NewSecretRotation(this, jsii.String("SecretRotation"), &SecretRotationProps{
	Application: secretsmanager.SecretRotationApplication_MYSQL_ROTATION_MULTI_USER(),
	Secret: myUserSecret,
	 // The secret that will be rotated
	MasterSecret: myMasterSecret,
	 // The secret used for the rotation
	Target: myDatabase,
	Vpc: myVpc,
})

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 automaticallyAfter property, set the rotateImmediatelyOnUpdate property to false:

ts
declare const myUserSecret: secretsmanager.Secret;
declare const myMasterSecret: secretsmanager.Secret;
declare const myDatabase: ec2.IConnectable;
declare const myVpc: ec2.Vpc;

new secretsmanager.SecretRotation(this, 'SecretRotation', {
  application: secretsmanager.SecretRotationApplication.MYSQL_ROTATION_MULTI_USER,
  secret: myUserSecret, // The secret that will be rotated
  masterSecret: myMasterSecret, // The secret used for the rotation
  target: myDatabase,
  vpc: myVpc,
  automaticallyAfter: Duration.days(7),
  rotateImmediatelyOnUpdate: false,
});
python
# my_user_secret: secretsmanager.Secret
# my_master_secret: secretsmanager.Secret
# my_database: ec2.IConnectable
# my_vpc: ec2.Vpc


secretsmanager.SecretRotation(self, "SecretRotation",
    application=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=Duration.days(7),
    rotate_immediately_on_update=False
)
java
Secret myUserSecret;
Secret myMasterSecret;
IConnectable myDatabase;
Vpc myVpc;


SecretRotation.Builder.create(this, "SecretRotation")
        .application(SecretRotationApplication.MYSQL_ROTATION_MULTI_USER)
        .secret(myUserSecret) // The secret that will be rotated
        .masterSecret(myMasterSecret) // The secret used for the rotation
        .target(myDatabase)
        .vpc(myVpc)
        .automaticallyAfter(Duration.days(7))
        .rotateImmediatelyOnUpdate(false)
        .build();
csharp
Secret myUserSecret;
Secret myMasterSecret;
IConnectable myDatabase;
Vpc myVpc;


new SecretRotation(this, "SecretRotation", new SecretRotationProps {
    Application = SecretRotationApplication.MYSQL_ROTATION_MULTI_USER,
    Secret = myUserSecret,  // The secret that will be rotated
    MasterSecret = myMasterSecret,  // The secret used for the rotation
    Target = myDatabase,
    Vpc = myVpc,
    AutomaticallyAfter = Duration.Days(7),
    RotateImmediatelyOnUpdate = false
});
go
var myUserSecret Secret
var myMasterSecret Secret
var myDatabase IConnectable
var myVpc Vpc


secretsmanager.NewSecretRotation(this, jsii.String("SecretRotation"), &SecretRotationProps{
	Application: secretsmanager.SecretRotationApplication_MYSQL_ROTATION_MULTI_USER(),
	Secret: myUserSecret,
	 // The secret that will be rotated
	MasterSecret: myMasterSecret,
	 // The secret used for the rotation
	Target: myDatabase,
	Vpc: myVpc,
	AutomaticallyAfter: awscdk.Duration_Days(jsii.Number(7)),
	RotateImmediatelyOnUpdate: jsii.Boolean(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.

ts
const secretCompleteArn = 'arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret-f3gDy9';
const secretPartialArn = 'arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret'; // No Secrets Manager suffix
const encryptionKey = kms.Key.fromKeyArn(this, 'MyEncKey', 'arn:aws:kms:eu-west-1:111111111111:key/21c4b39b-fde2-4273-9ac0-d9bb5c0d0030');
const mySecretFromCompleteArn = secretsmanager.Secret.fromSecretCompleteArn(this, 'SecretFromCompleteArn', secretCompleteArn);
const mySecretFromPartialArn = secretsmanager.Secret.fromSecretPartialArn(this, 'SecretFromPartialArn', secretPartialArn);
const mySecretFromName = secretsmanager.Secret.fromSecretNameV2(this, 'SecretFromName', 'MySecret')
const mySecretFromAttrs = secretsmanager.Secret.fromSecretAttributes(this, 'SecretFromAttributes', {
  secretCompleteArn,
  encryptionKey,
});
python
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 = 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 = secretsmanager.Secret.from_secret_complete_arn(self, "SecretFromCompleteArn", secret_complete_arn)
my_secret_from_partial_arn = secretsmanager.Secret.from_secret_partial_arn(self, "SecretFromPartialArn", secret_partial_arn)
my_secret_from_name = secretsmanager.Secret.from_secret_name_v2(self, "SecretFromName", "MySecret")
my_secret_from_attrs = secretsmanager.Secret.from_secret_attributes(self, "SecretFromAttributes",
    secret_complete_arn=secret_complete_arn,
    encryption_key=encryption_key
)
java
String secretCompleteArn = "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret-f3gDy9";
String secretPartialArn = "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret"; // No Secrets Manager suffix
IKey encryptionKey = Key.fromKeyArn(this, "MyEncKey", "arn:aws:kms:eu-west-1:111111111111:key/21c4b39b-fde2-4273-9ac0-d9bb5c0d0030");
ISecret mySecretFromCompleteArn = Secret.fromSecretCompleteArn(this, "SecretFromCompleteArn", secretCompleteArn);
ISecret mySecretFromPartialArn = Secret.fromSecretPartialArn(this, "SecretFromPartialArn", secretPartialArn);
ISecret mySecretFromName = Secret.fromSecretNameV2(this, "SecretFromName", "MySecret");
ISecret mySecretFromAttrs = Secret.fromSecretAttributes(this, "SecretFromAttributes", SecretAttributes.builder()
        .secretCompleteArn(secretCompleteArn)
        .encryptionKey(encryptionKey)
        .build());
csharp
var secretCompleteArn = "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret-f3gDy9";
var secretPartialArn = "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret"; // No Secrets Manager suffix
var encryptionKey = Key.FromKeyArn(this, "MyEncKey", "arn:aws:kms:eu-west-1:111111111111:key/21c4b39b-fde2-4273-9ac0-d9bb5c0d0030");
var mySecretFromCompleteArn = Secret.FromSecretCompleteArn(this, "SecretFromCompleteArn", secretCompleteArn);
var mySecretFromPartialArn = Secret.FromSecretPartialArn(this, "SecretFromPartialArn", secretPartialArn);
var mySecretFromName = Secret.FromSecretNameV2(this, "SecretFromName", "MySecret");
var mySecretFromAttrs = Secret.FromSecretAttributes(this, "SecretFromAttributes", new SecretAttributes {
    SecretCompleteArn = secretCompleteArn,
    EncryptionKey = encryptionKey
});
go
secretCompleteArn := "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret-f3gDy9"
secretPartialArn := "arn:aws:secretsmanager:eu-west-1:111111111111:secret:MySecret" // No Secrets Manager suffix
encryptionKey := kms.Key_FromKeyArn(this, jsii.String("MyEncKey"), jsii.String("arn:aws:kms:eu-west-1:111111111111:key/21c4b39b-fde2-4273-9ac0-d9bb5c0d0030"))
mySecretFromCompleteArn := secretsmanager.Secret_FromSecretCompleteArn(this, jsii.String("SecretFromCompleteArn"), secretCompleteArn)
mySecretFromPartialArn := secretsmanager.Secret_FromSecretPartialArn(this, jsii.String("SecretFromPartialArn"), secretPartialArn)
mySecretFromName := secretsmanager.Secret_FromSecretNameV2(this, jsii.String("SecretFromName"), jsii.String("MySecret"))
mySecretFromAttrs := secretsmanager.Secret_FromSecretAttributes(this, jsii.String("SecretFromAttributes"), &SecretAttributes{
	SecretCompleteArn: jsii.String(SecretCompleteArn),
	EncryptionKey: EncryptionKey,
})

Replicating secrets ​

Secrets can be replicated to multiple regions by specifying replicaRegions:

ts
declare const myKey: kms.Key;
new secretsmanager.Secret(this, 'Secret', {
  replicaRegions: [
    {
      region: 'eu-west-1',
    },
    {
      region: 'eu-central-1',
      encryptionKey: myKey,
    }
  ]
});
python
# my_key: kms.Key

secretsmanager.Secret(self, "Secret",
    replica_regions=[secretsmanager.ReplicaRegion(
        region="eu-west-1"
    ), secretsmanager.ReplicaRegion(
        region="eu-central-1",
        encryption_key=my_key
    )
    ]
)
java
Key myKey;

Secret.Builder.create(this, "Secret")
        .replicaRegions(List.of(ReplicaRegion.builder()
                .region("eu-west-1")
                .build(), ReplicaRegion.builder()
                .region("eu-central-1")
                .encryptionKey(myKey)
                .build()))
        .build();
csharp
Key myKey;

new Secret(this, "Secret", new SecretProps {
    ReplicaRegions = new [] { new ReplicaRegion {
        Region = "eu-west-1"
    }, new ReplicaRegion {
        Region = "eu-central-1",
        EncryptionKey = myKey
    } }
});
go
var myKey Key

secretsmanager.NewSecret(this, jsii.String("Secret"), &SecretProps{
	ReplicaRegions: []ReplicaRegion{
		&ReplicaRegion{
			Region: jsii.String("eu-west-1"),
		},
		&ReplicaRegion{
			Region: jsii.String("eu-central-1"),
			EncryptionKey: myKey,
		},
	},
})

Alternatively, use addReplicaRegion():

ts
const secret = new secretsmanager.Secret(this, 'Secret');
secret.addReplicaRegion('eu-west-1');
python
secret = secretsmanager.Secret(self, "Secret")
secret.add_replica_region("eu-west-1")
java
Secret secret = new Secret(this, "Secret");
secret.addReplicaRegion("eu-west-1");
csharp
var secret = new Secret(this, "Secret");
secret.AddReplicaRegion("eu-west-1");
go
secret := secretsmanager.NewSecret(this, jsii.String("Secret"))
secret.AddReplicaRegion(jsii.String("eu-west-1"))

Creating JSON Secrets ​

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

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

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

ts
const user = new iam.User(this, 'User');
const accessKey = new iam.AccessKey(this, 'AccessKey', { user });
declare const stack: Stack;

new secretsmanager.Secret(this, 'Secret', {
  secretObjectValue: {
    username: SecretValue.unsafePlainText(user.userName),
    database: SecretValue.unsafePlainText('foo'),
    password: accessKey.secretAccessKey,
  },
})
python
# stack: Stack
user = iam.User(self, "User")
access_key = iam.AccessKey(self, "AccessKey", user=user)

secretsmanager.Secret(self, "Secret",
    secret_object_value={
        "username": SecretValue.unsafe_plain_text(user.user_name),
        "database": SecretValue.unsafe_plain_text("foo"),
        "password": access_key.secret_access_key
    }
)
java
Stack stack;
User user = new User(this, "User");
AccessKey accessKey = AccessKey.Builder.create(this, "AccessKey").user(user).build();

Secret.Builder.create(this, "Secret")
        .secretObjectValue(Map.of(
                "username", SecretValue.unsafePlainText(user.getUserName()),
                "database", SecretValue.unsafePlainText("foo"),
                "password", accessKey.getSecretAccessKey()))
        .build();
csharp
Stack stack;
var user = new User(this, "User");
var accessKey = new AccessKey(this, "AccessKey", new AccessKeyProps { User = user });

new Secret(this, "Secret", new SecretProps {
    SecretObjectValue = new Dictionary<string, SecretValue> {
        { "username", SecretValue.UnsafePlainText(user.UserName) },
        { "database", SecretValue.UnsafePlainText("foo") },
        { "password", accessKey.SecretAccessKey }
    }
});
go
var stack Stack
user := iam.NewUser(this, jsii.String("User"))
accessKey := iam.NewAccessKey(this, jsii.String("AccessKey"), &AccessKeyProps{
	User: User,
})

secretsmanager.NewSecret(this, jsii.String("Secret"), &SecretProps{
	SecretObjectValue: map[string]SecretValue{
		"username": awscdk.SecretValue_unsafePlainText(user.userName),
		"database": awscdk.SecretValue_unsafePlainText(jsii.String("foo")),
		"password": accessKey.secretAccessKey,
	},
})

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".

Types ​

NameKindSummary
ResourcePolicyConstruct (L2)Resource Policy for SecretsManager Secrets.
RotationScheduleConstruct (L2)A rotation schedule.
SecretConstruct (L2)Creates a new secret in AWS SecretsManager.
SecretTargetAttachmentConstruct (L2)An attached secret.
CfnResourcePolicyConstruct (L1)Attaches a resource-based permission policy to a secret.
CfnRotationScheduleConstruct (L1)Configure the rotation schedule and Lambda rotation function for a secret. For more information, see How rotation works .
CfnSecretConstruct (L1)Creates a new secret.
CfnSecretTargetAttachmentConstruct (L1)The AWS::SecretsManager::SecretTargetAttachment resource completes the final link between a Secrets Manager secret and the associated database by adding the database connection information to the secret JSON.
AttachedSecretOptionsStructOptions to add a secret attachment to a secret.
AttachmentTargetTypeEnumThe type of service or database that's being associated with the secret.
CfnResourcePolicyPropsStructProperties for defining a CfnResourcePolicy.
CfnRotationSchedule.ExternalSecretRotationMetadataItemPropertyStructThe metadata needed to successfully rotate a managed external secret.
CfnRotationSchedule.HostedRotationLambdaPropertyStructCreates a new Lambda rotation function based on one of the Secrets Manager rotation function templates .
CfnRotationSchedule.RotationRulesPropertyStructThe rotation schedule and window.
CfnRotationSchedulePropsStructProperties for defining a CfnRotationSchedule.
CfnSecret.GenerateSecretStringPropertyStructGenerates a random password.
CfnSecret.ReplicaRegionPropertyStructSpecifies a Region and the KmsKeyId for a replica secret.
CfnSecretPropsStructProperties for defining a CfnSecret.
CfnSecretTargetAttachmentPropsStructProperties for defining a CfnSecretTargetAttachment.
HostedRotationClassA hosted rotation.
HostedRotationTypeClassHosted rotation type.
ISecretInterfaceA secret in AWS Secrets Manager.
ISecretAttachmentTargetInterfaceA secret attachment target.
ISecretTargetAttachmentInterface
MultiUserHostedRotationOptionsStructMulti user hosted rotation options.
ReplicaRegionStructSecret replica region.
ResourcePolicyPropsStructConstruction properties for a ResourcePolicy.
RotationScheduleOptionsStructOptions to add a rotation schedule to a secret.
RotationSchedulePropsStructConstruction properties for a RotationSchedule.
SecretAttachmentTargetPropsStructAttachment target specifications.
SecretAttributesStructAttributes required to import an existing secret into the Stack.
SecretPropsStructThe properties required to create a new secret in AWS Secrets Manager.
SecretRotationConstructSecret rotation for a service or database.
SecretRotationApplicationClassA secret rotation serverless application.
SecretRotationApplicationOptionsStructOptions for a SecretRotationApplication.
SecretRotationPropsStructConstruction properties for a SecretRotation.
SecretStringGeneratorStructConfiguration to generate secrets such as passwords automatically.
SecretStringValueBeta1ClassAn experimental class used to specify an initial secret value for a Secret.
SecretTargetAttachmentPropsStructConstruction properties for an AttachedSecret.
SingleUserHostedRotationOptionsStructSingle user hosted rotation options.