(aws-rds): Add support to `DatabaseCluster` to support `iam-db-auth` for masterUsername user.
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### 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](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-rds/lib/cluster.ts#L1481).
```
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
- https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-cluster.html
- https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBCluster.html
- https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_rds-readme.html
### 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](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-rds/lib/cluster.ts#L1486) will always set a password).
### Other Information
_No response_
### Acknowledgements
- [x] I may be able to implement this feature request
- [ ] This feature might incur a breaking change
### AWS CDK Library version (aws-cdk-lib)
aws-cdk-lib@2.217.0
### AWS CDK CLI version
2.1030.0
### Environment details (OS name and version, etc.)
AL2023
Contributor guide
Research direction
The L2 DatabaseCluster implementation is in packages/aws-cdk-lib/aws-rds/lib/cluster.ts; start at the prop handling around line 1481 and renderCredentials around line 1486. Trace how CfnDBCluster properties are synthesized, then verify the IAM master-user option omits the password while preserving existing behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, databases, infrastructure
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100