import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
In order to have SecretsManager generate a new secret value automatically, you can get started with the following:
The Secret
construct does not allow specifying the SecretString
property
of the AWS::SecretsManager::Secret
resource (as this will almost always
lead to the secret being surfaced in plain text and possibly committed to
your source control).
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:
const secret = secretsmanager.Secret.fromSecretAttributes(scope, '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,
});
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
, that removing a secret will fail.
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.grantUpdate
method, depending on your need:
const role = new iam.Role(stack, 'SomeRole', { assumedBy: new iam.AccountRootPrincipal() });
const secret = new secretsmanager.Secret(stack, 'Secret');
secret.grantRead(role);
secret.grantWrite(role);
If, as in the following example, your secret was created with a KMS key:
const key = new kms.Key(stack, 'KMS');
const secret = new secretsmanager.Secret(stack, 'Secret', { 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.
A rotation schedule can be added to a Secret using a custom Lambda function:
const fn = new lambda.Function(...);
const secret = new secretsmanager.Secret(this, 'Secret');
secret.addRotationSchedule('RotationSchedule', {
rotationLambda: fn,
automaticallyAfter: Duration.days(15)
});
See Overview of the Lambda Rotation Function on how to implement a Lambda Rotation Function.
Use the hostedRotation
prop to rotate a secret with a hosted Lambda function:
const secret = new secretsmanager.Secret(this, 'Secret');
secret.addRotationSchedule('RotationSchedule', {
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
:
const myHostedRotation = secretsmanager.HostedRotation.mysqlSingleUser({ vpc: myVpc });
secret.addRotationSchedule('RotationSchedule', { hostedRotation: myHostedRotation });
dbConnections.allowDefaultPortFrom(hostedRotation);
See also Automating secret creation in AWS CloudFormation.
Define a SecretRotation
to rotate database credentials:
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
});
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 masterSecret
must be specified:
new secretsmanager.SecretRotation(stack, '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,
});
See also aws-rds where credentials generation and rotation is integrated.
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 suffx); 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.
import * as kms from '@aws-cdk/aws-kms';
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(stack, 'MyEncKey', 'arn:aws:kms:eu-west-1:111111111111:key/21c4b39b-fde2-4273-9ac0-d9bb5c0d0030');
const mySecretFromCompleteArn = secretsmanager.Secret.fromSecretCompleteArn(stack, 'SecretFromCompleteArn', secretCompleteArn);
const mySecretFromPartialArn = secretsmanager.Secret.fromSecretPartialArn(stack, 'SecretFromPartialArn', secretPartialArn);
const mySecretFromName = secretsmanager.Secret.fromSecretNameV2(stack, 'SecretFromName', 'MySecret')
const mySecretFromAttrs = secretsmanager.Secret.fromSecretAttributes(stack, 'SecretFromAttributes', {
secretCompleteArn,
encryptionKey,
});
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.