From 4cf6486899257996f606d1f72a2f3f07f7ca64ac Mon Sep 17 00:00:00 2001 From: Josh Usiskin Date: Thu, 21 Oct 2021 17:24:25 +0000 Subject: [PATCH] fix(deadline): allow traffic from RenderQueue to UsageBasedLicensing --- .../aws-rfdk/lib/deadline/lib/render-queue.ts | 17 +++++++++ .../lib/deadline/lib/usage-based-licensing.ts | 12 +++++-- .../lib/deadline/test/render-queue.test.ts | 25 +++++++++++++ .../test/usage-based-licensing.test.ts | 36 +++++++++++++------ 4 files changed, 76 insertions(+), 14 deletions(-) diff --git a/packages/aws-rfdk/lib/deadline/lib/render-queue.ts b/packages/aws-rfdk/lib/deadline/lib/render-queue.ts index 77a63f7a7..b6441c361 100644 --- a/packages/aws-rfdk/lib/deadline/lib/render-queue.ts +++ b/packages/aws-rfdk/lib/deadline/lib/render-queue.ts @@ -113,6 +113,11 @@ export interface IRenderQueue extends IConstruct, IConnectable { */ readonly endpoint: ConnectableApplicationEndpoint; + /** + * A connections object for controlling access of the compute resources that host the render queue. + */ + readonly backendConnections: Connections; + /** * Configures an ECS cluster to be able to connect to a RenderQueue * @returns An environment mapping that is used to configure the Docker Images @@ -187,6 +192,11 @@ abstract class RenderQueueBase extends Construct implements IRenderQueue { */ public abstract readonly repository: IRepository; + /** + * @inheritdoc + */ + public abstract readonly backendConnections: Connections; + /** * Configures an ECS cluster to be able to connect to a RenderQueue * @returns An environment mapping that is used to configure the Docker Images @@ -314,6 +324,11 @@ export class RenderQueue extends RenderQueueBase implements IGrantable { */ public readonly repository: IRepository; + /** + * @inheritdoc + */ + public readonly backendConnections: Connections; + /** * Whether SEP policies have been added */ @@ -440,6 +455,8 @@ export class RenderQueue extends RenderQueueBase implements IGrantable { securityGroup: props.securityGroups?.backend, }); + this.backendConnections = this.asg.connections; + /** * The ECS-optimized AMI that is defaulted to when adding capacity to a cluster does not include the awscli or unzip * packages as is the case with the standard Amazon Linux AMI. These are required by RFDK scripts to configure the diff --git a/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts b/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts index 0dbd9f38b..39c6ebf6d 100644 --- a/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts +++ b/packages/aws-rfdk/lib/deadline/lib/usage-based-licensing.ts @@ -444,9 +444,12 @@ export interface UsageBasedLicensingProps { * * The Deadline License Forwarder is set up to run within an AWS ECS task. * - * Access to the running License Forwarder is gated by a security group that, by default, allows no ingress; - * when a Deadline Worker requires access to licensing, then the RFDK constructs will grant that worker’s security group - * ingress on TCP port 17004 as well as other ports as required by the specific licenses being used. + * Access to the running License Forwarder is gated by a security group that, by default, only allows ingress from the + * Render Queue (in order to register Workers for license forwarding). + * + * When a Deadline Worker requires access to licensing via `UsageBasedLicensing.grantPortAccess(...)`, then the RFDK + * constructs will grant that worker’s security group ingress on TCP port 17004 as well as other ports as required by + * the specific licenses being used. * * Note: This construct does not currently implement the Deadline License Forwarder's Web Forwarding functionality. * This construct is not usable in any China region. @@ -617,6 +620,9 @@ export class UsageBasedLicensing extends Construct implements IGrantable { }); } + // Grant the render queue the ability to connect to the license forwarder to register workers + this.asg.connections.allowFrom(props.renderQueue.backendConnections, Port.tcp(UsageBasedLicensing.LF_PORT)); + // Tag deployed resources with RFDK meta-data tagConstruct(this); } diff --git a/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts b/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts index b174f130c..d17487374 100644 --- a/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/render-queue.test.ts @@ -2974,4 +2974,29 @@ describe('RenderQueue', () => { }); }); }); + + test('.backendConnections is associated with ASG security group rules', () => { + // GIVEN + const instance = new Instance(dependencyStack, 'BackendConnectionInstance', { + instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MICRO), + machineImage: MachineImage.latestAmazonLinux(), + vpc, + }); + const portNumber = 5555; + const port = Port.tcp(portNumber); + const asgSecurityGroup = renderQueueCommon.asg.connections.securityGroups[0]; + + // WHEN + renderQueueCommon.backendConnections.allowFrom(instance, port); + + // THEN + expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + IpProtocol: 'tcp', + Description: `from ${instance.connections.securityGroups[0].uniqueId}:${portNumber}`, + GroupId: stack.resolve(asgSecurityGroup.securityGroupId), + SourceSecurityGroupId: stack.resolve(instance.connections.securityGroups[0].securityGroupId), + FromPort: portNumber, + ToPort: portNumber, + })); + }); }); diff --git a/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts b/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts index 11ad06c4f..b52866dd1 100644 --- a/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/usage-based-licensing.test.ts @@ -626,23 +626,37 @@ describe('UsageBasedLicensing', () => { }); describe('configures render queue', () => { - test('adds ingress rule for asg', () => { + test('adds ingress rule from UsageBasedLicensing ASG to RenderQueue ASG', () => { + // GIVEN + const renderQueueSecurityGroup = renderQueue.connections.securityGroups[0]; + // WHEN - createUbl(); + const ubl = createUbl(); + const ublSecurityGroup = ubl.connections.securityGroups[0]; expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 4433, ToPort: 4433, - GroupId: { - 'Fn::ImportValue': stringLike(`${Stack.of(renderQueue).stackName}:ExportsOutputFnGetAttRQNonDefaultPortLBSecurityGroup*`), - }, - SourceSecurityGroupId: { - 'Fn::GetAtt': [ - 'UBLClusterASGInstanceSecurityGroupAA1A7A2D', - 'GroupId', - ], - }, + GroupId: stack.resolve(renderQueueSecurityGroup.securityGroupId), + SourceSecurityGroupId: stack.resolve(ublSecurityGroup.securityGroupId), + })); + }); + + test('adds ingress rule from RenderQueue ASG to UsageBasedLicensing ASG', () => { + // GIVEN + const renderQueueSecurityGroup = renderQueue.backendConnections.securityGroups[0]; + + // WHEN + const ubl = createUbl(); + const ublSecurityGroup = ubl.connections.securityGroups[0]; + + expectCDK(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', { + IpProtocol: 'tcp', + FromPort: 17004, + ToPort: 17004, + GroupId: stack.resolve(ublSecurityGroup.securityGroupId), + SourceSecurityGroupId: stack.resolve(renderQueueSecurityGroup.securityGroupId), })); });