diff --git a/packages/@aws-cdk/aws-docdb/README.md b/packages/@aws-cdk/aws-docdb/README.md index 6f7ed89e28e11..12f8e08a08387 100644 --- a/packages/@aws-cdk/aws-docdb/README.md +++ b/packages/@aws-cdk/aws-docdb/README.md @@ -21,6 +21,7 @@ your instances will be launched privately or publicly: const cluster = new DatabaseCluster(this, 'Database', { masterUser: { username: 'myuser' // NOTE: 'admin' is reserved by DocumentDB + excludeCharacters: '\"@/:', // optional, defaults to the set "\"@/" }, instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE), vpcSubnets: { diff --git a/packages/@aws-cdk/aws-docdb/lib/cluster.ts b/packages/@aws-cdk/aws-docdb/lib/cluster.ts index 56b5a724dd439..c2b4c7c9737a2 100644 --- a/packages/@aws-cdk/aws-docdb/lib/cluster.ts +++ b/packages/@aws-cdk/aws-docdb/lib/cluster.ts @@ -352,6 +352,7 @@ export class DatabaseCluster extends DatabaseClusterBase { secret = new DatabaseSecret(this, 'Secret', { username: props.masterUser.username, encryptionKey: props.masterUser.kmsKey, + excludeCharacters: props.masterUser.excludeCharacters, }); } diff --git a/packages/@aws-cdk/aws-docdb/lib/database-secret.ts b/packages/@aws-cdk/aws-docdb/lib/database-secret.ts index 605609b4b6ab2..8f1bca671da6d 100644 --- a/packages/@aws-cdk/aws-docdb/lib/database-secret.ts +++ b/packages/@aws-cdk/aws-docdb/lib/database-secret.ts @@ -32,6 +32,13 @@ export interface DatabaseSecretProps { * @default - no master secret information will be included */ readonly masterSecret?: ISecret; + + /** + * Characters to not include in the generated password. + * + * @default "\"@/" + */ + readonly excludeCharacters?: string; } /** @@ -61,7 +68,7 @@ export class DatabaseSecret extends Secret { masterarn: props.masterSecret?.secretArn, }), generateStringKey: 'password', - excludeCharacters: '"@/', + excludeCharacters: props.excludeCharacters ?? '"@/', }, }); } diff --git a/packages/@aws-cdk/aws-docdb/lib/props.ts b/packages/@aws-cdk/aws-docdb/lib/props.ts index 9cd24b1fce1bc..d02f8768973a9 100644 --- a/packages/@aws-cdk/aws-docdb/lib/props.ts +++ b/packages/@aws-cdk/aws-docdb/lib/props.ts @@ -53,6 +53,13 @@ export interface Login { * @default default master key */ readonly kmsKey?: kms.IKey; + + /** + * Specifies characters to not include in generated passwords. + * + * @default "\"@/" + */ + readonly excludeCharacters?: string; } /** diff --git a/packages/@aws-cdk/aws-docdb/test/cluster.test.ts b/packages/@aws-cdk/aws-docdb/test/cluster.test.ts index cb1f8653509df..6628520118c84 100644 --- a/packages/@aws-cdk/aws-docdb/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-docdb/test/cluster.test.ts @@ -1,4 +1,4 @@ -import { expect as expectCDK, haveResource, ResourcePart, arrayWith } from '@aws-cdk/assert-internal'; +import { expect as expectCDK, haveResource, ResourcePart, arrayWith, haveResourceLike, objectLike } from '@aws-cdk/assert-internal'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; @@ -293,6 +293,29 @@ describe('DatabaseCluster', () => { })); }); + test('creates a secret with excludeCharacters', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + masterUser: { + username: 'admin', + excludeCharacters: '"@/()[]', + }, + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc, + }); + + // THEN + expectCDK(stack).to(haveResourceLike('AWS::SecretsManager::Secret', { + GenerateSecretString: objectLike({ + ExcludeCharacters: '\"@/()[]', + }), + })); + }); + test('create an encrypted cluster with custom KMS key', () => { // GIVEN const stack = testStack();