Skip to content

Commit

Permalink
feat(deadline): add security group configuration for Repository and R…
Browse files Browse the repository at this point in the history
…enderQueue
  • Loading branch information
jericht committed Feb 23, 2021
1 parent e6bb60d commit eb2878f
Show file tree
Hide file tree
Showing 8 changed files with 407 additions and 1 deletion.
13 changes: 13 additions & 0 deletions packages/aws-rfdk/lib/core/lib/mongodb-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,12 @@ export interface IMongoDb extends IConnectable, IConstruct {
* The version of MongoDB that is running on this instance.
*/
readonly version: MongoDbVersion;

/**
* Adds security groups to the database.
* @param securityGroups The security groups to add.
*/
addSecurityGroup(...securityGroups: ISecurityGroup[]): void;
}

/**
Expand Down Expand Up @@ -487,6 +493,13 @@ export class MongoDbInstance extends Construct implements IMongoDb, IGrantable {
tagConstruct(this);
}

/**
* @inheritdoc
*/
public addSecurityGroup(...securityGroups: ISecurityGroup[]): void {
securityGroups?.forEach(securityGroup => this.server.autoscalingGroup.addSecurityGroup(securityGroup));
}

/**
* Adds UserData commands to install & configure the CloudWatch Agent onto the instance.
*
Expand Down
44 changes: 44 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/database-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import * as path from 'path';
import {
CfnDBCluster,
CfnDBInstance,
DatabaseCluster,
IDatabaseCluster,
} from '@aws-cdk/aws-docdb';
import {
IConnectable,
ISecurityGroup,
OperatingSystemType,
Port,
} from '@aws-cdk/aws-ec2';
Expand Down Expand Up @@ -155,6 +157,13 @@ export abstract class DatabaseConnection {
* @param child The child to make dependent upon this database.
*/
public abstract addChildDependency(child: IConstruct): void;

/**
* Adds a security group to the database.
*
* @param securityGroups The security group to add.
*/
public abstract addSecurityGroup(...securityGroups: ISecurityGroup[]): void;
}

/**
Expand Down Expand Up @@ -267,6 +276,34 @@ class DocDBDatabaseConnection extends DatabaseConnection {
}
}

/**
* @inheritdoc
*/
public addSecurityGroup(...securityGroups: ISecurityGroup[]): void {
const added = false;
if (this.props.database instanceof DatabaseCluster) {
const resource = (this.props.database as DatabaseCluster).node.findChild('Resource');
if (resource instanceof CfnDBCluster) {
const cfnCluster = resource as CfnDBCluster;
const securityGroupIds = securityGroups.map(sg => sg.securityGroupId);

if (cfnCluster.vpcSecurityGroupIds === undefined) {
cfnCluster.vpcSecurityGroupIds = securityGroupIds;
} else {
cfnCluster.vpcSecurityGroupIds.push(...securityGroupIds);
}
}
}

if (!added) {
Annotations.of(this.props.database).addWarning(
`Failed to add the following security groups to ${this.props.database.node.id}: ${securityGroups.map(sg => sg.securityGroupId).join(', ')}. ` +
'This is because either the "database" property passed to this class is not an instance of AWS CDK\'s DocumentDB cluster construct or the ' +
'internal implementation of AWS CDK\'s DocumentDB cluster construct has changed.',
);
}
}

/**
* Deadline is only compatible with MongoDB 3.6. This function attempts to determine whether
* the given DocDB version is compatible.
Expand Down Expand Up @@ -375,6 +412,13 @@ class MongoDbInstanceDatabaseConnection extends DatabaseConnection {
}
}

/**
* @inheritdoc
*/
public addSecurityGroup(...securityGroups: ISecurityGroup[]): void {
this.props.database.addSecurityGroup(...securityGroups);
}

/**
* Download the client PKCS#12 certificate for authenticating to the MongoDB, and place it into
* the path defined by: DB_CERT_LOCATION
Expand Down
20 changes: 20 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/render-queue-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@aws-cdk/aws-certificatemanager';
import {
InstanceType,
ISecurityGroup,
IVpc,
SubnetSelection,
} from '@aws-cdk/aws-ec2';
Expand Down Expand Up @@ -211,6 +212,20 @@ export interface RenderQueueAccessLogProps {
readonly prefix?: string;
}

/**
* Options for security groups of the `RenderQueue`.
*/
export interface RenderQueueSecurityGroupsOptions {
/**
* The `AutoScalingGroup` security groups.
*/
readonly autoScalingGroup?: ISecurityGroup[];
/**
* The `LoadBalancer` security groups.
*/
readonly loadBalancer?: ISecurityGroup[];
}

/**
* Properties for the Render Queue
*/
Expand Down Expand Up @@ -312,6 +327,11 @@ export interface RenderQueueProps {
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#deletion-protection
*/
readonly deletionProtection?: boolean;

/**
* Options to add additional security groups to the `RenderQueue`.
*/
readonly securityGroups?: RenderQueueSecurityGroupsOptions;
}

/**
Expand Down
14 changes: 14 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/render-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import {
IRepository,
IVersion,
RenderQueueProps,
RenderQueueSecurityGroupsOptions,
VersionQuery,
} from '.';

Expand Down Expand Up @@ -448,6 +449,10 @@ export class RenderQueue extends RenderQueueBase implements IGrantable {
});
}

if (props.securityGroups) {
this.addSecurityGroups(props.securityGroups);
}

this.node.defaultChild = taskDefinition;

// Tag deployed resources with RFDK meta-data
Expand Down Expand Up @@ -519,6 +524,15 @@ export class RenderQueue extends RenderQueueBase implements IGrantable {
child.node.addDependency(this.taskDefinition);
}

public addSecurityGroups(securityGroups: RenderQueueSecurityGroupsOptions) {
securityGroups.autoScalingGroup?.forEach(securityGroup => {
this.asg.addSecurityGroup(securityGroup);
});
securityGroups.loadBalancer?.forEach(securityGroup => {
this.loadBalancer.addSecurityGroup(securityGroup);
});
}

private createTaskDefinition(props: {
image: ContainerImage,
portNumber: number,
Expand Down
19 changes: 19 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
InstanceClass,
InstanceSize,
InstanceType,
ISecurityGroup,
IVpc,
OperatingSystemType,
SubnetSelection,
Expand Down Expand Up @@ -339,6 +340,11 @@ export interface RepositoryProps {
* @default Duration.days(15) for the database
*/
readonly backupOptions?: RepositoryBackupOptions;

/**
* The security groups to add to the database.
*/
readonly securityGroups?: ISecurityGroup[];
}

/**
Expand Down Expand Up @@ -535,6 +541,10 @@ export class Repository extends Construct implements IRepository {
});
}

if (props.securityGroups) {
this.addSecurityGroup(...props.securityGroups);
}

// Launching the instance which installs the deadline repository in the stack.
this.installerGroup = new AutoScalingGroup(this, 'Installer', {
instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE),
Expand Down Expand Up @@ -602,6 +612,15 @@ export class Repository extends Construct implements IRepository {
return validationErrors;
}

/**
* Add the security groups to the repository
*
* @param securityGroups: The security groups to add
*/
public addSecurityGroup(...securityGroups: ISecurityGroup[]): void {
this.databaseConnection.addSecurityGroup(...securityGroups);
}

/**
* @inheritdoc
*/
Expand Down
52 changes: 51 additions & 1 deletion packages/aws-rfdk/lib/deadline/test/database-connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import {
} from '@aws-cdk/assert';
import {
DatabaseCluster,
Endpoint,
IDatabaseCluster,
} from '@aws-cdk/aws-docdb';
import {
AmazonLinuxGeneration,
Connections,
Instance,
InstanceClass,
InstanceSize,
Expand All @@ -31,9 +34,14 @@ import {
import {
PrivateHostedZone,
} from '@aws-cdk/aws-route53';
import { Secret } from '@aws-cdk/aws-secretsmanager';
import {
Secret,
SecretAttachmentTargetProps,
} from '@aws-cdk/aws-secretsmanager';
import {
Construct,
Duration,
ResourceEnvironment,
Stack,
} from '@aws-cdk/core';

Expand Down Expand Up @@ -264,6 +272,48 @@ describe('DocumentDB', () => {
}).toThrowError('Connecting to the Deadline Database is currently only supported for Linux.');
});

test('adds warning annotation when a security group cannot be added', () => {
// GIVEN
class FakeDatabaseCluster extends Construct implements IDatabaseCluster {
public readonly clusterIdentifier: string = '';
public readonly instanceIdentifiers: string[] = [];
public readonly clusterEndpoint: Endpoint = new Endpoint('address', 123);
public readonly clusterReadEndpoint: Endpoint = new Endpoint('readAddress', 123);
public readonly instanceEndpoints: Endpoint[] = [];
public readonly securityGroupId: string = '';
public readonly connections: Connections = new Connections();

public readonly stack: Stack;
public readonly env: ResourceEnvironment;

constructor(scope: Construct, id: string) {
super(scope, id);
this.stack = Stack.of(scope);
this.env = {account: this.stack.account, region: this.stack.region};
}

asSecretAttachmentTarget(): SecretAttachmentTargetProps {
throw new Error('Method not implemented.');
}
}
const fakeDatabase = new FakeDatabaseCluster(stack, 'FakeDatabase');
const securityGroup = new SecurityGroup(stack, 'NewSecurityGroup', { vpc });
const connection = DatabaseConnection.forDocDB({database: fakeDatabase, login: database.secret!});

// WHEN
connection.addSecurityGroup(securityGroup);

// THEN
expect(fakeDatabase.node.metadata).toEqual(expect.arrayContaining([
expect.objectContaining({
type: 'aws:cdk:warning',
data: expect.stringMatching(new RegExp(`Failed to add the following security groups to ${fakeDatabase.node.id}: .*\\. ` +
'This is because either the \\"database\\" property passed to this class is not an instance of AWS CDK\'s DocumentDB cluster construct or the ' +
'internal implementation of AWS CDK\'s DocumentDB cluster construct has changed.')),
}),
]));
});

});

describe('DocumentDB Version Checks', () => {
Expand Down
Loading

0 comments on commit eb2878f

Please sign in to comment.