Skip to content

Commit

Permalink
feat(docdb): Support multiple security groups to DatabaseCluster (#13290
Browse files Browse the repository at this point in the history
)

Resolves #13294

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
jericht authored May 5, 2021
1 parent 0948cc7 commit 1a97b66
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
10 changes: 10 additions & 0 deletions packages/@aws-cdk/aws-docdb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ attributes:
const writeAddress = cluster.clusterEndpoint.socketAddress; // "HOSTNAME:PORT"
```

If you have existing security groups you would like to add to the cluster, use the `addSecurityGroups` method. Security
groups added in this way will not be managed by the `Connections` object of the cluster.

```ts
const securityGroup = new ec2.SecurityGroup(stack, 'SecurityGroup', {
vpc,
});
cluster.addSecurityGroups(securityGroup);
```

## Rotating credentials

When the master password is generated and stored in AWS Secrets Manager, it can be rotated automatically:
Expand Down
32 changes: 24 additions & 8 deletions packages/@aws-cdk/aws-docdb/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@ export class DatabaseCluster extends DatabaseClusterBase {
*/
public readonly secret?: secretsmanager.ISecret;

/**
* The underlying CloudFormation resource for a database cluster.
*/
private readonly cluster: CfnDBCluster;

/**
* The VPC where the DB subnet group is created.
*/
Expand Down Expand Up @@ -348,7 +353,7 @@ export class DatabaseCluster extends DatabaseClusterBase {
}

// Create the DocDB cluster
const cluster = new CfnDBCluster(this, 'Resource', {
this.cluster = new CfnDBCluster(this, 'Resource', {
// Basic
engineVersion: props.engineVersion,
dbClusterIdentifier: props.dbClusterName,
Expand All @@ -370,16 +375,16 @@ export class DatabaseCluster extends DatabaseClusterBase {
storageEncrypted,
});

cluster.applyRemovalPolicy(props.removalPolicy, {
this.cluster.applyRemovalPolicy(props.removalPolicy, {
applyToUpdateReplacePolicy: true,
});

this.clusterIdentifier = cluster.ref;
this.clusterResourceIdentifier = cluster.attrClusterResourceId;
this.clusterIdentifier = this.cluster.ref;
this.clusterResourceIdentifier = this.cluster.attrClusterResourceId;

const port = Token.asNumber(cluster.attrPort);
this.clusterEndpoint = new Endpoint(cluster.attrEndpoint, port);
this.clusterReadEndpoint = new Endpoint(cluster.attrReadEndpoint, port);
const port = Token.asNumber(this.cluster.attrPort);
this.clusterEndpoint = new Endpoint(this.cluster.attrEndpoint, port);
this.clusterReadEndpoint = new Endpoint(this.cluster.attrReadEndpoint, port);

if (secret) {
this.secret = secret.attach(this);
Expand All @@ -399,7 +404,7 @@ export class DatabaseCluster extends DatabaseClusterBase {

const instance = new CfnDBInstance(this, `Instance${instanceIndex}`, {
// Link to cluster
dbClusterIdentifier: cluster.ref,
dbClusterIdentifier: this.cluster.ref,
dbInstanceIdentifier: instanceIdentifier,
// Instance properties
dbInstanceClass: databaseInstanceType(props.instanceType),
Expand Down Expand Up @@ -467,6 +472,17 @@ export class DatabaseCluster extends DatabaseClusterBase {
target: this,
});
}

/**
* Adds security groups to this cluster.
* @param securityGroups The security groups to add.
*/
public addSecurityGroups(...securityGroups: ec2.ISecurityGroup[]): void {
if (this.cluster.vpcSecurityGroupIds === undefined) {
this.cluster.vpcSecurityGroupIds = [];
}
this.cluster.vpcSecurityGroupIds.push(...securityGroups.map(sg => sg.securityGroupId));
}
}

/**
Expand Down
25 changes: 24 additions & 1 deletion packages/@aws-cdk/aws-docdb/test/cluster.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect as expectCDK, haveResource, ResourcePart } from '@aws-cdk/assert-internal';
import { expect as expectCDK, haveResource, ResourcePart, arrayWith } 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';
Expand Down Expand Up @@ -725,6 +725,29 @@ describe('DatabaseCluster', () => {
expect(addMultiUserRotation).toThrow();
});

test('adds security groups', () => {
// GIVEN
const stack = testStack();
const vpc = new ec2.Vpc(stack, 'VPC');
const cluster = new DatabaseCluster(stack, 'Database', {
vpc,
masterUser: {
username: 'admin',
},
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.SMALL),
});
const securityGroup = new ec2.SecurityGroup(stack, 'SecurityGroup', {
vpc,
});

// WHEN
cluster.addSecurityGroups(securityGroup);

// THEN
expectCDK(stack).to(haveResource('AWS::DocDB::DBCluster', {
VpcSecurityGroupIds: arrayWith(stack.resolve(securityGroup.securityGroupId)),
}));
});
});

function testStack() {
Expand Down

0 comments on commit 1a97b66

Please sign in to comment.