Skip to content

Commit 35e818b

Browse files
fix(ec2): dual-stack vpc without private subnets creates EgressOnlyInternetGateway (under feature flag) (#34437)
### Issue # (if applicable) Closes #30981. ### Reason for this change -> EgressOnlyInternetGateway was been created even without any private subnets ### Description of changes -> Fixed the condition that determins if a EgressOnlyInternetGateway will be created -> Added feature flag ### Describe any new or updated permissions being added N/A ### Description of how you validated changes I added two new unit tests that checks if EgressOnlyInternetGateway is created without a private subnet ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 5197882 commit 35e818b

File tree

6 files changed

+139
-4
lines changed

6 files changed

+139
-4
lines changed

packages/aws-cdk-lib/aws-ec2/lib/vpc.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,13 @@ export class Vpc extends VpcBase {
16561656
}
16571657

16581658
// Create an Egress Only Internet Gateway and attach it if necessary
1659-
if (this.useIpv6 && this.privateSubnets) {
1659+
1660+
const isRequirePrivateSubnetsForEgressOnlyIgw =
1661+
FeatureFlags.of(this).isEnabled(cxapi.EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY);
1662+
1663+
if ((this.useIpv6 && !isRequirePrivateSubnetsForEgressOnlyIgw && this.privateSubnets) ||
1664+
(this.useIpv6 && isRequirePrivateSubnetsForEgressOnlyIgw && this.privateSubnets.length > 0)
1665+
) {
16601666
const eigw = new CfnEgressOnlyInternetGateway(this, 'EIGW6', {
16611667
vpcId: this.vpcId,
16621668
});

packages/aws-cdk-lib/aws-ec2/test/vpc.test.ts

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
22
import { Annotations, Match, Template } from '../../assertions';
33
import { App, CfnOutput, CfnResource, Fn, Lazy, Stack, Tags } from '../../core';
4-
import { EC2_RESTRICT_DEFAULT_SECURITY_GROUP } from '../../cx-api';
4+
import { EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY, EC2_RESTRICT_DEFAULT_SECURITY_GROUP } from '../../cx-api';
55
import {
66
AclCidr,
77
AclTraffic,
@@ -2747,6 +2747,90 @@ describe('vpc', () => {
27472747
},
27482748
});
27492749
});
2750+
test('EgressOnlyIGW is created if no private subnet configured in dual stack and feature flag EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY is not enabled', () => {
2751+
// GIVEN
2752+
const app = new App();
2753+
const stack = new Stack(app, 'DualStackStack');
2754+
2755+
// WHEN
2756+
const vpc = new Vpc(stack, 'Vpc', {
2757+
ipProtocol: IpProtocol.DUAL_STACK,
2758+
subnetConfiguration: [
2759+
{
2760+
subnetType: SubnetType.PUBLIC,
2761+
name: 'public',
2762+
},
2763+
],
2764+
});
2765+
2766+
// THEN
2767+
Template.fromStack(stack).resourceCountIs('AWS::EC2::EgressOnlyInternetGateway', 1);
2768+
});
2769+
test('EgressOnlyIGW is created if a private subnet is configured in dual stack and feature flag EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY is not enabled', () => {
2770+
// GIVEN
2771+
const app = new App();
2772+
const stack = new Stack(app, 'DualStackStack');
2773+
2774+
// WHEN
2775+
const vpc = new Vpc(stack, 'Vpc', {
2776+
ipProtocol: IpProtocol.DUAL_STACK,
2777+
subnetConfiguration: [
2778+
{
2779+
subnetType: SubnetType.PUBLIC,
2780+
name: 'public',
2781+
},
2782+
{
2783+
subnetType: SubnetType.PRIVATE_WITH_EGRESS,
2784+
name: 'private',
2785+
},
2786+
],
2787+
});
2788+
2789+
// THEN
2790+
Template.fromStack(stack).resourceCountIs('AWS::EC2::EgressOnlyInternetGateway', 1);
2791+
});
2792+
2793+
test('EgressOnlyIGW is created if a private subnet is configured in dual stack and feature flag EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY is enabled', () => {
2794+
// GIVEN
2795+
const app = new App();
2796+
const stack = new Stack(app, 'DualStackStack');
2797+
// WHEN
2798+
stack.node.setContext(EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY, true);
2799+
const vpc = new Vpc(stack, 'Vpc', {
2800+
ipProtocol: IpProtocol.DUAL_STACK,
2801+
subnetConfiguration: [
2802+
{
2803+
subnetType: SubnetType.PUBLIC,
2804+
name: 'public',
2805+
},
2806+
{
2807+
subnetType: SubnetType.PRIVATE_WITH_EGRESS,
2808+
name: 'private',
2809+
},
2810+
],
2811+
});
2812+
2813+
// THEN
2814+
Template.fromStack(stack).resourceCountIs('AWS::EC2::EgressOnlyInternetGateway', 1);
2815+
});
2816+
test('EgressOnlyIGW is not created if no private subnet is configured in dual stack and feature flag EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY is enabled', () => {
2817+
// GIVEN
2818+
const app = new App();
2819+
const stack = new Stack(app, 'DualStackStack');
2820+
stack.node.setContext(EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY, true);
2821+
// WHEN
2822+
const vpc = new Vpc(stack, 'Vpc', {
2823+
ipProtocol: IpProtocol.DUAL_STACK,
2824+
subnetConfiguration: [
2825+
{
2826+
subnetType: SubnetType.PUBLIC,
2827+
name: 'public',
2828+
},
2829+
],
2830+
});
2831+
// THEN
2832+
Template.fromStack(stack).resourceCountIs('AWS::EC2::EgressOnlyInternetGateway', 0);
2833+
});
27502834

27512835
test('error should occur if IPv6 properties are provided for a non-dual-stack VPC', () => {
27522836
// GIVEN

packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ Flags come in three types:
101101
| [@aws-cdk/core:aspectPrioritiesMutating](#aws-cdkcoreaspectprioritiesmutating) | When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING. | 2.189.1 | new default |
102102
| [@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions](#aws-cdks3-notificationsadds3trustkeypolicyforsnssubscriptions) | Add an S3 trust policy to a KMS key resource policy for SNS subscriptions. | 2.195.0 | fix |
103103
| [@aws-cdk/aws-s3:publicAccessBlockedByDefault](#aws-cdkaws-s3publicaccessblockedbydefault) | When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined. | V2NEXT | fix |
104+
| [@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway](#aws-cdkaws-ec2requireprivatesubnetsforegressonlyinternetgateway) | When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC. | V2NEXT | fix |
104105

105106
<!-- END table -->
106107

@@ -185,7 +186,8 @@ The following json shows the current recommended set of flags, as `cdk init` wou
185186
"@aws-cdk/aws-dynamodb:retainTableReplica": true,
186187
"@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": true,
187188
"@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": true,
188-
"@aws-cdk/aws-s3:publicAccessBlockedByDefault": true
189+
"@aws-cdk/aws-s3:publicAccessBlockedByDefault": true,
190+
"@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": true
189191
}
190192
}
191193
```
@@ -2125,4 +2127,19 @@ The new behavior from this feature will allow a user, for example, to set 1 of t
21252127
| V2NEXT | `false` | `true` |
21262128

21272129

2130+
### @aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway
2131+
2132+
*When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC.*
2133+
2134+
Flag type: Backwards incompatible bugfix
2135+
2136+
When this feature flag is enabled, EgressOnlyGateway resource will not be created when you create a vpc with only public subnets.
2137+
2138+
2139+
| Since | Default | Recommended |
2140+
| ----- | ----- | ----- |
2141+
| (not in v1) | | |
2142+
| V2NEXT | `false` | `true` |
2143+
2144+
21282145
<!-- END details -->

packages/aws-cdk-lib/cx-api/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,18 @@ _cdk.json_
732732
}
733733
}
734734
```
735+
736+
* `@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway`
737+
738+
When this feature flag is enabled, EgressOnlyGateway is created only for dual-stack VPC with private subnets
739+
740+
When this feature flag is disabled, EgressOnlyGateway resource is created for all dual-stack VPC regardless of subnet type
741+
742+
_cdk.json_
743+
744+
```json
745+
{
746+
"context": {
747+
"@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": true
748+
}
749+
}

packages/aws-cdk-lib/cx-api/lib/features.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export const DYNAMODB_TABLE_RETAIN_TABLE_REPLICA = '@aws-cdk/aws-dynamodb:retain
137137
export const LOG_USER_POOL_CLIENT_SECRET_VALUE = '@aws-cdk/cognito:logUserPoolClientSecretValue';
138138
export const PIPELINE_REDUCE_CROSS_ACCOUNT_ACTION_ROLE_TRUST_SCOPE = '@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope';
139139
export const S3_TRUST_KEY_POLICY_FOR_SNS_SUBSCRIPTIONS = '@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions';
140+
export const EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY = '@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway';
140141
export const USE_RESOURCEID_FOR_VPCV2_MIGRATION = '@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration';
141142
export const S3_PUBLIC_ACCESS_BLOCKED_BY_DEFAULT = '@aws-cdk/aws-s3:publicAccessBlockedByDefault';
142143

@@ -1578,6 +1579,17 @@ export const FLAGS: Record<string, FlagInfo> = {
15781579
},
15791580

15801581
//////////////////////////////////////////////////////////////////////
1582+
[EC2_REQUIRE_PRIVATE_SUBNETS_FOR_EGRESSONLYINTERNETGATEWAY]: {
1583+
type: FlagType.BugFix,
1584+
summary: 'When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC.',
1585+
detailsMd: `
1586+
When this feature flag is enabled, EgressOnlyGateway resource will not be created when you create a vpc with only public subnets.
1587+
`,
1588+
introducedIn: { v2: 'V2NEXT' },
1589+
recommendedValue: true,
1590+
},
1591+
1592+
/// ///////////////////////////////////////////////////////////////////
15811593
[USE_RESOURCEID_FOR_VPCV2_MIGRATION]: {
15821594
type: FlagType.ApiDefault,
15831595
summary: 'When enabled, use resource IDs for VPC V2 migration',

packages/aws-cdk-lib/recommended-feature-flags.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,6 @@
7272
"@aws-cdk/aws-dynamodb:retainTableReplica": true,
7373
"@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": true,
7474
"@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": true,
75-
"@aws-cdk/aws-s3:publicAccessBlockedByDefault": true
75+
"@aws-cdk/aws-s3:publicAccessBlockedByDefault": true,
76+
"@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": true
7677
}

0 commit comments

Comments
 (0)