Aws-cdk: [rds] Ability to choose name for database secrets

Created on 9 Jul 2020  路  6Comments  路  Source: aws/aws-cdk

Per documentation https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-rds.DatabaseInstance.html:
"By default, the master password will be generated and stored in AWS Secrets Manager with auto-generated description."

In my case during provisioning of DatabaseInstance, CDK generated a secret with a name = LogicalId from CFN template. Would be nice to be able to set a name for a secret which will be generated by AWS CDK and stored in AWS Secrets Manager.

Also applies to other resources which are provisioned as part of higher lever constructs.

@aws-cdaws-rds efforsmall feature-request p1

Most helpful comment

Hi, I'd like to help out with this if no one is currently working on it.

All 6 comments

Hi,

I believe this to be a bug not a feature request. I think you should be able to supply the secret as per the code below. However, the cloudformation script that are created based on this fail as they do not correctly handle the referencing between the secret and the database as the key can not exist until the database is created. This isn't an issue when the secret isn't specified as it is handled correctly.

export class CdkDbStack extends cdk.Stack {

    readonly secret: secretsManager.ISecret;
    readonly testGocdRDSInstance: rds.DatabaseInstance;

    constructor(scope: cdk.App, id: string, props: SharedStackProps) {
        super(scope, id, props);

        const databaseUsername = 'admin';

        this.secret =  new secretsManager.Secret(this, 'TestDBCredentialsSecret', {
            secretName: `test-rds-server-credentials`,
            generateSecretString: {
                secretStringTemplate: JSON.stringify({
                    username: databaseUsername,
                }),
                generateStringKey: 'password'
            }
        });



        const testRDSInstance = new rds.DatabaseInstance(this, 'test-rds-db-Instance', {
            engine: rds.DatabaseInstanceEngine.POSTGRES,
            // micro database should be available on free tier
            instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO),
            masterUsername: databaseUsername,
            masterUserPassword: this.secret.secretValue,
            vpc: props.vpc,
            // Placement via the subnet defined for the VPC
            vpcPlacement: {subnetGroupName: 'Database'},
            // Alternative mapping if only one of the subnet types exists
            // vpcPlacement: {subnetType: SubnetType.ISOLATED },
            storageType: rds.StorageType.GP2,
            storageEncrypted: true,
            allocatedStorage: 20, // GiB
            backupRetention: Duration.days(5),
            maxAllocatedStorage: 30, //GiB
            instanceIdentifier: 'test-ci-database',
            // None production we can live without multiple availability zones
            multiAz: false,
            autoMinorVersionUpgrade: true
        });
    }

The differences between the generated cloudformation scripts:

Specified secret, not working.

        "MasterUserPassword": {
          "Fn::Join": [
            "",
            [
              "{{resolve:secretsmanager:",
              {
                "Ref": "TestCiGoServerDBCredentialsSecret9741AE3F"
              },
              ":SecretString:::}}"
            ]
          ]
        },

Unspecified key, working:

         "MasterUserPassword": {
          "Fn::Join": [
            "",
            [
              "{{resolve:secretsmanager:",
              {
                "Ref": "testcidbInstanceSecret66362675"
              },
              ":SecretString:password::}}"
            ]
          ]
        },

There are also differences in the secret resource.

I've discovered that if you pass the secret value from the JSON as shown below:

            masterUserPassword: this.secret.secretValueFromJson('password'),

Then the deployment works and you can successfully achieve the feature requested by the original poster and the deployment works. I'd suggest that this reinforced that this is a bug with the compiler.

Hi, I'd like to help out with this if no one is currently working on it.

This applies to Aurora clusters as well, as both use Credentials()

@kochie - I don't believe anyone else is currently working on it. Please feel free to take a shot and post the PR, and let us know if you'd like any guidance.

As the login/credentials interface of RDS changed between the original request and now, I'd say there are now two options for how to go about this:

  1. Add the option for secretName to DatabaseSecret, and use Credentials.fromSecret to use it with a DB. This would involve just the change to the DatabaseSecret class and props.
const secret = new DatabaseSecret(this, 'Secret', {
  username: 'admin',
  secretName: 'myDbSecret',
});
const instance = new rds.DatabaseInstance(this, 'Instance', {
  credentials: rds.Credentials.fromSecret(secret),
  ...
});
  1. Add secretName as an option for CredentialsFromUsernameOptions to use with the Credentials.fromUsername method. This would entail changes to Credentials as well as each of its consumers (DatabaseInstance, DatabaseCluster, and ServerlessCluster).
const instance = new rds.DatabaseInstance(this, 'Instance', {
  credentials: rds.Credentials.fromUsername('admin', { secretName: 'myDbSecret'} ),
  ...
});

Any progress on this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

clareliguori picture clareliguori  路  30Comments

fogfish picture fogfish  路  30Comments

rclark picture rclark  路  49Comments

eladb picture eladb  路  33Comments

julienlepine picture julienlepine  路  39Comments