diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.alb-ecs-service-command-entry-point.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.alb-ecs-service-command-entry-point.ts index 2983ad23728fc..bdbcbf8d8b006 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.alb-ecs-service-command-entry-point.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.alb-ecs-service-command-entry-point.ts @@ -8,6 +8,8 @@ import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'; const app = new cdk.App({ postCliContext: { '@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, }, }); const stack = new cdk.Stack(app, 'aws-ecs-integ-alb-ec2-cmd-entrypoint'); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.application-load-balanced-ecs-service.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.application-load-balanced-ecs-service.ts index b765af9dd41df..cb8e0bf60983c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.application-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.application-load-balanced-ecs-service.ts @@ -6,7 +6,12 @@ import * as integ from '@aws-cdk/integ-tests-alpha'; import { ApplicationLoadBalancedEc2Service } from 'aws-cdk-lib/aws-ecs-patterns'; import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; -const app = new App(); +const app = new App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new Stack(app, 'aws-ecs-integ-alb'); const vpc = new Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); const cluster = new Cluster(stack, 'Cluster', { vpc }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-application-load-balanced-ecs-service.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-application-load-balanced-ecs-service.ts index 09c61744a0ad1..3681f8d4a5ab7 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-application-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-application-load-balanced-ecs-service.ts @@ -7,7 +7,12 @@ import { IntegTest } from '@aws-cdk/integ-tests-alpha'; import { ApplicationMultipleTargetGroupsEc2Service } from 'aws-cdk-lib/aws-ecs-patterns'; -const app = new App(); +const app = new App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new Stack(app, 'aws-ecs-integ-multiple-alb-healthchecks'); const vpc = new Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); const cluster = new Cluster(stack, 'Cluster', { vpc }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-network-load-balanced-ecs-service.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-network-load-balanced-ecs-service.ts index 26172a7ec9bf7..eb7ba7af9649f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-network-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.healthchecks-multiple-network-load-balanced-ecs-service.ts @@ -5,7 +5,12 @@ import { App, Stack } from 'aws-cdk-lib'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; import { NetworkMultipleTargetGroupsEc2Service } from 'aws-cdk-lib/aws-ecs-patterns'; -const app = new App(); +const app = new App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new Stack(app, 'aws-ecs-integ-nlb-healthchecks'); const vpc = new Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); const cluster = new Cluster(stack, 'Cluster', { vpc }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service-idle-timeout.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service-idle-timeout.ts index 38e51b7d64a87..f83d722c97b29 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service-idle-timeout.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service-idle-timeout.ts @@ -12,6 +12,8 @@ const app = new App({ postCliContext: { '@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm': false, '@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, }, }); const stack = new Stack(app, 'aws-ecs-integ-alb-idle-timeout'); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.ts index dfbaf2e4e5f42..3788182dc2957 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.multiple-application-load-balanced-ecs-service.ts @@ -9,6 +9,8 @@ const app = new App({ postCliContext: { [AUTOSCALING_GENERATE_LAUNCH_TEMPLATE]: false, [REDUCE_EC2_FARGATE_CLOUDWATCH_PERMISSIONS]: false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, }, }); const stack = new Stack(app, 'aws-ecs-integ-multiple-alb'); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.network-load-balanced-ecs-service.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.network-load-balanced-ecs-service.ts index 8c3bdeff260c7..0b9f2abe9756e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.network-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.network-load-balanced-ecs-service.ts @@ -6,7 +6,12 @@ import * as integ from '@aws-cdk/integ-tests-alpha'; import { NetworkLoadBalancedEc2Service } from 'aws-cdk-lib/aws-ecs-patterns'; import { IpAddressType } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; -const app = new App(); +const app = new App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new Stack(app, 'aws-ecs-integ-nlb'); const vpc = new Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); const cluster = new Cluster(stack, 'Cluster', { vpc }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.ts index fa37055b431f3..8460098c3c87c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.scheduled-ecs-task.ts @@ -5,7 +5,12 @@ import * as cdk from 'aws-cdk-lib'; import * as integ from '@aws-cdk/integ-tests-alpha'; import { ScheduledEc2Task } from 'aws-cdk-lib/aws-ecs-patterns'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); class EventStack extends cdk.Stack { constructor(scope: cdk.App, id: string) { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.tls-network-load-balanced-ecs-service.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.tls-network-load-balanced-ecs-service.ts index 893295167780d..26254a735f8e9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.tls-network-load-balanced-ecs-service.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs-patterns/test/ec2/integ.tls-network-load-balanced-ecs-service.ts @@ -11,7 +11,12 @@ import { Certificate } from 'aws-cdk-lib/aws-certificatemanager'; const certArn = process.env.CDK_INTEG_CERT_ARN || process.env.CERT_ARN; if (!certArn) throw new Error('For this test you must provide your own Certificate as an env var "CERT_ARN". See framework-integ/README.md for details.'); -const app = new App(); +const app = new App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new Stack(app, 'tls-network-load-balanced-ecs-service'); const vpc = new Vpc(stack, 'Vpc', { maxAzs: 2 }); const cluster = new Cluster(stack, 'Cluster', { vpc }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.app-mesh-proxy-config.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.app-mesh-proxy-config.ts index ae71fd9d78f76..7bd89d55cccc8 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.app-mesh-proxy-config.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.app-mesh-proxy-config.ts @@ -2,7 +2,12 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-appmesh-proxy'); // Create a cluster diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts index 1f7fff205d7ee..6675d688954e0 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider-managed-draining.ts @@ -7,6 +7,8 @@ import * as integ from '@aws-cdk/integ-tests-alpha'; const app = new cdk.App({ postCliContext: { '@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, }, }); const stack = new cdk.Stack(app, 'integ-ec2-capacity-provider-managed-draining'); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider.ts index 8bbb65a470a8e..e6f9333b79ec4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.capacity-provider.ts @@ -3,7 +3,12 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'integ-ec2-capacity-provider'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.clb-host-nw.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.clb-host-nw.ts index 223a9929d6f84..17f7bc2022961 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.clb-host-nw.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.clb-host-nw.ts @@ -3,7 +3,12 @@ import * as elb from 'aws-cdk-lib/aws-elasticloadbalancing'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.cloudmap-container-port.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.cloudmap-container-port.ts index ba0c009dfa425..0882ca3f65181 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.cloudmap-container-port.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.cloudmap-container-port.ts @@ -3,7 +3,12 @@ import * as cloudmap from 'aws-cdk-lib/aws-servicediscovery'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ'); const vpc = new ec2.Vpc(stack, 'Vpc', { restrictDefaultSecurityGroup: false, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.default-capacity-provider.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.default-capacity-provider.ts index 6cea48957a5fb..bda14d047446b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.default-capacity-provider.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.default-capacity-provider.ts @@ -4,7 +4,12 @@ import * as cdk from 'aws-cdk-lib'; import * as integ from '@aws-cdk/integ-tests-alpha'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'integ-default-capacity-provider'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.deployment-alarms.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.deployment-alarms.ts index 6e5dfebfa4f9c..6e5ca339d20a8 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.deployment-alarms.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.deployment-alarms.ts @@ -5,7 +5,12 @@ import * as cdk from 'aws-cdk-lib'; import * as integ from '@aws-cdk/integ-tests-alpha'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'integ-deployment-alarms'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2 }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.enable-execute-command.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.enable-execute-command.ts index fe6e9a8404470..662b57b40c399 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.enable-execute-command.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.enable-execute-command.ts @@ -9,6 +9,8 @@ import * as ecs from 'aws-cdk-lib/aws-ecs'; const app = new cdk.App({ postCliContext: { '@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, }, }); const stack = new cdk.Stack(app, 'aws-ecs-integ-enable-execute-command'); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts index 2a862f4de6c19..627fbb6746dc6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts @@ -7,7 +7,12 @@ import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ'); // S3 bucket to host envfile without public access diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.exec-command.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.exec-command.ts index 1cbfe8c447394..2afd7db903d4b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.exec-command.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.exec-command.ts @@ -5,7 +5,12 @@ import * as s3 from 'aws-cdk-lib/aws-s3'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-exec-command'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.firelens-s3-config.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.firelens-s3-config.ts index d026759ee68e7..54bc029a6ed43 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.firelens-s3-config.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.firelens-s3-config.ts @@ -4,7 +4,12 @@ import * as s3_assets from 'aws-cdk-lib/aws-s3-assets'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.graviton.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.graviton.ts index 7c280aff6ae80..79bc54cf617b6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.graviton.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.graviton.ts @@ -2,7 +2,12 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-awsvpc-nw.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-awsvpc-nw.ts index 8667d63c7c143..20c4c4168afe7 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-awsvpc-nw.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-awsvpc-nw.ts @@ -3,7 +3,12 @@ import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-bridge-nw.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-bridge-nw.ts index 93a7a3d465aa1..1baa11f71a67f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-bridge-nw.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.lb-bridge-nw.ts @@ -4,7 +4,12 @@ import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-ecs'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-constraint-default-empty.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-constraint-default-empty.ts index 873f168670aeb..5f6d5ce3731df 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-constraint-default-empty.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-constraint-default-empty.ts @@ -4,7 +4,12 @@ import { Construct } from 'constructs'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); // WHEN class EcsStack extends cdk.Stack { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts index 92350f2b710e2..ce17e5db4ac13 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.placement-strategies.ts @@ -3,7 +3,12 @@ import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); class EcsStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.pseudo-terminal.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.pseudo-terminal.ts index dd396281e86fb..9a3cc9c943262 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.pseudo-terminal.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.pseudo-terminal.ts @@ -3,7 +3,12 @@ import * as cdk from 'aws-cdk-lib'; import * as integ from '@aws-cdk/integ-tests-alpha'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-pseudo-terminal'); // Create a cluster diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-awsvpc-nw.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-awsvpc-nw.ts index 4a3923cf384bf..ef3ed277e88d3 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-awsvpc-nw.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-awsvpc-nw.ts @@ -2,7 +2,12 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-ecs'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-bridge-nw.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-bridge-nw.ts index 0e6d11b6fe8d7..09b26a9e12a6b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-bridge-nw.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.sd-bridge-nw.ts @@ -2,7 +2,12 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-ecs'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.spot-drain.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.spot-drain.ts index c5a49abdec8a5..818fffcd59576 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.spot-drain.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.spot-drain.ts @@ -2,7 +2,12 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-spot'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.swap-parameters.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.swap-parameters.ts index 8ce87e7240f50..680d22d9b3e4d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.swap-parameters.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.swap-parameters.ts @@ -4,7 +4,12 @@ import * as integ from '@aws-cdk/integ-tests-alpha'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import { LinuxParameters } from 'aws-cdk-lib/aws-ecs'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.task-definition-placement-constraints.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.task-definition-placement-constraints.ts index 84170fdce75ee..0c55c74456a39 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.task-definition-placement-constraints.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.task-definition-placement-constraints.ts @@ -3,7 +3,12 @@ import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-cdk-ecs-integration-test-stack'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2 }); const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-amazonlinux2-neuron-ami.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-amazonlinux2-neuron-ami.ts index d5c6ec7036d74..8199e582c5c3c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-amazonlinux2-neuron-ami.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-amazonlinux2-neuron-ami.ts @@ -4,7 +4,12 @@ import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as integ from '@aws-cdk/integ-tests-alpha'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'integ-ecs-neuron-ami'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts index 9bb84fd52424f..ed15bf7804937 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-imported.ts @@ -4,7 +4,12 @@ import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as integ from '@aws-cdk/integ-tests-alpha'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'integ-ecs-imported-cluster'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-windows-server-ami.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-windows-server-ami.ts index b55d07c270705..9e5c97cff801c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-windows-server-ami.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-windows-server-ami.ts @@ -5,7 +5,12 @@ import * as cdk from 'aws-cdk-lib'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as integ from '@aws-cdk/integ-tests-alpha'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'integ-ecs-windows-server-ami'); const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 1 }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/ClusterAL2023DefaultTestDeployAssert19111415.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/ClusterAL2023DefaultTestDeployAssert19111415.assets.json new file mode 100644 index 0000000000000..ee34f51b00bf4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/ClusterAL2023DefaultTestDeployAssert19111415.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "ClusterAL2023DefaultTestDeployAssert19111415.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/ClusterAL2023DefaultTestDeployAssert19111415.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/ClusterAL2023DefaultTestDeployAssert19111415.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/ClusterAL2023DefaultTestDeployAssert19111415.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c6e612584e352 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ-ecs-al2023-ami.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ-ecs-al2023-ami.assets.json new file mode 100644 index 0000000000000..dc91f134d9af6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ-ecs-al2023-ami.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "f875639342074982d90d3f026dd2a665ec32849787c8c2fee81f9a8dd2f1f58d": { + "source": { + "path": "integ-ecs-al2023-ami.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "f875639342074982d90d3f026dd2a665ec32849787c8c2fee81f9a8dd2f1f58d.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ-ecs-al2023-ami.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ-ecs-al2023-ami.template.json new file mode 100644 index 0000000000000..13f9ef83aa094 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ-ecs-al2023-ami.template.json @@ -0,0 +1,827 @@ +{ + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/17", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1RouteTableAssociation97140677": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "VpcPublicSubnet1DefaultRoute3DA9E72A": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet1EIPD7E02669": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1RouteTableAssociation97140677" + ] + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/17", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "ClusterEB0386A7": { + "Type": "AWS::ECS::Cluster" + }, + "Cluster3DA9CCBA": { + "Type": "AWS::ECS::ClusterCapacityProviderAssociations", + "Properties": { + "CapacityProviders": [ + { + "Ref": "EC2CapacityProvider5A2E35CD" + } + ], + "Cluster": { + "Ref": "ClusterEB0386A7" + }, + "DefaultCapacityProviderStrategy": [] + } + }, + "InstanceRole3CCE2F1D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AmazonEC2ContainerServiceForEC2Role" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonSSMManagedInstanceCore" + ] + ] + } + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "InstanceRoleDefaultPolicy1531605C": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "cloudformation:SignalResource", + "Effect": "Allow", + "Resource": { + "Ref": "AWS::StackId" + } + }, + { + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:Poll", + "ecs:StartTelemetrySession" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecr:GetAuthorizationToken", + "ecs:DiscoverPollEndpoint", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "InstanceRoleDefaultPolicy1531605C", + "Roles": [ + { + "Ref": "InstanceRole3CCE2F1D" + } + ] + } + }, + "ASGInstanceSecurityGroup0525485D": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "integ-ecs-al2023-ami/ASG/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "ASGInstanceProfile0A2834D7": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "InstanceRole3CCE2F1D" + } + ] + } + }, + "ASGLaunchTemplate0CA92847": { + "Type": "AWS::EC2::LaunchTemplate", + "Properties": { + "LaunchTemplateData": { + "IamInstanceProfile": { + "Arn": { + "Fn::GetAtt": [ + "ASGInstanceProfile0A2834D7", + "Arn" + ] + } + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2023recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t2.micro", + "Monitoring": { + "Enabled": false + }, + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "ASGInstanceSecurityGroup0525485D", + "GroupId" + ] + } + ], + "TagSpecifications": [ + { + "ResourceType": "instance", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG/LaunchTemplate" + } + ] + }, + { + "ResourceType": "volume", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG/LaunchTemplate" + } + ] + } + ], + "UserData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "#!/bin/bash\nset -x\nset -e\necho ECS_CLUSTER=", + { + "Ref": "ClusterEB0386A7" + }, + " >> /etc/ecs/ecs.config\nsudo yum install -y iptables-services; sudo iptables --insert DOCKER-USER 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo iptables-save | sudo tee /etc/sysconfig/iptables && sudo systemctl enable --now iptables\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config\nyum install -y aws-cfn-bootstrap\n/opt/aws/bin/cfn-signal -e $? --stack ", + { + "Ref": "AWS::StackId" + }, + " --resource ASG46ED3070 --region ", + { + "Ref": "AWS::Region" + } + ] + ] + } + } + }, + "TagSpecifications": [ + { + "ResourceType": "launch-template", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG/LaunchTemplate" + } + ] + } + ] + }, + "DependsOn": [ + "InstanceRoleDefaultPolicy1531605C", + "InstanceRole3CCE2F1D" + ] + }, + "ASG46ED3070": { + "Type": "AWS::AutoScaling::AutoScalingGroup", + "Properties": { + "LaunchTemplate": { + "LaunchTemplateId": { + "Ref": "ASGLaunchTemplate0CA92847" + }, + "Version": { + "Fn::GetAtt": [ + "ASGLaunchTemplate0CA92847", + "LatestVersionNumber" + ] + } + }, + "MaxSize": "1", + "MinSize": "1", + "Tags": [ + { + "Key": "Name", + "PropagateAtLaunch": true, + "Value": "integ-ecs-al2023-ami/ASG" + } + ], + "VPCZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + ] + }, + "CreationPolicy": { + "ResourceSignal": { + "Count": 1, + "Timeout": "PT10M" + } + }, + "UpdatePolicy": { + "AutoScalingScheduledAction": { + "IgnoreUnmodifiedGroupSizeProperties": true + } + } + }, + "ASGDrainECSHookFunctionServiceRoleC12963BB": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG" + } + ] + } + }, + "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeHosts", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "autoscaling:CompleteLifecycleAction", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":autoscaling:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":autoScalingGroup:*:autoScalingGroupName/", + { + "Ref": "ASG46ED3070" + } + ] + ] + } + }, + { + "Action": [ + "ecs:DescribeContainerInstances", + "ecs:DescribeTasks", + "ecs:ListTasks", + "ecs:UpdateContainerInstancesState" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:ListContainerInstances", + "ecs:SubmitContainerStateChange", + "ecs:SubmitTaskStateChange" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "Roles": [ + { + "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ] + } + }, + "ASGDrainECSHookFunction5F24CF4D": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + }, + "Environment": { + "Variables": { + "CLUSTER": { + "Ref": "ClusterEB0386A7" + } + } + }, + "Handler": "index.lambda_handler", + "Role": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunctionServiceRoleC12963BB", + "Arn" + ] + }, + "Runtime": "python3.9", + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG" + } + ], + "Timeout": 310 + }, + "DependsOn": [ + "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "ASGDrainECSHookFunctionServiceRoleC12963BB" + ] + }, + "ASGDrainECSHookFunctionAllowInvokeintegecsal2023amiASGLifecycleHookDrainHookTopic083F299FF8F99189": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "Principal": "sns.amazonaws.com", + "SourceArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "ASGDrainECSHookFunctionTopicD6FC59F7": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Endpoint": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "Protocol": "lambda", + "TopicArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "ASGLifecycleHookDrainHookTopicA8AD4ACB": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG" + } + ] + } + }, + "ASGLifecycleHookDrainHookRoleD640316C": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "autoscaling.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "integ-ecs-al2023-ami/ASG" + } + ] + } + }, + "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "Roles": [ + { + "Ref": "ASGLifecycleHookDrainHookRoleD640316C" + } + ] + } + }, + "ASGLifecycleHookDrainHookFE4AFEBE": { + "Type": "AWS::AutoScaling::LifecycleHook", + "Properties": { + "AutoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "DefaultResult": "CONTINUE", + "HeartbeatTimeout": 300, + "LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", + "NotificationTargetARN": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + }, + "RoleARN": { + "Fn::GetAtt": [ + "ASGLifecycleHookDrainHookRoleD640316C", + "Arn" + ] + } + }, + "DependsOn": [ + "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "ASGLifecycleHookDrainHookRoleD640316C" + ] + }, + "EC2CapacityProvider5A2E35CD": { + "Type": "AWS::ECS::CapacityProvider", + "Properties": { + "AutoScalingGroupProvider": { + "AutoScalingGroupArn": { + "Ref": "ASG46ED3070" + }, + "ManagedScaling": { + "Status": "ENABLED", + "TargetCapacity": 100 + }, + "ManagedTerminationProtection": "DISABLED" + } + } + } + }, + "Parameters": { + "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2023recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ.json new file mode 100644 index 0000000000000..483e48bdbbc38 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "38.0.1", + "testCases": { + "ClusterAL2023/DefaultTest": { + "stacks": [ + "integ-ecs-al2023-ami" + ], + "assertionStack": "ClusterAL2023/DefaultTest/DeployAssert", + "assertionStackName": "ClusterAL2023DefaultTestDeployAssert19111415" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/manifest.json new file mode 100644 index 0000000000000..175636b354cc9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/manifest.json @@ -0,0 +1,299 @@ +{ + "version": "38.0.1", + "artifacts": { + "integ-ecs-al2023-ami.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-ecs-al2023-ami.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-ecs-al2023-ami": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-ecs-al2023-ami.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f875639342074982d90d3f026dd2a665ec32849787c8c2fee81f9a8dd2f1f58d.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-ecs-al2023-ami.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integ-ecs-al2023-ami.assets" + ], + "metadata": { + "/integ-ecs-al2023-ami/Vpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpc8378EB38" + } + ], + "/integ-ecs-al2023-ami/Vpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1Subnet5C2D37C4" + } + ], + "/integ-ecs-al2023-ami/Vpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTable6C95E38E" + } + ], + "/integ-ecs-al2023-ami/Vpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTableAssociation97140677" + } + ], + "/integ-ecs-al2023-ami/Vpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1DefaultRoute3DA9E72A" + } + ], + "/integ-ecs-al2023-ami/Vpc/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1EIPD7E02669" + } + ], + "/integ-ecs-al2023-ami/Vpc/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1NATGateway4D7517AA" + } + ], + "/integ-ecs-al2023-ami/Vpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1Subnet536B997A" + } + ], + "/integ-ecs-al2023-ami/Vpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableB2C5B500" + } + ], + "/integ-ecs-al2023-ami/Vpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableAssociation70C59FA6" + } + ], + "/integ-ecs-al2023-ami/Vpc/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1DefaultRouteBE02A9ED" + } + ], + "/integ-ecs-al2023-ami/Vpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIGWD7BA715C" + } + ], + "/integ-ecs-al2023-ami/Vpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcVPCGWBF912B6E" + } + ], + "/integ-ecs-al2023-ami/Cluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ClusterEB0386A7" + } + ], + "/integ-ecs-al2023-ami/Cluster/Cluster": [ + { + "type": "aws:cdk:logicalId", + "data": "Cluster3DA9CCBA" + } + ], + "/integ-ecs-al2023-ami/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceRole3CCE2F1D" + } + ], + "/integ-ecs-al2023-ami/InstanceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceRoleDefaultPolicy1531605C" + } + ], + "/integ-ecs-al2023-ami/ASG/InstanceSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceSecurityGroup0525485D" + } + ], + "/integ-ecs-al2023-ami/ASG/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGInstanceProfile0A2834D7" + } + ], + "/integ-ecs-al2023-ami/ASG/LaunchTemplate/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLaunchTemplate0CA92847" + } + ], + "/integ-ecs-al2023-ami/ASG/ASG": [ + { + "type": "aws:cdk:logicalId", + "data": "ASG46ED3070" + } + ], + "/integ-ecs-al2023-ami/ASG/DrainECSHook/Function/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ], + "/integ-ecs-al2023-ami/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27" + } + ], + "/integ-ecs-al2023-ami/ASG/DrainECSHook/Function/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunction5F24CF4D" + } + ], + "/integ-ecs-al2023-ami/ASG/DrainECSHook/Function/AllowInvoke:integecsal2023amiASGLifecycleHookDrainHookTopic083F299F": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionAllowInvokeintegecsal2023amiASGLifecycleHookDrainHookTopic083F299FF8F99189" + } + ], + "/integ-ecs-al2023-ami/ASG/DrainECSHook/Function/Topic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGDrainECSHookFunctionTopicD6FC59F7" + } + ], + "/integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Topic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + ], + "/integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookRoleD640316C" + } + ], + "/integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57" + } + ], + "/integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ASGLifecycleHookDrainHookFE4AFEBE" + } + ], + "/integ-ecs-al2023-ami/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2023--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2023recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/integ-ecs-al2023-ami/EC2CapacityProvider/EC2CapacityProvider": [ + { + "type": "aws:cdk:logicalId", + "data": "EC2CapacityProvider5A2E35CD" + } + ], + "/integ-ecs-al2023-ami/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-ecs-al2023-ami/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-ecs-al2023-ami" + }, + "ClusterAL2023DefaultTestDeployAssert19111415.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ClusterAL2023DefaultTestDeployAssert19111415.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ClusterAL2023DefaultTestDeployAssert19111415": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ClusterAL2023DefaultTestDeployAssert19111415.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ClusterAL2023DefaultTestDeployAssert19111415.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ClusterAL2023DefaultTestDeployAssert19111415.assets" + ], + "metadata": { + "/ClusterAL2023/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ClusterAL2023/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ClusterAL2023/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/tree.json new file mode 100644 index 0000000000000..7da3a829f5650 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.js.snapshot/tree.json @@ -0,0 +1,1357 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-ecs-al2023-ami": { + "id": "integ-ecs-al2023-ami", + "path": "integ-ecs-al2023-ami", + "children": { + "Vpc": { + "id": "Vpc", + "path": "integ-ecs-al2023-ami/Vpc", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/Vpc/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/17", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + }, + "subnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "integ-ecs-al2023-ami/Vpc/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/17", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + }, + "subnetId": { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "integ-ecs-al2023-ami/Vpc/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" + }, + "routeTableId": { + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "integ-ecs-al2023-ami/Vpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "integ-ecs-al2023-ami/Vpc/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "Cluster": { + "id": "Cluster", + "path": "integ-ecs-al2023-ami/Cluster", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/Cluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Cluster", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnCluster", + "version": "0.0.0" + } + }, + "Cluster": { + "id": "Cluster", + "path": "integ-ecs-al2023-ami/Cluster/Cluster", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::ClusterCapacityProviderAssociations", + "aws:cdk:cloudformation:props": { + "capacityProviders": [ + { + "Ref": "EC2CapacityProvider5A2E35CD" + } + ], + "cluster": { + "Ref": "ClusterEB0386A7" + }, + "defaultCapacityProviderStrategy": [] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnClusterCapacityProviderAssociations", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.Cluster", + "version": "0.0.0" + } + }, + "InstanceRole": { + "id": "InstanceRole", + "path": "integ-ecs-al2023-ami/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "integ-ecs-al2023-ami/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AmazonEC2ContainerServiceForEC2Role" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonSSMManagedInstanceCore" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ecs-al2023-ami/InstanceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/InstanceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "cloudformation:SignalResource", + "Effect": "Allow", + "Resource": { + "Ref": "AWS::StackId" + } + }, + { + "Action": [ + "ecs:DeregisterContainerInstance", + "ecs:RegisterContainerInstance", + "ecs:Submit*" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + }, + { + "Action": [ + "ecs:Poll", + "ecs:StartTelemetrySession" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecr:GetAuthorizationToken", + "ecs:DiscoverPollEndpoint", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "InstanceRoleDefaultPolicy1531605C", + "roles": [ + { + "Ref": "InstanceRole3CCE2F1D" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "ASG": { + "id": "ASG", + "path": "integ-ecs-al2023-ami/ASG", + "children": { + "InstanceSecurityGroup": { + "id": "InstanceSecurityGroup", + "path": "integ-ecs-al2023-ami/ASG/InstanceSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/InstanceSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "integ-ecs-al2023-ami/ASG/InstanceSecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "integ-ecs-al2023-ami/ASG/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "InstanceRole3CCE2F1D" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "ImportedInstanceProfile": { + "id": "ImportedInstanceProfile", + "path": "integ-ecs-al2023-ami/ASG/ImportedInstanceProfile", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "LaunchTemplate": { + "id": "LaunchTemplate", + "path": "integ-ecs-al2023-ami/ASG/LaunchTemplate", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/LaunchTemplate/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::LaunchTemplate", + "aws:cdk:cloudformation:props": { + "launchTemplateData": { + "iamInstanceProfile": { + "arn": { + "Fn::GetAtt": [ + "ASGInstanceProfile0A2834D7", + "Arn" + ] + } + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceecsoptimizedamiamazonlinux2023recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t2.micro", + "monitoring": { + "enabled": false + }, + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "ASGInstanceSecurityGroup0525485D", + "GroupId" + ] + } + ], + "tagSpecifications": [ + { + "resourceType": "instance", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG/LaunchTemplate" + } + ] + }, + { + "resourceType": "volume", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG/LaunchTemplate" + } + ] + } + ], + "userData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "#!/bin/bash\nset -x\nset -e\necho ECS_CLUSTER=", + { + "Ref": "ClusterEB0386A7" + }, + " >> /etc/ecs/ecs.config\nsudo yum install -y iptables-services; sudo iptables --insert DOCKER-USER 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo iptables-save | sudo tee /etc/sysconfig/iptables && sudo systemctl enable --now iptables\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config\nyum install -y aws-cfn-bootstrap\n/opt/aws/bin/cfn-signal -e $? --stack ", + { + "Ref": "AWS::StackId" + }, + " --resource ASG46ED3070 --region ", + { + "Ref": "AWS::Region" + } + ] + ] + } + } + }, + "tagSpecifications": [ + { + "resourceType": "launch-template", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG/LaunchTemplate" + } + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnLaunchTemplate", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.LaunchTemplate", + "version": "0.0.0" + } + }, + "ASG": { + "id": "ASG", + "path": "integ-ecs-al2023-ami/ASG/ASG", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::AutoScalingGroup", + "aws:cdk:cloudformation:props": { + "launchTemplate": { + "launchTemplateId": { + "Ref": "ASGLaunchTemplate0CA92847" + }, + "version": { + "Fn::GetAtt": [ + "ASGLaunchTemplate0CA92847", + "LatestVersionNumber" + ] + } + }, + "maxSize": "1", + "minSize": "1", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG", + "propagateAtLaunch": true + } + ], + "vpcZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.CfnAutoScalingGroup", + "version": "0.0.0" + } + }, + "DrainECSHook": { + "id": "DrainECSHook", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook", + "children": { + "Function": { + "id": "Function", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ], + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeHosts", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "autoscaling:CompleteLifecycleAction", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":autoscaling:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":autoScalingGroup:*:autoScalingGroupName/", + { + "Ref": "ASG46ED3070" + } + ] + ] + } + }, + { + "Action": [ + "ecs:DescribeContainerInstances", + "ecs:DescribeTasks", + "ecs:ListTasks", + "ecs:UpdateContainerInstancesState" + ], + "Condition": { + "ArnEquals": { + "ecs:cluster": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecs:ListContainerInstances", + "ecs:SubmitContainerStateChange", + "ecs:SubmitTaskStateChange" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "ClusterEB0386A7", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGDrainECSHookFunctionServiceRoleDefaultPolicy16848A27", + "roles": [ + { + "Ref": "ASGDrainECSHookFunctionServiceRoleC12963BB" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "import boto3, json, os, time\n\necs = boto3.client('ecs')\nautoscaling = boto3.client('autoscaling')\n\n\ndef lambda_handler(event, context):\n print(json.dumps(dict(event, ResponseURL='...')))\n cluster = os.environ['CLUSTER']\n snsTopicArn = event['Records'][0]['Sns']['TopicArn']\n lifecycle_event = json.loads(event['Records'][0]['Sns']['Message'])\n instance_id = lifecycle_event.get('EC2InstanceId')\n if not instance_id:\n print('Got event without EC2InstanceId: %s', json.dumps(dict(event, ResponseURL='...')))\n return\n\n instance_arn = container_instance_arn(cluster, instance_id)\n print('Instance %s has container instance ARN %s' % (lifecycle_event['EC2InstanceId'], instance_arn))\n\n if not instance_arn:\n return\n\n task_arns = container_instance_task_arns(cluster, instance_arn)\n\n if task_arns:\n print('Instance ARN %s has task ARNs %s' % (instance_arn, ', '.join(task_arns)))\n\n while has_tasks(cluster, instance_arn, task_arns):\n time.sleep(10)\n\n try:\n print('Terminating instance %s' % instance_id)\n autoscaling.complete_lifecycle_action(\n LifecycleActionResult='CONTINUE',\n **pick(lifecycle_event, 'LifecycleHookName', 'LifecycleActionToken', 'AutoScalingGroupName'))\n except Exception as e:\n # Lifecycle action may have already completed.\n print(str(e))\n\n\ndef container_instance_arn(cluster, instance_id):\n \"\"\"Turn an instance ID into a container instance ARN.\"\"\"\n arns = ecs.list_container_instances(cluster=cluster, filter='ec2InstanceId==' + instance_id)['containerInstanceArns']\n if not arns:\n return None\n return arns[0]\n\ndef container_instance_task_arns(cluster, instance_arn):\n \"\"\"Fetch tasks for a container instance ARN.\"\"\"\n arns = ecs.list_tasks(cluster=cluster, containerInstance=instance_arn)['taskArns']\n return arns\n\ndef has_tasks(cluster, instance_arn, task_arns):\n \"\"\"Return True if the instance is running tasks for the given cluster.\"\"\"\n instances = ecs.describe_container_instances(cluster=cluster, containerInstances=[instance_arn])['containerInstances']\n if not instances:\n return False\n instance = instances[0]\n\n if instance['status'] == 'ACTIVE':\n # Start draining, then try again later\n set_container_instance_to_draining(cluster, instance_arn)\n return True\n\n task_count = None\n\n if task_arns:\n # Fetch details for tasks running on the container instance\n tasks = ecs.describe_tasks(cluster=cluster, tasks=task_arns)['tasks']\n if tasks:\n # Consider any non-stopped tasks as running\n task_count = sum(task['lastStatus'] != 'STOPPED' for task in tasks) + instance['pendingTasksCount']\n\n if not task_count:\n # Fallback to instance task counts if detailed task information is unavailable\n task_count = instance['runningTasksCount'] + instance['pendingTasksCount']\n\n print('Instance %s has %s tasks' % (instance_arn, task_count))\n\n return task_count > 0\n\ndef set_container_instance_to_draining(cluster, instance_arn):\n ecs.update_container_instances_state(\n cluster=cluster,\n containerInstances=[instance_arn], status='DRAINING')\n\n\ndef pick(dct, *keys):\n \"\"\"Pick a subset of a dict.\"\"\"\n return {k: v for k, v in dct.items() if k in keys}\n" + }, + "environment": { + "variables": { + "CLUSTER": { + "Ref": "ClusterEB0386A7" + } + } + }, + "handler": "index.lambda_handler", + "role": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunctionServiceRoleC12963BB", + "Arn" + ] + }, + "runtime": "python3.9", + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG" + } + ], + "timeout": 310 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", + "version": "0.0.0" + } + }, + "AllowInvoke:integecsal2023amiASGLifecycleHookDrainHookTopic083F299F": { + "id": "AllowInvoke:integecsal2023amiASGLifecycleHookDrainHookTopic083F299F", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/AllowInvoke:integecsal2023amiASGLifecycleHookDrainHookTopic083F299F", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Permission", + "aws:cdk:cloudformation:props": { + "action": "lambda:InvokeFunction", + "functionName": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "principal": "sns.amazonaws.com", + "sourceArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnPermission", + "version": "0.0.0" + } + }, + "Topic": { + "id": "Topic", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/Topic", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/DrainECSHook/Function/Topic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Subscription", + "aws:cdk:cloudformation:props": { + "endpoint": { + "Fn::GetAtt": [ + "ASGDrainECSHookFunction5F24CF4D", + "Arn" + ] + }, + "protocol": "lambda", + "topicArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.CfnSubscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.Subscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "LifecycleHookDrainHook": { + "id": "LifecycleHookDrainHook", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook", + "children": { + "Topic": { + "id": "Topic", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Topic", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Topic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Topic", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.CfnTopic", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sns.Topic", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Role/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "autoscaling.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "integ-ecs-al2023-ami/ASG" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "sns:Publish", + "Effect": "Allow", + "Resource": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "ASGLifecycleHookDrainHookRoleDefaultPolicy3EEFDE57", + "roles": [ + { + "Ref": "ASGLifecycleHookDrainHookRoleD640316C" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "integ-ecs-al2023-ami/ASG/LifecycleHookDrainHook/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AutoScaling::LifecycleHook", + "aws:cdk:cloudformation:props": { + "autoScalingGroupName": { + "Ref": "ASG46ED3070" + }, + "defaultResult": "CONTINUE", + "heartbeatTimeout": 300, + "lifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING", + "notificationTargetArn": { + "Ref": "ASGLifecycleHookDrainHookTopicA8AD4ACB" + }, + "roleArn": { + "Fn::GetAtt": [ + "ASGLifecycleHookDrainHookRoleD640316C", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.CfnLifecycleHook", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.LifecycleHook", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_autoscaling.AutoScalingGroup", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2023--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2023--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "integ-ecs-al2023-ami/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2023--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2023--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2023--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "integ-ecs-al2023-ami/SsmParameterValue:--aws--service--ecs--optimized-ami--amazon-linux-2023--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "EC2CapacityProvider": { + "id": "EC2CapacityProvider", + "path": "integ-ecs-al2023-ami/EC2CapacityProvider", + "children": { + "EC2CapacityProvider": { + "id": "EC2CapacityProvider", + "path": "integ-ecs-al2023-ami/EC2CapacityProvider/EC2CapacityProvider", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::CapacityProvider", + "aws:cdk:cloudformation:props": { + "autoScalingGroupProvider": { + "autoScalingGroupArn": { + "Ref": "ASG46ED3070" + }, + "managedScaling": { + "status": "ENABLED", + "targetCapacity": 100 + }, + "managedTerminationProtection": "DISABLED" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnCapacityProvider", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.AsgCapacityProvider", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-ecs-al2023-ami/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-ecs-al2023-ami/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "ClusterAL2023": { + "id": "ClusterAL2023", + "path": "ClusterAL2023", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "ClusterAL2023/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "ClusterAL2023/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "ClusterAL2023/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ClusterAL2023/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ClusterAL2023/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.ts new file mode 100644 index 0000000000000..17dda232db22d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster.amazonlinux2023-ami.ts @@ -0,0 +1,64 @@ +import * as autoscaling from 'aws-cdk-lib/aws-autoscaling'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as cdk from 'aws-cdk-lib'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as iam from 'aws-cdk-lib/aws-iam'; + +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); +const stack = new cdk.Stack(app, 'integ-ecs-al2023-ami'); + +const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 1, restrictDefaultSecurityGroup: false }); +const cluster = new ecs.Cluster(stack, 'Cluster', { + vpc, +}); + +const insRole = new iam.Role(stack, 'InstanceRole', { + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), + managedPolicies: [ + // following policy contains permission needed by the ECS agent: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html + iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceForEC2Role'), // for ECS + // following policy allows ssh-ing into the instance via the AWS Console SSM manager. Good for debugging this integ test + iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'), // for SSM + ], +}); +insRole.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY); + +const userData = ec2.UserData.forLinux(); +// echo each commands so they appear in /var/log/cloud-init-output.log +userData.addCommands('set -x'); +// error out on any commands failure in the UserData so that cfn-signal will not run at the end, thus, failing the cfn deployment +userData.addCommands('set -e'); + +const autoScalingGroup = new autoscaling.AutoScalingGroup(stack, 'ASG', { + vpc, + role: insRole, + userData, + instanceType: new ec2.InstanceType('t2.micro'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2023(), + minCapacity: 1, + signals: autoscaling.Signals.waitForMinCapacity({ + timeout: cdk.Duration.minutes(10), + }), +}); + +const cp = new ecs.AsgCapacityProvider(stack, 'EC2CapacityProvider', { + autoScalingGroup, + enableManagedTerminationProtection: false, +}); + +cluster.addAsgCapacityProvider(cp); +autoScalingGroup.addUserData('yum install -y aws-cfn-bootstrap'); +// cfn-signal sends a signal to CFN to indicate ASG creation is completed +autoScalingGroup.addUserData(`/opt/aws/bin/cfn-signal -e $? --stack ${stack.stackId}` + +` --resource ${(autoScalingGroup.node.defaultChild as autoscaling.CfnAutoScalingGroup).logicalId}` + + ` --region ${stack.region}`); + +new integ.IntegTest(app, 'ClusterAL2023', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/ecs/integ.event-ec2-task.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/ecs/integ.event-ec2-task.ts index ba7fb097c036c..f9a3572c3bf3e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/ecs/integ.event-ec2-task.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/ecs/integ.event-ec2-task.ts @@ -7,7 +7,12 @@ import * as cdk from 'aws-cdk-lib'; import * as integ from '@aws-cdk/integ-tests-alpha'; import * as targets from 'aws-cdk-lib/aws-events-targets'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-ecs-integ-ecs'); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task-ref-definition.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task-ref-definition.ts index c0c0fddf5ed3d..60003da29968e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task-ref-definition.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task-ref-definition.ts @@ -7,7 +7,12 @@ import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; import { EC2_RESTRICT_DEFAULT_SECURITY_GROUP, STEPFUNCTIONS_TASKS_FIX_RUN_ECS_TASK_POLICY } from 'aws-cdk-lib/cx-api'; -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-sfn-tasks-ecs-run-task-ref-task-definition'); stack.node.setContext(EC2_RESTRICT_DEFAULT_SECURITY_GROUP, false); stack.node.setContext(STEPFUNCTIONS_TASKS_FIX_RUN_ECS_TASK_POLICY, false); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.ts index 3c374a583984d..a6f8fe8a9b24c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-run-task.ts @@ -17,7 +17,12 @@ import { IntegTest } from '@aws-cdk/integ-tests-alpha'; * -- aws stepfunctions start-execution --state-machine-arn provides execution arn * -- aws stepfunctions describe-execution --execution-arn returns a status of `Succeeded` */ -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-sfn-tasks-ecs-run-task'); stack.node.setContext(EC2_RESTRICT_DEFAULT_SECURITY_GROUP, false); stack.node.setContext(STEPFUNCTIONS_TASKS_FIX_RUN_ECS_TASK_POLICY, false); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.ts index 9ed50631515d6..6acd65bc8523c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/ecs/integ.ec2-task.ts @@ -17,7 +17,12 @@ import { IntegTest } from '@aws-cdk/integ-tests-alpha'; * -- aws stepfunctions start-execution --state-machine-arn provides execution arn * -- aws stepfunctions describe-execution --execution-arn returns a status of `Succeeded` */ -const app = new cdk.App(); +const app = new cdk.App({ + postCliContext: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, +}); const stack = new cdk.Stack(app, 'aws-sfn-tasks-ecs-task'); stack.node.setContext(EC2_RESTRICT_DEFAULT_SECURITY_GROUP, false); diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index 2ae3186d3a2f1..a4d15dee57855 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -13,7 +13,21 @@ import { IKey } from '../../aws-kms'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; import * as cloudmap from '../../aws-servicediscovery'; -import { Aws, Duration, IResource, Resource, Stack, Aspects, ArnFormat, IAspect, Token, Names, AspectPriority } from '../../core'; +import { + Aws, + Duration, + IResource, + Resource, + Stack, + Aspects, + ArnFormat, + IAspect, + Token, + Names, + AspectPriority, + FeatureFlags, Annotations, +} from '../../core'; +import { Disable_ECS_IMDS_Blocking, Enable_IMDS_Blocking_Deprecated_Feature } from '../../cx-api'; const CLUSTER_SYMBOL = Symbol.for('@aws-cdk/aws-ecs/lib/cluster.Cluster'); @@ -101,6 +115,23 @@ export enum MachineImageType { BOTTLEROCKET, } +/** + * Determine the value for the canContainersAccessInstanceRole option if it is undefined. + * The value is determined based on the @aws-cdk/aws-ecs:disableEcsImdsBlocking feature flag. + */ +const getCanContainersAccessInstanceRoleDefault = (canContainersAccessInstanceRole: boolean | undefined, + disableEcsImdsBlockingFlag: boolean | undefined): boolean => { + if (canContainersAccessInstanceRole !== undefined) { + return canContainersAccessInstanceRole; + } + + if (disableEcsImdsBlockingFlag === true) { + return true; + } else { + return false; + } +}; + /** * A regional grouping of one or more container instances on which you can run tasks and services. */ @@ -515,7 +546,9 @@ export class Cluster extends Resource implements ICluster { machineImageType: provider.machineImageType, // Don't enable the instance-draining lifecycle hook if managed termination protection or managed draining is enabled taskDrainTime: (provider.enableManagedTerminationProtection || provider.enableManagedDraining) ? Duration.seconds(0) : options.taskDrainTime, - canContainersAccessInstanceRole: options.canContainersAccessInstanceRole ?? provider.canContainersAccessInstanceRole, + canContainersAccessInstanceRole: getCanContainersAccessInstanceRoleDefault( + options.canContainersAccessInstanceRole ?? provider.canContainersAccessInstanceRole, + FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)), }); this._capacityProviderNames.push(provider.capacityProviderName); @@ -536,14 +569,24 @@ export class Cluster extends Resource implements ICluster { } private configureAutoScalingGroup(autoScalingGroup: autoscaling.AutoScalingGroup, options: AddAutoScalingGroupCapacityOptions = {}) { + // mutating the original options may cause unexpected behavioral change, hence, creating a clone here to avoid mutation + const optionsClone: AddAutoScalingGroupCapacityOptions = { + ...options, + machineImageType: options.machineImageType ?? MachineImageType.AMAZON_LINUX_2, + canContainersAccessInstanceRole: getCanContainersAccessInstanceRoleDefault( + options.canContainersAccessInstanceRole, + FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)), + }; + if (!(autoScalingGroup instanceof autoscaling.AutoScalingGroup)) { throw new Error('Cannot configure the AutoScalingGroup because it is an imported resource.'); } + if (autoScalingGroup.osType === ec2.OperatingSystemType.WINDOWS) { - this.configureWindowsAutoScalingGroup(autoScalingGroup, options); + this.configureWindowsAutoScalingGroup(autoScalingGroup, optionsClone); } else { // Tie instances to cluster - switch (options.machineImageType) { + switch (optionsClone.machineImageType) { // Bottlerocket AMI case MachineImageType.BOTTLEROCKET: { autoScalingGroup.addUserData( @@ -557,23 +600,26 @@ export class Cluster extends Resource implements ICluster { autoScalingGroup.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore')); // required managed policy autoScalingGroup.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceforEC2Role')); + + this.handleCanContainersAccessInstanceRoleForBottleRocket(optionsClone); break; } - default: - // Amazon ECS-optimized AMI for Amazon Linux 2 + case MachineImageType.AMAZON_LINUX_2: { autoScalingGroup.addUserData(`echo ECS_CLUSTER=${this.clusterName} >> /etc/ecs/ecs.config`); - if (!options.canContainersAccessInstanceRole) { - // Deny containers access to instance metadata service - // Source: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html - autoScalingGroup.addUserData('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP'); - autoScalingGroup.addUserData('sudo service iptables save'); - // The following is only for AwsVpc networking mode, but doesn't hurt for the other modes. - autoScalingGroup.addUserData('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config'); - } - - if (autoScalingGroup.spotPrice && options.spotInstanceDraining) { + this.handleCanContainersAccessInstanceRoleForAL2(autoScalingGroup, optionsClone); + if (autoScalingGroup.spotPrice && optionsClone.spotInstanceDraining) { autoScalingGroup.addUserData('echo ECS_ENABLE_SPOT_INSTANCE_DRAINING=true >> /etc/ecs/ecs.config'); } + break; + } + default: { + Annotations.of(this).addWarningV2('@aws-cdk/aws-ecs:unknownImageType', + `Unknown ECS Image type: ${optionsClone.machineImageType}.`); + if (optionsClone.canContainersAccessInstanceRole === false) { + throw new Error('The canContainersAccessInstanceRole option is not supported. See https://github.com/aws/aws-cdk/discussions/32609'); + } + break; + } } } @@ -631,6 +677,48 @@ export class Cluster extends Resource implements ICluster { } } + private handleCanContainersAccessInstanceRoleForBottleRocket(options: AddAutoScalingGroupCapacityOptions): void { + if ((options.canContainersAccessInstanceRole === false || options.canContainersAccessInstanceRole === undefined) && + !FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)) { + Annotations.of(this).addWarningV2('@aws-cdk/aws-ecs:deprecatedImdsBlocking', + 'Blocking container accessing instance role is not supported. See https://github.com/aws/aws-cdk/discussions/32609'); + } + + if (options.canContainersAccessInstanceRole === false && + FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)) { + throw new Error('The canContainersAccessInstanceRole option is not supported. See https://github.com/aws/aws-cdk/discussions/32609'); + } + } + + private handleCanContainersAccessInstanceRoleForAL2(autoScalingGroup: autoscaling.AutoScalingGroup, + options: AddAutoScalingGroupCapacityOptions): void { + if (options.canContainersAccessInstanceRole === false && + FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)) { + throw new Error('The canContainersAccessInstanceRole option is not supported. See https://github.com/aws/aws-cdk/discussions/32609'); + } + + if (options.canContainersAccessInstanceRole === false || + options.canContainersAccessInstanceRole === undefined) { + + if (!FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking) && + FeatureFlags.of(this).isEnabled(Enable_IMDS_Blocking_Deprecated_Feature)) { + // new commands from https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html#task-iam-role-considerations + autoScalingGroup.addUserData('sudo yum install -y iptables-services; sudo iptables --insert DOCKER-USER 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP'); + autoScalingGroup.addUserData('sudo iptables-save | sudo tee /etc/sysconfig/iptables && sudo systemctl enable --now iptables'); + } else if (!FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking) && + !FeatureFlags.of(this).isEnabled(Enable_IMDS_Blocking_Deprecated_Feature)) { + // old commands + autoScalingGroup.addUserData('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP'); + autoScalingGroup.addUserData('sudo service iptables save'); + + Annotations.of(this).addWarningV2('@aws-cdk/aws-ecs:deprecatedImdsBlocking', + 'Blocking container access to instance role will be deprecated. Use the @aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature feature flag' + + 'to keep this feature temporarily. See https://github.com/aws/aws-cdk/discussions/32609'); + } + // The following is only for AwsVpc networking mode, but doesn't hurt for the other modes. + autoScalingGroup.addUserData('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config'); + } + } /** * This method enables the Fargate or Fargate Spot capacity providers on the cluster. * @@ -679,6 +767,17 @@ export class Cluster extends Resource implements ICluster { } private configureWindowsAutoScalingGroup(autoScalingGroup: autoscaling.AutoScalingGroup, options: AddAutoScalingGroupCapacityOptions = {}) { + if ((options.canContainersAccessInstanceRole === false || options.canContainersAccessInstanceRole === undefined) && + !FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)) { + Annotations.of(this).addWarningV2('@aws-cdk/aws-ecs:deprecatedImdsBlocking', + 'Blocking container accessing instance role is not supported. See https://github.com/aws/aws-cdk/discussions/32609'); + } + + if (options.canContainersAccessInstanceRole === false && + FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)) { + throw new Error('The canContainersAccessInstanceRole option is not supported. See https://github.com/aws/aws-cdk/discussions/32609'); + } + // clear the cache of the agent autoScalingGroup.addUserData('Remove-Item -Recurse C:\\ProgramData\\Amazon\\ECS\\Cache'); @@ -977,7 +1076,9 @@ export interface AddAutoScalingGroupCapacityOptions { /** * Specifies whether the containers can access the container instance role. * - * @default false + * @deprecated See https://github.com/aws/aws-cdk/discussions/32609 + * @default true if @aws-cdk/aws-ecs:disableEcsImdsBlocking feature flag is set to true. + * false if @aws-cdk/aws-ecs:disableEcsImdsBlocking is set to false. */ readonly canContainersAccessInstanceRole?: boolean; @@ -1369,7 +1470,9 @@ export class AsgCapacityProvider extends Construct { /** * Specifies whether the containers can access the container instance role. * - * @default false + * @deprecated See https://github.com/aws/aws-cdk/discussions/32609 + * @default true if @aws-cdk/aws-ecs:disableEcsImdsBlocking feature flag is set to true. + * false if @aws-cdk/aws-ecs:disableEcsImdsBlocking is set to false. */ readonly canContainersAccessInstanceRole?: boolean; @@ -1378,7 +1481,8 @@ export class AsgCapacityProvider extends Construct { let capacityProviderName = props.capacityProviderName; this.autoScalingGroup = props.autoScalingGroup as autoscaling.AutoScalingGroup; this.machineImageType = props.machineImageType ?? MachineImageType.AMAZON_LINUX_2; - this.canContainersAccessInstanceRole = props.canContainersAccessInstanceRole; + this.canContainersAccessInstanceRole = getCanContainersAccessInstanceRoleDefault( + props.canContainersAccessInstanceRole, FeatureFlags.of(this).isEnabled(Disable_ECS_IMDS_Blocking)); this.enableManagedTerminationProtection = props.enableManagedTerminationProtection ?? true; this.enableManagedDraining = props.enableManagedDraining; diff --git a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts index 0337ff49bd066..4231655b57d39 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts @@ -1,5 +1,5 @@ import { testDeprecated } from '@aws-cdk/cdk-build-tools'; -import { Match, Template } from '../../assertions'; +import { Annotations, Match, Template } from '../../assertions'; import * as autoscaling from '../../aws-autoscaling'; import * as ec2 from '../../aws-ec2'; import * as iam from '../../aws-iam'; @@ -8,9 +8,9 @@ import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; import * as cloudmap from '../../aws-servicediscovery'; import * as cdk from '../../core'; -import { getWarnings } from '../../core/test/util'; import * as cxapi from '../../cx-api'; import * as ecs from '../lib'; +import { CfnCluster, MachineImageType } from '../lib'; describe('cluster', () => { describe('isCluster() returns', () => { @@ -3353,3 +3353,939 @@ describe('Accessing container instance role', function () { expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config'); }); }); + +describe('canContainersAccessInstanceRole behaviour', () => { + const ECS_CLUSTER_LOGICAL_ID = 'EcsCluster'; + + const retrieveUserData = (template: Template) => { + const launchTemplate = template.findResources('AWS::AutoScaling::LaunchConfiguration'); + expect(Object.keys(launchTemplate).length).toBe(1); + return Object.values(launchTemplate)[0].Properties.UserData['Fn::Base64']; + }; + + describe('when using Linux as OS', () => { + const assertUserDataHasLinuxOldIptableCommands = (userData: object) => { + expect(userData).toMatchObject({ + 'Fn::Join': [ + '', + [ + '#!/bin/bash\necho ECS_CLUSTER=', + { + Ref: ECS_CLUSTER_LOGICAL_ID, + }, + ' >> /etc/ecs/ecs.config\nsudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo service iptables save\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config', + ], + ], + }); + }; + + const assertUserDataHasLinuxUpdatedIptableCommands = (userData: object) => { + expect(userData).toMatchObject({ + 'Fn::Join': [ + '', + [ + '#!/bin/bash\necho ECS_CLUSTER=', + { + Ref: ECS_CLUSTER_LOGICAL_ID, + }, + ' >> /etc/ecs/ecs.config\nsudo yum install -y iptables-services; sudo iptables --insert DOCKER-USER 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP\nsudo iptables-save | sudo tee /etc/sysconfig/iptables && sudo systemctl enable --now iptables\necho ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config', + ], + ], + }); + }; + + const assertUserDataDoesNotHaveNetworkingCommands = (userData: object) => { + expect(userData).toMatchObject({ + 'Fn::Join': [ + '', + [ + '#!/bin/bash\necho ECS_CLUSTER=', + { + Ref: ECS_CLUSTER_LOGICAL_ID, + }, + ' >> /etc/ecs/ecs.config', + ], + ], + }); + }; + + const createClusterUsingAddAutoScalingGroup = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const vpc = new ec2.Vpc(options.stack, 'Vpc'); + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + const autoScalingGroup = new autoscaling.AutoScalingGroup(options.stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('fake'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + }); + cluster.addAutoScalingGroup(autoScalingGroup, { canContainersAccessInstanceRole: options.canContainersAccessInstanceRole }); + + return cluster; + }; + + const createClusterUsingAddAsgCapacityProvider = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const vpc = new ec2.Vpc(options.stack, 'Vpc'); + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + const autoScalingGroup = new autoscaling.AutoScalingGroup(options.stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('fake'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + }); + const capacityProvider = new ecs.AsgCapacityProvider(options.stack, 'provider', { + autoScalingGroup, + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + }); + cluster.addAsgCapacityProvider(capacityProvider); + + return cluster; + }; + + const createClusterUsingAddCapacity = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + cluster.addCapacity('DefaultAutoScalingGroupCapacity', { + instanceType: new ec2.InstanceType('fake'), + machineImage: ecs.EcsOptimizedImage.amazonLinux2(), + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + }); + + return cluster; + }; + + const waysToCreateCluster = [ + createClusterUsingAddAutoScalingGroup, + createClusterUsingAddAsgCapacityProvider, + createClusterUsingAddCapacity, + ]; + + [ + // canContainersAccessInstanceRole=undefined + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveNetworkingCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveNetworkingCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasLinuxUpdatedIptableCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container access to instance role will be deprecated. Use the @aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature feature flag'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasLinuxOldIptableCommands(userData); + }, + }, + // canContainersAccessInstanceRole=false + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: 'The canContainersAccessInstanceRole option is not supported.', + assertion: (_: cdk.Stack) => { /* no-op */ }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: 'The canContainersAccessInstanceRole option is not supported.', + assertion: (_: cdk.Stack) => { /* no-op */ }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasLinuxUpdatedIptableCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container access to instance role will be deprecated. Use the @aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature feature flag'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasLinuxOldIptableCommands(userData); + }, + }, + // canContainersAccessInstanceRole=true + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveNetworkingCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveNetworkingCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveNetworkingCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveNetworkingCommands(userData); + }, + }, + ].forEach(cdkConfigurations => { + waysToCreateCluster.forEach(wayToCreateCluster => { + test(`${wayToCreateCluster.name} with canContainersAccessInstanceRole=${cdkConfigurations.canContainersAccessInstanceRole}` + + ` and feature flags: ${JSON.stringify(cdkConfigurations.featureFlags)}`, () => { + const app = new cdk.App({ + postCliContext: cdkConfigurations.featureFlags, + }); + const stack = new cdk.Stack(app, 'test'); + + if (cdkConfigurations.expectedSynthError !== undefined) { + expect(() => { + wayToCreateCluster({ stack, canContainersAccessInstanceRole: cdkConfigurations.canContainersAccessInstanceRole }); + }).toThrow(cdkConfigurations.expectedSynthError); + } else { + wayToCreateCluster({ stack, canContainersAccessInstanceRole: cdkConfigurations.canContainersAccessInstanceRole }); + cdkConfigurations.assertion(stack); + } + }); + }); + }); + }); + + describe('when using BottleRocket as OS', () => { + const assertUserDataHasBottleRocketCommands = (userData: object) => { + expect(userData).toMatchObject({ + 'Fn::Join': [ + '', + [ + '\n[settings.ecs]\ncluster = "', + { + Ref: 'EcsCluster', + }, + '"', + ], + ], + }); + }; + + const createClusterUsingAddAutoScalingGroup = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const vpc = new ec2.Vpc(options.stack, 'Vpc'); + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + const autoScalingGroup = new autoscaling.AutoScalingGroup(options.stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('fake'), + machineImage: new ecs.BottleRocketImage(), + }); + cluster.addAutoScalingGroup(autoScalingGroup, { + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + machineImageType: MachineImageType.BOTTLEROCKET, + }); + + return cluster; + }; + + const createClusterUsingAddAsgCapacityProvider = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const vpc = new ec2.Vpc(options.stack, 'Vpc'); + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + const autoScalingGroup = new autoscaling.AutoScalingGroup(options.stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('fake'), + machineImage: new ecs.BottleRocketImage(), + }); + const capacityProvider = new ecs.AsgCapacityProvider(options.stack, 'provider', { + autoScalingGroup, + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + machineImageType: MachineImageType.BOTTLEROCKET, + }); + cluster.addAsgCapacityProvider(capacityProvider); + + return cluster; + }; + + const createClusterUsingAddCapacity = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + cluster.addCapacity('DefaultAutoScalingGroupCapacity', { + instanceType: new ec2.InstanceType('fake'), + machineImage: new ecs.BottleRocketImage(), + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + }); + + return cluster; + }; + + const waysToCreateCluster = [ + createClusterUsingAddAutoScalingGroup, + createClusterUsingAddAsgCapacityProvider, + createClusterUsingAddCapacity, + ]; + + [ + // canContainersAccessInstanceRole=undefined + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + // canContainersAccessInstanceRole=false + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: 'The canContainersAccessInstanceRole option is not supported.', + assertion: (_: cdk.Stack) => { /* no-op */ }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: 'The canContainersAccessInstanceRole option is not supported.', + assertion: (_: cdk.Stack) => { /* no-op */ }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + // canContainersAccessInstanceRole=true + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasBottleRocketCommands(userData); + }, + }, + ].forEach(cdkConfigurations => { + waysToCreateCluster.forEach(wayToCreateCluster => { + test(`${wayToCreateCluster.name} with canContainersAccessInstanceRole=${cdkConfigurations.canContainersAccessInstanceRole}` + + ` and feature flags: ${JSON.stringify(cdkConfigurations.featureFlags)}`, () => { + const app = new cdk.App({ + postCliContext: cdkConfigurations.featureFlags, + }); + const stack = new cdk.Stack(app, 'test'); + + if (cdkConfigurations.expectedSynthError !== undefined) { + expect(() => { + wayToCreateCluster({ stack, canContainersAccessInstanceRole: cdkConfigurations.canContainersAccessInstanceRole }); + }).toThrow(cdkConfigurations.expectedSynthError); + } else { + wayToCreateCluster({ stack, canContainersAccessInstanceRole: cdkConfigurations.canContainersAccessInstanceRole }); + cdkConfigurations.assertion(stack); + } + }); + }); + }); + }); + + describe('when using Windows as OS', () => { + const assertUserDataDoesNotHaveTaskRoleCommands = (userData: object) => { + expect(userData).toMatchObject({ + 'Fn::Join': [ + '', + [ + 'Remove-Item -Recurse C:\\ProgramData\\Amazon\\ECS\\Cache\nImport-Module ECSTools\n[Environment]::SetEnvironmentVariable("ECS_CLUSTER", "', + { + Ref: 'EcsCluster', + }, + "\", \"Machine\")\n[Environment]::SetEnvironmentVariable(\"ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE\", \"true\", \"Machine\")\n[Environment]::SetEnvironmentVariable(\"ECS_AVAILABLE_LOGGING_DRIVERS\", '[\"json-file\",\"awslogs\"]', \"Machine\")\nInitialize-ECSAgent -Cluster '", + { + Ref: 'EcsCluster', + }, + "'", + ], + ], + }); + }; + + const assertUserDataHasTaskRoleCommands = (userData: object) => { + expect(userData).toMatchObject({ + 'Fn::Join': [ + '', + [ + 'Remove-Item -Recurse C:\\ProgramData\\Amazon\\ECS\\Cache\nImport-Module ECSTools\n[Environment]::SetEnvironmentVariable("ECS_CLUSTER", "', + { + Ref: 'EcsCluster', + }, + "\", \"Machine\")\n[Environment]::SetEnvironmentVariable(\"ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE\", \"true\", \"Machine\")\n[Environment]::SetEnvironmentVariable(\"ECS_AVAILABLE_LOGGING_DRIVERS\", '[\"json-file\",\"awslogs\"]', \"Machine\")\n[Environment]::SetEnvironmentVariable(\"ECS_ENABLE_TASK_IAM_ROLE\", \"true\", \"Machine\")\nInitialize-ECSAgent -Cluster '", + { + Ref: 'EcsCluster', + }, + "' -EnableTaskIAMRole", + ], + ], + }); + }; + + const createClusterUsingAddAutoScalingGroup = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const vpc = new ec2.Vpc(options.stack, 'Vpc'); + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + const autoScalingGroup = new autoscaling.AutoScalingGroup(options.stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('fake'), + machineImage: ecs.EcsOptimizedImage.windows(ecs.WindowsOptimizedVersion.SERVER_2022), + }); + cluster.addAutoScalingGroup(autoScalingGroup, { + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + }); + + return cluster; + }; + + const createClusterUsingAddAsgCapacityProvider = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const vpc = new ec2.Vpc(options.stack, 'Vpc'); + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + const autoScalingGroup = new autoscaling.AutoScalingGroup(options.stack, 'asg', { + vpc, + instanceType: new ec2.InstanceType('fake'), + machineImage: ecs.EcsOptimizedImage.windows(ecs.WindowsOptimizedVersion.SERVER_2022), + }); + const capacityProvider = new ecs.AsgCapacityProvider(options.stack, 'provider', { + autoScalingGroup, + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + }); + cluster.addAsgCapacityProvider(capacityProvider); + + return cluster; + }; + + const createClusterUsingAddCapacity = (options: { + stack: cdk.Stack; + canContainersAccessInstanceRole: boolean; + }) => { + const cluster = new ecs.Cluster(options.stack, 'EcsCluster'); + (cluster.node.defaultChild as CfnCluster).overrideLogicalId(ECS_CLUSTER_LOGICAL_ID); + cluster.addCapacity('DefaultAutoScalingGroupCapacity', { + instanceType: new ec2.InstanceType('fake'), + machineImage: ecs.EcsOptimizedImage.windows(ecs.WindowsOptimizedVersion.SERVER_2022), + canContainersAccessInstanceRole: options.canContainersAccessInstanceRole, + }); + + return cluster; + }; + + const waysToCreateCluster = [ + createClusterUsingAddAutoScalingGroup, + createClusterUsingAddAsgCapacityProvider, + createClusterUsingAddCapacity, + ]; + + [ + // canContainersAccessInstanceRole=undefined + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveTaskRoleCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveTaskRoleCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasTaskRoleCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: undefined, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasTaskRoleCommands(userData); + }, + }, + // canContainersAccessInstanceRole=false + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: 'The canContainersAccessInstanceRole option is not supported.', + assertion: (_: cdk.Stack) => { /* no-op */ }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: 'The canContainersAccessInstanceRole option is not supported.', + assertion: (_: cdk.Stack) => { /* no-op */ }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasTaskRoleCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: false, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasWarning( + '*', + Match.stringLikeRegexp('Blocking container accessing instance role is not supported.'), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataHasTaskRoleCommands(userData); + }, + }, + // canContainersAccessInstanceRole=true + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveTaskRoleCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': true, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveTaskRoleCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': true, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveTaskRoleCommands(userData); + }, + }, + { + featureFlags: { + '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature': false, + '@aws-cdk/aws-ecs:disableEcsImdsBlocking': false, + }, + canContainersAccessInstanceRole: true, + expectedSynthError: undefined, + assertion: (stack: cdk.Stack) => { + Annotations.fromStack(stack).hasNoWarning( + '*', + Match.anyValue(), + ); + const template = Template.fromStack(stack); + const userData = retrieveUserData(template); + assertUserDataDoesNotHaveTaskRoleCommands(userData); + }, + }, + ].forEach(cdkConfigurations => { + waysToCreateCluster.forEach(wayToCreateCluster => { + test(`${wayToCreateCluster.name} with canContainersAccessInstanceRole=${cdkConfigurations.canContainersAccessInstanceRole}` + + ` and feature flags: ${JSON.stringify(cdkConfigurations.featureFlags)}`, () => { + const app = new cdk.App({ + postCliContext: cdkConfigurations.featureFlags, + }); + const stack = new cdk.Stack(app, 'test'); + + if (cdkConfigurations.expectedSynthError !== undefined) { + expect(() => { + wayToCreateCluster({ stack, canContainersAccessInstanceRole: cdkConfigurations.canContainersAccessInstanceRole }); + }).toThrow(cdkConfigurations.expectedSynthError); + } else { + wayToCreateCluster({ stack, canContainersAccessInstanceRole: cdkConfigurations.canContainersAccessInstanceRole }); + cdkConfigurations.assertion(stack); + } + }); + }); + }); + }); +}); diff --git a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md index 703d404082431..af60cf74ac326 100644 --- a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +++ b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md @@ -84,6 +84,8 @@ Flags come in three types: | [@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault](#aws-cdkaws-ec2bastionhostuseamazonlinux2023bydefault) | When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2. | 2.172.0 | (default) | | [@aws-cdk/core:aspectStabilization](#aws-cdkcoreaspectstabilization) | When enabled, a stabilization loop will be run when invoking Aspects during synthesis. | 2.172.0 | (config) | | [@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource](#aws-cdkaws-route53-targetsuserpooldomainnamemethodwithoutcustomresource) | When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource. | 2.174.0 | (fix) | +| [@aws-cdk/aws-ecs:disableEcsImdsBlocking](#aws-cdkaws-ecsdisableecsimdsblocking) | When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)** | V2NEXT | (temporary) | +| [@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature](#aws-cdkaws-ecsenableimdsblockingdeprecatedfeature) | When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)** | V2NEXT | (temporary) | @@ -146,6 +148,8 @@ The following json shows the current recommended set of flags, as `cdk init` wou "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true, "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false, "@aws-cdk/aws-s3:keepNotificationInImportedBucket": false, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": true, "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true, "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true, "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true, @@ -1572,6 +1576,45 @@ When this feature flag is enabled, a stabilization loop is run to recurse the co | 2.172.0 | `true` | `true` | +### @aws-cdk/aws-ecs:disableEcsImdsBlocking + +*When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)*** (temporary) + +In an ECS Cluster with `MachineImageType.AMAZON_LINUX_2`, the canContainersAccessInstanceRole=false option attempts to add commands to block containers from +accessing IMDS. CDK cannot guarantee the correct execution of the feature in all platforms. Setting this feature flag +to true will ensure CDK does not attempt to implement IMDS blocking. By **end of 2025**, CDK will remove the +IMDS blocking feature. See [Github discussion](https://github.com/aws/aws-cdk/discussions/32609) for more information. + +It is recommended to follow ECS documentation to block IMDS for your specific platform and cluster configuration. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| V2NEXT | `false` | `true` | + +**Compatibility with old behavior:** It is strongly recommended to set this flag to true. However, if necessary, set this flag to false to continue using the old implementation. + + +### @aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature + +*When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)*** (temporary) + +In an ECS Cluster with `MachineImageType.AMAZON_LINUX_2`, the canContainersAccessInstanceRole=false option attempts to add commands to block containers from +accessing IMDS. Set this flag to true in order to use new and updated commands. Please note that this +feature alone with this feature flag will be deprecated by **end of 2025** as CDK cannot +guarantee the correct execution of the feature in all platforms. See [Github discussion](https://github.com/aws/aws-cdk/discussions/32609) for more information. +It is recommended to follow ECS documentation to block IMDS for your specific platform and cluster configuration. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| V2NEXT | `false` | `false` | + +**Compatibility with old behavior:** Set this flag to false in order to continue using old and outdated commands. However, it is **not** recommended. + + ### @aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource *When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource.* (fix) diff --git a/packages/aws-cdk-lib/cx-api/README.md b/packages/aws-cdk-lib/cx-api/README.md index 5bba4c9198135..e1cf51ff8364e 100644 --- a/packages/aws-cdk-lib/cx-api/README.md +++ b/packages/aws-cdk-lib/cx-api/README.md @@ -513,3 +513,46 @@ _cdk.json_ } } ``` + +* `@aws-cdk/aws-ecs:disableEcsImdsBlocking` + +When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. + +In an ECS Cluster with `MachineImageType.AMAZON_LINUX_2`, the canContainersAccessInstanceRole=false option attempts to add commands to block containers from +accessing IMDS. CDK cannot guarantee the correct execution of the feature in all platforms. Setting this feature flag +to true will ensure CDK does not attempt to implement IMDS blocking. By **end of 2025**, CDK will remove the +IMDS blocking feature. See [Github discussion](https://github.com/aws/aws-cdk/discussions/32609) for more information. + +**It is recommended to follow ECS documentation to block IMDS for your specific platform and cluster configuration.** + +_cdk.json_ + +```json +{ + "context": { + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": true + } +} +``` + +* `@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature` + +When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only.** + +In an ECS Cluster with `MachineImageType.AMAZON_LINUX_2`, the canContainersAccessInstanceRole=false option attempts to add commands to block containers from +accessing IMDS. Set this flag to true in order to use new and updated commands. Please note that this +feature alone with this feature flag will be deprecated by end of 2025 as CDK cannot +guarantee the correct execution of the feature in all platforms. See [Github discussion](https://github.com/aws/aws-cdk/discussions/32609) for more information. + +**It is recommended to follow ECS documentation to block IMDS for your specific platform and cluster configuration.** + + +_cdk.json_ + +```json +{ + "context": { + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false, + }, +} +``` \ No newline at end of file diff --git a/packages/aws-cdk-lib/cx-api/build-tools/flag-report.ts b/packages/aws-cdk-lib/cx-api/build-tools/flag-report.ts index 00477c8833876..c777b6fc9701f 100644 --- a/packages/aws-cdk-lib/cx-api/build-tools/flag-report.ts +++ b/packages/aws-cdk-lib/cx-api/build-tools/flag-report.ts @@ -114,6 +114,7 @@ function oldBehavior(flag: FlagInfo): string | undefined { case FlagType.ApiDefault: return flag.compatibilityWithOldBehaviorMd; case FlagType.BugFix: return flag.compatibilityWithOldBehaviorMd; case FlagType.VisibleContext: return undefined; + case FlagType.Temporary: return flag.compatibilityWithOldBehaviorMd; } } @@ -148,6 +149,7 @@ function renderType(type: FlagType): string { case FlagType.ApiDefault: return '(default)'; case FlagType.BugFix: return '(fix)'; case FlagType.VisibleContext: return '(config)'; + case FlagType.Temporary: return '(temporary)'; } } diff --git a/packages/aws-cdk-lib/cx-api/lib/features.ts b/packages/aws-cdk-lib/cx-api/lib/features.ts index 3d57ceb0bbe6f..2117c431e66c8 100644 --- a/packages/aws-cdk-lib/cx-api/lib/features.ts +++ b/packages/aws-cdk-lib/cx-api/lib/features.ts @@ -118,6 +118,8 @@ export const STEPFUNCTIONS_TASKS_FIX_RUN_ECS_TASK_POLICY = '@aws-cdk/aws-stepfun export const BASTION_HOST_USE_AMAZON_LINUX_2023_BY_DEFAULT = '@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault'; export const ASPECT_STABILIZATION = '@aws-cdk/core:aspectStabilization'; export const USER_POOL_DOMAIN_NAME_METHOD_WITHOUT_CUSTOM_RESOURCE = '@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource'; +export const Enable_IMDS_Blocking_Deprecated_Feature = '@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature'; +export const Disable_ECS_IMDS_Blocking = '@aws-cdk/aws-ecs:disableEcsImdsBlocking'; export const FLAGS: Record = { ////////////////////////////////////////////////////////////////////// @@ -1138,6 +1140,44 @@ export const FLAGS: Record = { compatibilityWithOldBehaviorMd: 'Disable the feature flag to use input and output path fields for s3 URI', }, + ////////////////////////////////////////////////////////////////////// + [Enable_IMDS_Blocking_Deprecated_Feature]: { + type: FlagType.Temporary, + summary: 'When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated ' + + 'commands will be added to UserData to block container accessing IMDS. ' + + '**Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**', + detailsMd: ` + In an ECS Cluster with \`MachineImageType.AMAZON_LINUX_2\`, the canContainersAccessInstanceRole=false option attempts to add commands to block containers from + accessing IMDS. Set this flag to true in order to use new and updated commands. Please note that this + feature alone with this feature flag will be deprecated by **end of 2025** as CDK cannot + guarantee the correct execution of the feature in all platforms. See [Github discussion](https://github.com/aws/aws-cdk/discussions/32609) for more information. + It is recommended to follow ECS documentation to block IMDS for your specific platform and cluster configuration. + `, + introducedIn: { v2: 'V2NEXT' }, + recommendedValue: false, + compatibilityWithOldBehaviorMd: 'Set this flag to false in order to continue using old and outdated commands. ' + + 'However, it is **not** recommended.', + }, + + ////////////////////////////////////////////////////////////////////// + [Disable_ECS_IMDS_Blocking]: { + type: FlagType.Temporary, + summary: 'When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false.' + + ' **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**', + detailsMd: ` + In an ECS Cluster with \`MachineImageType.AMAZON_LINUX_2\`, the canContainersAccessInstanceRole=false option attempts to add commands to block containers from + accessing IMDS. CDK cannot guarantee the correct execution of the feature in all platforms. Setting this feature flag + to true will ensure CDK does not attempt to implement IMDS blocking. By **end of 2025**, CDK will remove the + IMDS blocking feature. See [Github discussion](https://github.com/aws/aws-cdk/discussions/32609) for more information. + + It is recommended to follow ECS documentation to block IMDS for your specific platform and cluster configuration. + `, + introducedIn: { v2: 'V2NEXT' }, + recommendedValue: true, + compatibilityWithOldBehaviorMd: 'It is strongly recommended to set this flag to true. However, if necessary, set ' + + 'this flag to false to continue using the old implementation.', + }, + ////////////////////////////////////////////////////////////////////// [REDUCE_EC2_FARGATE_CLOUDWATCH_PERMISSIONS]: { type: FlagType.BugFix, diff --git a/packages/aws-cdk-lib/cx-api/lib/private/flag-modeling.ts b/packages/aws-cdk-lib/cx-api/lib/private/flag-modeling.ts index 55279650d075e..2747f12d90041 100644 --- a/packages/aws-cdk-lib/cx-api/lib/private/flag-modeling.ts +++ b/packages/aws-cdk-lib/cx-api/lib/private/flag-modeling.ts @@ -20,6 +20,11 @@ export enum FlagType { * Advertise the presence of this context option in `cdk.json` */ VisibleContext, + + /** + * Use this type for flags that are to be removed on a set date + */ + Temporary, }; export interface FlagInfoBase { @@ -45,6 +50,8 @@ export type FlagInfo = FlagInfoBase & ( /** Describe restoring old behavior or dealing with the change (Markdown) */ readonly compatibilityWithOldBehaviorMd?: string; } | { readonly type: FlagType.VisibleContext } + | { readonly type: FlagType.Temporary; + readonly compatibilityWithOldBehaviorMd?: string; } ); /**