Skip to content

(aws-rds): Add support to DatabaseCluster to support iam-db-auth for masterUsername user. #37658

@sbrinkerhoff

Description

@sbrinkerhoff

Describe the feature

Using the aws cli one can create an AWS Aurora Serverless V2 Postgres cluster that utilizes IAM Authentication for the master-username.

# Create the cluster with IAM-only master auth
aws rds create-db-cluster \
  --db-cluster-identifier my-aurora-cluster \
  --engine aurora-postgresql \
  --region us-west-2 \
  --master-username postgres \
  --master-user-authentication-type iam-db-auth \
  --enable-iam-database-authentication

# Set scaling policy
aws rds modify-db-cluster \
  --db-cluster-identifier my-aurora-cluster \
  --serverless-v2-scaling-configuration MinCapacity=0.5,MaxCapacity=2 \
  --region us-west-2

# Add a Serverless v2 writer instance
aws rds create-db-instance \
  --db-instance-identifier my-aurora-cluster-writer \
  --db-cluster-identifier my-aurora-cluster \
  --engine aurora-postgresql \
  --db-instance-class db.serverless \
  --region us-west-2

This can be replicated using aws-cdk with the L1 constructs:

import { App, Stack, RemovalPolicy } from 'aws-cdk-lib';
import { CfnDBCluster, CfnDBInstance, CfnDBSubnetGroup } from 'aws-cdk-lib/aws-rds';
import { Vpc, SecurityGroup } from 'aws-cdk-lib/aws-ec2';

const app = new App();
const stack = new Stack(app, 'L1-IamAuth', {
  env: { account: 'YOUR-ACCOUNT-HERE', region: 'us-west-2' },
});

const vpc = Vpc.fromLookup(stack, 'Vpc', { vpcId: 'YOUR-VPC-HERE' });

const sg = new SecurityGroup(stack, 'DbSg', {
  vpc,
  description: 'Aurora cluster security group',
});

const subnetGroup = new CfnDBSubnetGroup(stack, 'SubnetGroup', {
  dbSubnetGroupDescription: 'Subnets for IAM auth repro cluster',
  subnetIds: vpc.privateSubnets.map(s => s.subnetId),
});

const cluster = new CfnDBCluster(stack, 'Cluster', {
  engine: 'aurora-postgresql',
  engineVersion: '17.5',
  masterUsername: 'postgres',
  masterUserAuthenticationType: 'iam-db-auth',
  enableIamDatabaseAuthentication: true,
  serverlessV2ScalingConfiguration: { minCapacity: 0.5, maxCapacity: 2 },
  dbSubnetGroupName: subnetGroup.ref,
  vpcSecurityGroupIds: [sg.securityGroupId],
  storageEncrypted: true,
});
cluster.applyRemovalPolicy(RemovalPolicy.DESTROY);

const writer = new CfnDBInstance(stack, 'Writer', {
  dbClusterIdentifier: cluster.ref,
  dbInstanceClass: 'db.serverless',
  engine: 'aurora-postgresql',
});

However there does not appear to be a functional way to use the L2 DatabaseCluster construct to achieve this same functionality. There is no masterUserAuthenticationType passed through in the construct.

const cluster = new DatabaseCluster(stack, 'DB', {
  engine: DatabaseClusterEngine.auroraPostgres({
    version: AuroraPostgresEngineVersion.VER_17_5,
  }),
  vpc,
  writer: ClusterInstance.serverlessV2('writer'),
  iamAuthentication: true,
  defaultDatabaseName: 'repro',
  removalPolicy: RemovalPolicy.DESTROY,
});

One can add a PropertyOverride:

const cfnCluster = cluster.node.defaultChild as CfnDBCluster;
cfnCluster.addPropertyOverride('MasterUserAuthenticationType', 'iam-db-auth');

However the MasterUserPassword is always set.

  "DB4924F778": {
   "Type": "AWS::RDS::DBCluster",
   "Properties": {
    "CopyTagsToSnapshot": true,
    "DBClusterParameterGroupName": "default.aurora-postgresql17",
    "DBSubnetGroupName": {
     "Ref": "DBSubnets7B70DA43"
    },
    "EnableIAMDatabaseAuthentication": true,
    "Engine": "aurora-postgresql",
    "EngineVersion": "17.5",
    "MasterUserAuthenticationType": "iam-db-auth",
    "MasterUserPassword": {
     "Fn::Join": [
      "",
      [
       "{{resolve:secretsmanager:",
       {
        "Ref": "DBSecretB8D1B379"
       },
       ":SecretString:password::}}"
      ]
     ]
    },

It is possible to override the masterUserPassword to enable creating an RDS Cluster with the L2 construct and IAM Master user authentication.

      const cfnCluster = this.databaseCluster.node.defaultChild as CfnDBCluster;
      const origDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(cfnCluster), 'cfnProperties');
      Object.defineProperty(cfnCluster, 'cfnProperties', {
        get() {
          const baseProps = origDescriptor?.get?.call(this) ?? {};
          delete baseProps.masterUserPassword;
          delete baseProps.manageMasterUserPassword;
          baseProps.masterUserAuthenticationType = 'iam-db-auth';
          return baseProps;
        },
        configurable: true,
      });

References

Use Case

Functional equivalency with the command line, and L1 construct should exist in the L2 construct.

Proposed Solution

Allow a prop that can configure the master database user to use IAM, and not set the MasterPassword value (which is always set right now, as renderCredentials will always set a password).

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

AWS CDK Library version (aws-cdk-lib)

[email protected]

AWS CDK CLI version

2.1030.0

Environment details (OS name and version, etc.)

AL2023

Metadata

Metadata

Assignees

No one assigned

    Labels

    @aws-cdk/aws-rdsRelated to Amazon Relational Databaseeffort/mediumMedium work item – several days of effortfeature-requestA feature should be added or improved.p2

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions