From 22e8500e430008f88273a367e3d9a81191943817 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Wed, 29 Jul 2020 21:37:20 +0000 Subject: [PATCH 1/7] Initial commit --- .../lib/accelerator-security-group.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts diff --git a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts new file mode 100644 index 0000000000000..626a74adb2ce9 --- /dev/null +++ b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts @@ -0,0 +1,62 @@ +import { Construct } from '@aws-cdk/core'; +import { ISecurityGroup, SecurityGroup, IVpc } from '@aws-cdk/aws-ec2'; +import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId} from '@aws-cdk/custom-resources'; + +/** + * The security group used by a Global Accelerator to send traffic to resources in a VPC. + */ +export class AcceleratorSecurityGroup { + /** + * Lookup the Global Accelerator security group at CloudFormation deployment time. + * + * As of this writing, Global Accelerators (AGA) create a single security group per VPC. AGA security groups are shared + * by all AGAs in an account. Additionally, there is no CloudFormation mechanism to reference the AGA security groups. + * + * This makes creating security group rules which allow traffic from an AGA complicated in CDK. This lookup will identify + * the AGA security group for a given VPC at CloudFormation deployment time, and lets you create rules for traffic from AGA + * to other resources created by CDK. + */ + public static fromVpc(scope: Construct, vpc: IVpc): ISecurityGroup { + + // The security group name is always 'GlobalAccelerator' + const globalAcceleratorSGName = 'GlobalAccelerator'; + + // How to reference the security group name in the response from EC2 + const ec2ResponseSGIdField = 'SecurityGroups.0.GroupId'; + + // The AWS Custom Resource that make a call to EC2 to get the security group ID, for the given VPC + const lookupAcceleratorSGCustomResource = new AwsCustomResource(scope, 'GetGlobalAcceleratorSGCustomResource', { + onCreate: { + service: 'EC2', + action: 'describeSecurityGroups', + parameters: { + Filters: [ + { + Name: 'group-name', + Values: [ + globalAcceleratorSGName, + ], + }, + { + Name: 'vpc-id', + Values: [ + vpc.vpcId, + ], + }, + ], + }, + // We get back a list of responses, but the list should be of length 0 or 1 + // Getting no response means no resources have been linked to the AGA + physicalResourceId: PhysicalResourceId.fromResponse(ec2ResponseSGIdField), + }, + policy: AwsCustomResourcePolicy.fromSdkCalls({ + resources: AwsCustomResourcePolicy.ANY_RESOURCE, + }), + }); + + // Look up the security group ID + return SecurityGroup.fromSecurityGroupId(scope, + 'GlobalAcceleratorSecurityGroup', + lookupAcceleratorSGCustomResource.getResponseField(ec2ResponseSGIdField)); + } +} From f5a55cb6c6e193b67be09fc8b343ab0388f8dbef Mon Sep 17 00:00:00 2001 From: James Fleming Date: Wed, 29 Jul 2020 22:33:07 +0000 Subject: [PATCH 2/7] Successful build --- .../lib/accelerator-security-group.ts | 2 +- packages/@aws-cdk/aws-globalaccelerator/package.json | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts index 626a74adb2ce9..ef0e5718523e1 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts @@ -1,5 +1,5 @@ -import { Construct } from '@aws-cdk/core'; import { ISecurityGroup, SecurityGroup, IVpc } from '@aws-cdk/aws-ec2'; +import { Construct } from '@aws-cdk/core'; import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId} from '@aws-cdk/custom-resources'; /** diff --git a/packages/@aws-cdk/aws-globalaccelerator/package.json b/packages/@aws-cdk/aws-globalaccelerator/package.json index fb84dd0d1d5eb..d9fa05dcacc62 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/package.json +++ b/packages/@aws-cdk/aws-globalaccelerator/package.json @@ -66,7 +66,6 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/assert": "0.0.0", - "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-elasticloadbalancingv2": "0.0.0", "cdk-integ-tools": "0.0.0", "cdk-build-tools": "0.0.0", @@ -74,12 +73,16 @@ "pkglint": "0.0.0" }, "dependencies": { + "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/core": "0.0.0", + "@aws-cdk/custom-resources": "0.0.0", "constructs": "^3.0.2" }, "peerDependencies": { + "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/core": "0.0.0", - "constructs": "^3.0.2" + "constructs": "^3.0.2", + "@aws-cdk/custom-resources": "0.0.0" }, "engines": { "node": ">= 10.13.0 <13 || >=13.7.0" From b58d582cc1ba2e9a74b028444b99b2610dcdc06b Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 30 Jul 2020 15:01:29 +0000 Subject: [PATCH 3/7] Add unit tests --- .../lib/accelerator-security-group.ts | 6 +- .../aws-globalaccelerator/lib/index.ts | 1 + .../globalaccelerator-security-group.test.ts | 69 +++++++++++++++++++ .../aws-globalaccelerator/test/util.ts | 2 +- 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts diff --git a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts index ef0e5718523e1..12257ee68bf31 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts @@ -16,7 +16,7 @@ export class AcceleratorSecurityGroup { * the AGA security group for a given VPC at CloudFormation deployment time, and lets you create rules for traffic from AGA * to other resources created by CDK. */ - public static fromVpc(scope: Construct, vpc: IVpc): ISecurityGroup { + public static fromVpc(scope: Construct, id: string, vpc: IVpc): ISecurityGroup { // The security group name is always 'GlobalAccelerator' const globalAcceleratorSGName = 'GlobalAccelerator'; @@ -25,7 +25,7 @@ export class AcceleratorSecurityGroup { const ec2ResponseSGIdField = 'SecurityGroups.0.GroupId'; // The AWS Custom Resource that make a call to EC2 to get the security group ID, for the given VPC - const lookupAcceleratorSGCustomResource = new AwsCustomResource(scope, 'GetGlobalAcceleratorSGCustomResource', { + const lookupAcceleratorSGCustomResource = new AwsCustomResource(scope, id + 'CustomResource', { onCreate: { service: 'EC2', action: 'describeSecurityGroups', @@ -56,7 +56,7 @@ export class AcceleratorSecurityGroup { // Look up the security group ID return SecurityGroup.fromSecurityGroupId(scope, - 'GlobalAcceleratorSecurityGroup', + id, lookupAcceleratorSGCustomResource.getResponseField(ec2ResponseSGIdField)); } } diff --git a/packages/@aws-cdk/aws-globalaccelerator/lib/index.ts b/packages/@aws-cdk/aws-globalaccelerator/lib/index.ts index ce94d8991fb5d..ff4675e6af2e5 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/lib/index.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/lib/index.ts @@ -1,5 +1,6 @@ // AWS::GlobalAccelerator CloudFormation Resources: export * from './globalaccelerator.generated'; export * from './accelerator'; +export * from './accelerator-security-group'; export * from './listener'; export * from './endpoint-group'; diff --git a/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts b/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts new file mode 100644 index 0000000000000..a6d193e455a1a --- /dev/null +++ b/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts @@ -0,0 +1,69 @@ +import { expect, haveResource } from '@aws-cdk/assert'; +import { Port } from '@aws-cdk/aws-ec2'; +import * as ga from '../lib'; +import { testFixture, testFixtureAlb } from './util'; + +test('custom resource exists', () => { + // GIVEN + const { stack, vpc } = testFixture(); + + // WHEN + ga.AcceleratorSecurityGroup.fromVpc(stack, 'GlobalAcceleratorSG', vpc); + + // THEN + expect(stack).to(haveResource('Custom::AWS', { + Create: { + action: 'describeSecurityGroups', + service: 'EC2', + parameters: { + Filters: [ + { + Name: 'group-name', + Values: [ + 'GlobalAccelerator', + ], + }, + { + Name: 'vpc-id', + Values: [ + { + Ref: 'VPCB9E5F0B4', + }, + ], + }, + ], + }, + physicalResourceId: { + responsePath: 'SecurityGroups.0.GroupId', + }, + }, + })); +}); + +test('can create security group rule', () => { + // GIVEN + const { stack, alb, vpc } = testFixtureAlb(); + + // WHEN + const sg = ga.AcceleratorSecurityGroup.fromVpc(stack, 'GlobalAcceleratorSG', vpc); + alb.connections.allowFrom(sg, Port.tcp(443)); + + // THEN + expect(stack).to(haveResource('AWS::EC2::SecurityGroupIngress', { + IpProtocol: 'tcp', + FromPort: 443, + GroupId: { + 'Fn::GetAtt': [ + 'ALBSecurityGroup8B8624F8', + 'GroupId', + ], + }, + SourceSecurityGroupId: { + 'Fn::GetAtt': [ + 'GlobalAcceleratorSGCustomResourceC1DB5287', + 'SecurityGroups.0.GroupId', + ], + }, + ToPort: 443, + })); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-globalaccelerator/test/util.ts b/packages/@aws-cdk/aws-globalaccelerator/test/util.ts index 03fc491788e21..56e7561565c1a 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/test/util.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/test/util.ts @@ -19,7 +19,7 @@ export function testFixtureAlb() { const { stack, app, vpc } = testFixture(); const alb = new elbv2.ApplicationLoadBalancer(stack, 'ALB', { vpc, internetFacing: true }); - return { stack, app, alb }; + return { stack, app, alb, vpc }; } export function testFixtureNlb() { From 8f2c13c55a254023d028ea5dfbe0d66f8f5b6ac8 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 30 Jul 2020 16:29:43 +0000 Subject: [PATCH 4/7] Add readme --- .../@aws-cdk/aws-globalaccelerator/README.md | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-globalaccelerator/README.md b/packages/@aws-cdk/aws-globalaccelerator/README.md index ac304fe3ea03e..a380a1464ed24 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/README.md +++ b/packages/@aws-cdk/aws-globalaccelerator/README.md @@ -15,7 +15,7 @@ ## Introduction -AWS Global Accelerator is a service that improves the availability and performance of your applications with local or global users. It provides static IP addresses that act as a fixed entry point to your application endpoints in a single or multiple AWS Regions, such as your Application Load Balancers, Network Load Balancers or Amazon EC2 instances. +AWS Global Accelerator (AGA) is a service that improves the availability and performance of your applications with local or global users. It provides static IP addresses that act as a fixed entry point to your application endpoints in a single or multiple AWS Regions, such as your Application Load Balancers, Network Load Balancers or Amazon EC2 instances. This module supports features under [AWS Global Accelerator](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_GlobalAccelerator.html) that allows users set up resources using the `@aws-cdk/aws-globalaccelerator` module. @@ -93,3 +93,38 @@ endpointGroup.addElasticIpAddress('EipEndpoint', eip); endpointGroup.addEc2Instance('InstanceEndpoint', instances[0]); endpointGroup.addEndpoint('InstanceEndpoint2', instances[1].instanceId); ``` + +## Accelerator Security Groups + +When using certain AGA features (client IP address preservation), AGA creates elastic network interfaces (ENI) in your AWS account which are +associated with a Security Group, and which are reused for all AGAs associated with that VPC. Per the +[best practices](https://docs.aws.amazon.com/global-accelerator/latest/dg/best-practices-aga.html) page, AGA creates a specific security group +called `GlobalAccelerator` for each VPC it has an ENI in. You can use the security groups created by AGA as a source group in other security +groups, such as those for EC2 instances or Elastic Load Balancers, in order to implement least-privilege security group rules. + +CloudFormation doesn't support referencing the security group created by AGA. CDK has a library that enables you to reference the AGA security group +for a VPC using an AwsCustomResource. + +``` +const vpc = new Vpc(stack, 'VPC', {}); +const alb = new elbv2.ApplicationLoadBalancer(stack, 'ALB', { vpc, internetFacing: false }); +const accelerator = new ga.Accelerator(stack, 'Accelerator'); +const listener = new ga.Listener(stack, 'Listener', { + accelerator, + portRanges: [ + { + fromPort: 443, + toPort: 443, + }, + ], +}); +const endpointGroup = new ga.EndpointGroup(stack, 'Group', { listener }); +endpointGroup.addLoadBalancer('AlbEndpoint', alb); + +// Remember that there is only one AGA security group per VPC. +// This code will fail at CloudFormation deployment time if you do not have an AGA +const agaSg = ga.AcceleratorSecurityGroup.fromVpc(stack, 'GlobalAcceleratorSG', vpc); + +// Allow connections from the AGA to the ALB +alb.connections.allowFrom(agaSg, Port.tcp(443)); +``` \ No newline at end of file From d1512c6fddc2fda44cc64993939adebcfc2af0ff Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 30 Jul 2020 16:58:16 +0000 Subject: [PATCH 5/7] Add dependency to guarantee order --- .../lib/accelerator-security-group.ts | 10 +++++-- .../globalaccelerator-security-group.test.ts | 30 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts index 12257ee68bf31..07f7b715157b0 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts @@ -1,6 +1,7 @@ import { ISecurityGroup, SecurityGroup, IVpc } from '@aws-cdk/aws-ec2'; import { Construct } from '@aws-cdk/core'; import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId} from '@aws-cdk/custom-resources'; +import { EndpointGroup } from '../lib'; /** * The security group used by a Global Accelerator to send traffic to resources in a VPC. @@ -16,7 +17,7 @@ export class AcceleratorSecurityGroup { * the AGA security group for a given VPC at CloudFormation deployment time, and lets you create rules for traffic from AGA * to other resources created by CDK. */ - public static fromVpc(scope: Construct, id: string, vpc: IVpc): ISecurityGroup { + public static fromVpc(scope: Construct, id: string, vpc: IVpc, endpointGroup: EndpointGroup): ISecurityGroup { // The security group name is always 'GlobalAccelerator' const globalAcceleratorSGName = 'GlobalAccelerator'; @@ -55,8 +56,13 @@ export class AcceleratorSecurityGroup { }); // Look up the security group ID - return SecurityGroup.fromSecurityGroupId(scope, + const sg = SecurityGroup.fromSecurityGroupId(scope, id, lookupAcceleratorSGCustomResource.getResponseField(ec2ResponseSGIdField)); + // We add a dependency on the endpoint group, guaranteeing that CloudFormation won't + // try and look up the SG before AGA creates it. The SG is created when a VPC resource + // is associated with an AGA + sg.node.addDependency(endpointGroup); + return sg; } } diff --git a/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts b/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts index a6d193e455a1a..dee3291139ac4 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts @@ -6,9 +6,20 @@ import { testFixture, testFixtureAlb } from './util'; test('custom resource exists', () => { // GIVEN const { stack, vpc } = testFixture(); + const accelerator = new ga.Accelerator(stack, 'Accelerator'); + const listener = new ga.Listener(stack, 'Listener', { + accelerator, + portRanges: [ + { + fromPort: 443, + toPort: 443, + }, + ], + }); + const endpointGroup = new ga.EndpointGroup(stack, 'Group', { listener }); // WHEN - ga.AcceleratorSecurityGroup.fromVpc(stack, 'GlobalAcceleratorSG', vpc); + ga.AcceleratorSecurityGroup.fromVpc(stack, 'GlobalAcceleratorSG', vpc, endpointGroup); // THEN expect(stack).to(haveResource('Custom::AWS', { @@ -37,15 +48,30 @@ test('custom resource exists', () => { responsePath: 'SecurityGroups.0.GroupId', }, }, + DependsOn: [ + 'GroupAFA0823F', + ], })); }); test('can create security group rule', () => { // GIVEN const { stack, alb, vpc } = testFixtureAlb(); + const accelerator = new ga.Accelerator(stack, 'Accelerator'); + const listener = new ga.Listener(stack, 'Listener', { + accelerator, + portRanges: [ + { + fromPort: 443, + toPort: 443, + }, + ], + }); + const endpointGroup = new ga.EndpointGroup(stack, 'Group', { listener }); + endpointGroup.addLoadBalancer('endpoint', alb); // WHEN - const sg = ga.AcceleratorSecurityGroup.fromVpc(stack, 'GlobalAcceleratorSG', vpc); + const sg = ga.AcceleratorSecurityGroup.fromVpc(stack, 'GlobalAcceleratorSG', vpc, endpointGroup); alb.connections.allowFrom(sg, Port.tcp(443)); // THEN From 81282190341d7c334308587890a2c09dab56aa64 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Thu, 30 Jul 2020 18:54:14 +0000 Subject: [PATCH 6/7] Needed to use ResourcePart.CompleteDefinition to compare the DependsOn field --- .../lib/accelerator-security-group.ts | 2 +- .../globalaccelerator-security-group.test.ts | 56 +++++++++++-------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts index 07f7b715157b0..809af55798f11 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts @@ -62,7 +62,7 @@ export class AcceleratorSecurityGroup { // We add a dependency on the endpoint group, guaranteeing that CloudFormation won't // try and look up the SG before AGA creates it. The SG is created when a VPC resource // is associated with an AGA - sg.node.addDependency(endpointGroup); + lookupAcceleratorSGCustomResource.node.addDependency(endpointGroup); return sg; } } diff --git a/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts b/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts index dee3291139ac4..c3ca726bf344c 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/test/globalaccelerator-security-group.test.ts @@ -1,4 +1,4 @@ -import { expect, haveResource } from '@aws-cdk/assert'; +import { expect, haveResource, ResourcePart } from '@aws-cdk/assert'; import { Port } from '@aws-cdk/aws-ec2'; import * as ga from '../lib'; import { testFixture, testFixtureAlb } from './util'; @@ -23,35 +23,43 @@ test('custom resource exists', () => { // THEN expect(stack).to(haveResource('Custom::AWS', { - Create: { - action: 'describeSecurityGroups', - service: 'EC2', - parameters: { - Filters: [ - { - Name: 'group-name', - Values: [ - 'GlobalAccelerator', - ], - }, - { - Name: 'vpc-id', - Values: [ - { - Ref: 'VPCB9E5F0B4', - }, - ], - }, + Properties: { + ServiceToken: { + 'Fn::GetAtt': [ + 'AWS679f53fac002430cb0da5b7982bd22872D164C4C', + 'Arn', ], }, - physicalResourceId: { - responsePath: 'SecurityGroups.0.GroupId', + Create: { + action: 'describeSecurityGroups', + service: 'EC2', + parameters: { + Filters: [ + { + Name: 'group-name', + Values: [ + 'GlobalAccelerator', + ], + }, + { + Name: 'vpc-id', + Values: [ + { + Ref: 'VPCB9E5F0B4', + }, + ], + }, + ], + }, + physicalResourceId: { + responsePath: 'SecurityGroups.0.GroupId', + }, }, }, DependsOn: [ - 'GroupAFA0823F', + 'GroupC77FDACD', ], - })); + }, ResourcePart.CompleteDefinition)); }); test('can create security group rule', () => { From 3cc28465552c8a337cb87ce99536adeb92a6d351 Mon Sep 17 00:00:00 2001 From: James Fleming Date: Mon, 10 Aug 2020 15:37:10 +0000 Subject: [PATCH 7/7] Review feedback --- packages/@aws-cdk/aws-globalaccelerator/README.md | 2 +- .../aws-globalaccelerator/lib/accelerator-security-group.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-globalaccelerator/README.md b/packages/@aws-cdk/aws-globalaccelerator/README.md index a380a1464ed24..7d32fc8c72bae 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/README.md +++ b/packages/@aws-cdk/aws-globalaccelerator/README.md @@ -99,7 +99,7 @@ endpointGroup.addEndpoint('InstanceEndpoint2', instances[1].instanceId); When using certain AGA features (client IP address preservation), AGA creates elastic network interfaces (ENI) in your AWS account which are associated with a Security Group, and which are reused for all AGAs associated with that VPC. Per the [best practices](https://docs.aws.amazon.com/global-accelerator/latest/dg/best-practices-aga.html) page, AGA creates a specific security group -called `GlobalAccelerator` for each VPC it has an ENI in. You can use the security groups created by AGA as a source group in other security +called `GlobalAccelerator` for each VPC it has an ENI in. You can use the security group created by AGA as a source group in other security groups, such as those for EC2 instances or Elastic Load Balancers, in order to implement least-privilege security group rules. CloudFormation doesn't support referencing the security group created by AGA. CDK has a library that enables you to reference the AGA security group diff --git a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts index 809af55798f11..223954e24134e 100644 --- a/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts +++ b/packages/@aws-cdk/aws-globalaccelerator/lib/accelerator-security-group.ts @@ -65,4 +65,6 @@ export class AcceleratorSecurityGroup { lookupAcceleratorSGCustomResource.node.addDependency(endpointGroup); return sg; } + + private constructor() {} }