diff --git a/package.json b/package.json index 81541f5989b1f..630c193ac134b 100644 --- a/package.json +++ b/package.json @@ -175,5 +175,6 @@ }, "dependencies": { "string-width": "^4.2.3" - } + }, + "packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/aws-ecs-ephemeral-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/aws-ecs-ephemeral-integ.assets.json new file mode 100644 index 0000000000000..6f5c3b7bf9b96 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/aws-ecs-ephemeral-integ.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "76e1737d5de58a9bf05d5630b781e44838fe1c3cf4e17c3614cdd42e1208cd13": { + "source": { + "path": "aws-ecs-ephemeral-integ.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "76e1737d5de58a9bf05d5630b781e44838fe1c3cf4e17c3614cdd42e1208cd13.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-encrypt-ephemeral-storage.js.snapshot/aws-ecs-ephemeral-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/aws-ecs-ephemeral-integ.template.json new file mode 100644 index 0000000000000..9090db61ebb77 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/aws-ecs-ephemeral-integ.template.json @@ -0,0 +1,612 @@ +{ + "Resources": { + "Vpc8378EB38": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc" + } + ] + } + }, + "VpcPublicSubnet1Subnet5C2D37C4": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet1RouteTable6C95E38E": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/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": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "VpcPublicSubnet1NATGateway4D7517AA": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet1EIPD7E02669", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet1RouteTableAssociation97140677" + ] + }, + "VpcPublicSubnet2Subnet691E08A3": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.64.0/18", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet2RouteTable94F7E489": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "VpcPublicSubnet2DefaultRoute97F91067": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "RouteTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + }, + "DependsOn": [ + "VpcVPCGWBF912B6E" + ] + }, + "VpcPublicSubnet2EIP3C605A87": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "VpcPublicSubnet2NATGateway9182C01D": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "VpcPublicSubnet2DefaultRoute97F91067", + "VpcPublicSubnet2RouteTableAssociationDD5762D8" + ] + }, + "VpcPrivateSubnet1Subnet536B997A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet1RouteTableB2C5B500": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/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" + } + } + }, + "VpcPrivateSubnet2Subnet3788AAA1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.192.0/18", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet2RouteTableA678073B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "SubnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "VpcPrivateSubnet2DefaultRoute060D2087": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "RouteTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + } + } + }, + "VpcIGWD7BA715C": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-ecs-ephemeral-integ/Vpc" + } + ] + } + }, + "VpcVPCGWBF912B6E": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "keyforunnamed8EC121F9": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + }, + { + "Action": "kms:GenerateDataKeyWithoutPlaintext", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow generate data key access for Fargate tasks." + }, + { + "Action": "kms:CreateGrant", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ] + }, + "ForAllValues:StringEquals": { + "kms:GrantOperations": [ + "Decrypt" + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow grant creation permission for Fargate tasks." + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "cluster611F8AFF": { + "Type": "AWS::ECS::Cluster", + "Properties": { + "Configuration": { + "ManagedStorageConfiguration": { + "FargateEphemeralStorageKmsKeyId": { + "Ref": "keyforunnamed8EC121F9" + } + } + } + } + }, + "keyfornamedA9032E67": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + }, + { + "Action": "kms:GenerateDataKeyWithoutPlaintext", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ], + "kms:EncryptionContext:aws:ecs:clusterName": [ + "cluster-name" + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow generate data key access for Fargate tasks." + }, + { + "Action": "kms:CreateGrant", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ], + "kms:EncryptionContext:aws:ecs:clusterName": [ + "cluster-name" + ] + }, + "ForAllValues:StringEquals": { + "kms:GrantOperations": [ + "Decrypt" + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow grant creation permission for Fargate tasks." + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "namedcluster68273CF6": { + "Type": "AWS::ECS::Cluster", + "Properties": { + "ClusterName": "cluster-name", + "Configuration": { + "ManagedStorageConfiguration": { + "FargateEphemeralStorageKmsKeyId": { + "Ref": "keyfornamedA9032E67" + } + } + } + } + } + }, + "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-encrypt-ephemeral-storage.js.snapshot/awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.assets.json new file mode 100644 index 0000000000000..678d16ef3f8e8 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.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-encrypt-ephemeral-storage.js.snapshot/awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.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-encrypt-ephemeral-storage.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/integ.json new file mode 100644 index 0000000000000..6a710fed1bad2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest": { + "stacks": [ + "aws-ecs-ephemeral-integ" + ], + "assertionStack": "aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest/DeployAssert", + "assertionStackName": "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/manifest.json new file mode 100644 index 0000000000000..8a148d257bc52 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/manifest.json @@ -0,0 +1,269 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-ecs-ephemeral-integ.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-ecs-ephemeral-integ.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-ecs-ephemeral-integ": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-ecs-ephemeral-integ.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}/76e1737d5de58a9bf05d5630b781e44838fe1c3cf4e17c3614cdd42e1208cd13.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-ecs-ephemeral-integ.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": [ + "aws-ecs-ephemeral-integ.assets" + ], + "metadata": { + "/aws-ecs-ephemeral-integ/Vpc/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Vpc8378EB38" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1Subnet5C2D37C4" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTable6C95E38E" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1RouteTableAssociation97140677" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1DefaultRoute3DA9E72A" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1EIPD7E02669" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet1NATGateway4D7517AA" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTable94F7E489" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2RouteTableAssociationDD5762D8" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2DefaultRoute97F91067" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2EIP3C605A87" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPublicSubnet2NATGateway9182C01D" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1Subnet536B997A" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableB2C5B500" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1RouteTableAssociation70C59FA6" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet1DefaultRouteBE02A9ED" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2Subnet3788AAA1" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2RouteTableA678073B" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2RouteTableAssociationA89CAD56" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcPrivateSubnet2DefaultRoute060D2087" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcIGWD7BA715C" + } + ], + "/aws-ecs-ephemeral-integ/Vpc/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VpcVPCGWBF912B6E" + } + ], + "/aws-ecs-ephemeral-integ/key-for-unnamed/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "keyforunnamed8EC121F9" + } + ], + "/aws-ecs-ephemeral-integ/cluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "cluster611F8AFF" + } + ], + "/aws-ecs-ephemeral-integ/key-for-named/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "keyfornamedA9032E67" + } + ], + "/aws-ecs-ephemeral-integ/named-cluster/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "namedcluster68273CF6" + } + ], + "/aws-ecs-ephemeral-integ/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-ecs-ephemeral-integ/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-ecs-ephemeral-integ" + }, + "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.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": [ + "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.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": [ + "awsecsclusterencryptephemeralstorageDefaultTestDeployAssertCC6A879E.assets" + ], + "metadata": { + "/aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-ecs-cluster-encrypt-ephemeral-storage/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-encrypt-ephemeral-storage.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/tree.json new file mode 100644 index 0000000000000..26d2d3a1ee46f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.js.snapshot/tree.json @@ -0,0 +1,995 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-ecs-ephemeral-integ": { + "id": "aws-ecs-ephemeral-integ", + "path": "aws-ecs-ephemeral-integ", + "children": { + "Vpc": { + "id": "Vpc", + "path": "aws-ecs-ephemeral-integ/Vpc", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-ephemeral-integ/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": "aws-ecs-ephemeral-integ/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-ephemeral-integ/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/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-ephemeral-integ/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": "aws-ecs-ephemeral-integ/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": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-ecs-ephemeral-integ/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": "aws-ecs-ephemeral-integ/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" + } + }, + "PublicSubnet2": { + "id": "PublicSubnet2", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.64.0/18", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + }, + "subnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VpcIGWD7BA715C" + }, + "routeTableId": { + "Ref": "VpcPublicSubnet2RouteTable94F7E489" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "VpcPublicSubnet2EIP3C605A87", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + }, + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PublicSubnet2" + } + ] + } + }, + "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": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-ephemeral-integ/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/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-ephemeral-integ/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": "aws-ecs-ephemeral-integ/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" + } + }, + "PrivateSubnet2": { + "id": "PrivateSubnet2", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 1, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.192.0/18", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + }, + "subnetId": { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-ecs-ephemeral-integ/Vpc/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VpcPublicSubnet2NATGateway9182C01D" + }, + "routeTableId": { + "Ref": "VpcPrivateSubnet2RouteTableA678073B" + } + } + }, + "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": "aws-ecs-ephemeral-integ/Vpc/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-ecs-ephemeral-integ/Vpc" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "aws-ecs-ephemeral-integ/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" + } + }, + "key-for-unnamed": { + "id": "key-for-unnamed", + "path": "aws-ecs-ephemeral-integ/key-for-unnamed", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-ephemeral-integ/key-for-unnamed/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + }, + { + "Action": "kms:GenerateDataKeyWithoutPlaintext", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow generate data key access for Fargate tasks." + }, + { + "Action": "kms:CreateGrant", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ] + }, + "ForAllValues:StringEquals": { + "kms:GrantOperations": [ + "Decrypt" + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow grant creation permission for Fargate tasks." + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.CfnKey", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.Key", + "version": "0.0.0" + } + }, + "cluster": { + "id": "cluster", + "path": "aws-ecs-ephemeral-integ/cluster", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-ephemeral-integ/cluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Cluster", + "aws:cdk:cloudformation:props": { + "configuration": { + "managedStorageConfiguration": { + "fargateEphemeralStorageKmsKeyId": { + "Ref": "keyforunnamed8EC121F9" + } + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnCluster", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.Cluster", + "version": "0.0.0" + } + }, + "key-for-named": { + "id": "key-for-named", + "path": "aws-ecs-ephemeral-integ/key-for-named", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-ephemeral-integ/key-for-named/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + }, + { + "Action": "kms:GenerateDataKeyWithoutPlaintext", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ], + "kms:EncryptionContext:aws:ecs:clusterName": [ + "cluster-name" + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow generate data key access for Fargate tasks." + }, + { + "Action": "kms:CreateGrant", + "Condition": { + "StringEquals": { + "kms:EncryptionContext:aws:ecs:clusterAccount": [ + { + "Ref": "AWS::AccountId" + } + ], + "kms:EncryptionContext:aws:ecs:clusterName": [ + "cluster-name" + ] + }, + "ForAllValues:StringEquals": { + "kms:GrantOperations": [ + "Decrypt" + ] + } + }, + "Effect": "Allow", + "Principal": { + "Service": "fargate.amazonaws.com" + }, + "Resource": "*", + "Sid": "Allow grant creation permission for Fargate tasks." + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.CfnKey", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.Key", + "version": "0.0.0" + } + }, + "named-cluster": { + "id": "named-cluster", + "path": "aws-ecs-ephemeral-integ/named-cluster", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-ecs-ephemeral-integ/named-cluster/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ECS::Cluster", + "aws:cdk:cloudformation:props": { + "clusterName": "cluster-name", + "configuration": { + "managedStorageConfiguration": { + "fargateEphemeralStorageKmsKeyId": { + "Ref": "keyfornamedA9032E67" + } + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.CfnCluster", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ecs.Cluster", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-ecs-ephemeral-integ/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-ecs-ephemeral-integ/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "aws-ecs-cluster-encrypt-ephemeral-storage": { + "id": "aws-ecs-cluster-encrypt-ephemeral-storage", + "path": "aws-ecs-cluster-encrypt-ephemeral-storage", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-ecs-cluster-encrypt-ephemeral-storage/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-ecs-cluster-encrypt-ephemeral-storage/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.3.0" + } + } + }, + "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-encrypt-ephemeral-storage.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.ts new file mode 100644 index 0000000000000..b255d2249b3d3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/integ.cluster-encrypt-ephemeral-storage.ts @@ -0,0 +1,34 @@ +import * as cdk from 'aws-cdk-lib'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as integ from '@aws-cdk/integ-tests-alpha'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-ecs-ephemeral-integ'); +const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); + +const keyForUnnamed = new kms.Key(stack, 'key-for-unnamed', { + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); +new ecs.Cluster(stack, 'cluster', { + vpc, + managedStorageConfiguration: { fargateEphemeralStorageKmsKey: keyForUnnamed }, +}); + +const keyForNamed = new kms.Key(stack, 'key-for-named', { + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +new ecs.Cluster(stack, 'named-cluster', { + vpc, + clusterName: 'cluster-name', + managedStorageConfiguration: { fargateEphemeralStorageKmsKey: keyForNamed }, +}); + +new integ.IntegTest(app, 'aws-ecs-cluster-encrypt-ephemeral-storage', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/aws-cdk-lib/aws-ecs/README.md b/packages/aws-cdk-lib/aws-ecs/README.md index f0669e3adcc66..5cfd3e5c36ecb 100644 --- a/packages/aws-cdk-lib/aws-ecs/README.md +++ b/packages/aws-cdk-lib/aws-ecs/README.md @@ -85,6 +85,17 @@ const cluster = new ecs.Cluster(this, 'Cluster', { }); ``` +To encrypt the fargate ephemeral storage configure a KMS key. +```ts +declare const key: kms.Key; + +const cluster = new ecs.Cluster(this, 'Cluster', { + managedStorageConfiguration: { + fargateEphemeralStorageKmsKey: key, + }, +}); +``` + The following code imports an existing cluster using the ARN which can be used to import an Amazon ECS service either EC2 or Fargate. @@ -1865,4 +1876,4 @@ taskDefinition.addContainer('TheContainer', { softLimit: 128, }], }); -``` \ No newline at end of file +``` diff --git a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts index 26f476983ee07..cbdbea5fa427f 100644 --- a/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts @@ -7,11 +7,13 @@ import * as autoscaling from '../../aws-autoscaling'; import * as cloudwatch from '../../aws-cloudwatch'; import * as ec2 from '../../aws-ec2'; import * as iam from '../../aws-iam'; +import { PolicyStatement, ServicePrincipal } from '../../aws-iam'; import * as kms from '../../aws-kms'; +import { IKey } from '../../aws-kms'; import * as logs from '../../aws-logs'; import * as s3 from '../../aws-s3'; import * as cloudmap from '../../aws-servicediscovery'; -import { Duration, IResource, Resource, Stack, Aspects, ArnFormat, IAspect, Token, Names } from '../../core'; +import { Aws, Duration, IResource, Resource, Stack, Aspects, ArnFormat, IAspect, Token, Names } from '../../core'; const CLUSTER_SYMBOL = Symbol.for('@aws-cdk/aws-ecs/lib/cluster.Cluster'); @@ -76,6 +78,13 @@ export interface ClusterProps { * @default - no configuration will be provided. */ readonly executeCommandConfiguration?: ExecuteCommandConfiguration; + + /** + * Encryption configuration for ECS Managed storage + * + * @default - no encryption will be applied. + */ + readonly managedStorageConfiguration?: ManagedStorageConfiguration; } /** @@ -196,6 +205,8 @@ export class Cluster extends Resource implements ICluster { */ private _executeCommandConfiguration?: ExecuteCommandConfiguration; + private _managedStorageConfiguration?: ManagedStorageConfiguration; + /** * CfnCluster instance */ @@ -213,10 +224,13 @@ export class Cluster extends Resource implements ICluster { * clusterSettings needs to be undefined if containerInsights is not explicitly set in order to allow any * containerInsights settings on the account to apply. See: * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-clustersettings.html#cfn-ecs-cluster-clustersettings-value - */ + */ let clusterSettings = undefined; if (props.containerInsights !== undefined) { - clusterSettings = [{ name: 'containerInsights', value: props.containerInsights ? ContainerInsights.ENABLED : ContainerInsights.DISABLED }]; + clusterSettings = [{ + name: 'containerInsights', + value: props.containerInsights ? ContainerInsights.ENABLED : ContainerInsights.DISABLED, + }]; } this._capacityProviderNames = props.capacityProviders ?? []; @@ -232,10 +246,12 @@ export class Cluster extends Resource implements ICluster { this._executeCommandConfiguration = props.executeCommandConfiguration; } + this._managedStorageConfiguration = props.managedStorageConfiguration; + this._cfnCluster = new CfnCluster(this, 'Resource', { clusterName: this.physicalName, clusterSettings, - configuration: this._executeCommandConfiguration && this.renderExecuteCommandConfiguration(), + configuration: this.renderClusterConfiguration(), }); this.clusterArn = this.getResourceArnAttribute(this._cfnCluster.attrArn, { @@ -255,6 +271,8 @@ export class Cluster extends Resource implements ICluster { ? this.addCapacity('DefaultAutoScalingGroup', props.capacity) : undefined; + this.updateKeyPolicyForEphemeralStorageConfiguration(props.clusterName); + // Only create cluster capacity provider associations if there are any EC2 // capacity providers. Ordinarily we'd just add the construct to the tree // since it's harmless, but we'd prefer not to add unexpected new @@ -263,6 +281,42 @@ export class Cluster extends Resource implements ICluster { Aspects.of(this).add(new MaybeCreateCapacityProviderAssociations(this, id)); } + /** + * Applies policy to the target key for encryption. + * + * @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-create-storage-key.html + */ + private updateKeyPolicyForEphemeralStorageConfiguration(clusterName?: string) { + const key = this._managedStorageConfiguration?.fargateEphemeralStorageKmsKey; + if (!key) return; + const clusterConditions = { + StringEquals: { + 'kms:EncryptionContext:aws:ecs:clusterAccount': [Aws.ACCOUNT_ID], + ...(clusterName && { 'kms:EncryptionContext:aws:ecs:clusterName': [clusterName] }), + }, + }; + + key.addToResourcePolicy(new PolicyStatement({ + sid: 'Allow generate data key access for Fargate tasks.', + principals: [new ServicePrincipal('fargate.amazonaws.com')], + resources: ['*'], + actions: ['kms:GenerateDataKeyWithoutPlaintext'], + conditions: clusterConditions, + })); + key.addToResourcePolicy(new PolicyStatement({ + sid: 'Allow grant creation permission for Fargate tasks.', + principals: [new ServicePrincipal('fargate.amazonaws.com')], + resources: ['*'], + actions: ['kms:CreateGrant'], + conditions: { + ...clusterConditions, + 'ForAllValues:StringEquals': { + 'kms:GrantOperations': ['Decrypt'], + }, + }, + })); + } + /** * Enable the Fargate capacity providers for this cluster. */ @@ -310,13 +364,16 @@ export class Cluster extends Resource implements ICluster { this._defaultCapacityProviderStrategy = defaultCapacityProviderStrategy; } - private renderExecuteCommandConfiguration(): CfnCluster.ClusterConfigurationProperty { + private renderClusterConfiguration(): CfnCluster.ClusterConfigurationProperty { return { - executeCommandConfiguration: { + executeCommandConfiguration: this._executeCommandConfiguration && { kmsKeyId: this._executeCommandConfiguration?.kmsKey?.keyArn, logConfiguration: this._executeCommandConfiguration?.logConfiguration && this.renderExecuteCommandLogConfiguration(), logging: this._executeCommandConfiguration?.logging, }, + managedStorageConfiguration: this._managedStorageConfiguration && { + fargateEphemeralStorageKmsKeyId: this._managedStorageConfiguration?.fargateEphemeralStorageKmsKey?.keyId, + }, }; } @@ -452,7 +509,7 @@ export class Cluster extends Resource implements ICluster { ...options, 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, + taskDrainTime: (provider.enableManagedTerminationProtection || provider.enableManagedDraining) ? Duration.seconds(0) : options.taskDrainTime, canContainersAccessInstanceRole: options.canContainersAccessInstanceRole ?? provider.canContainersAccessInstanceRole, }); @@ -602,12 +659,12 @@ export class Cluster extends Resource implements ICluster { } /** - * Grants an ECS Task Protection API permission to the specified grantee. - * This method provides a streamlined way to assign the 'ecs:UpdateTaskProtection' - * permission, enabling the grantee to manage task protection in the ECS cluster. - * - * @param grantee The entity (e.g., IAM role or user) to grant the permissions to. - */ + * Grants an ECS Task Protection API permission to the specified grantee. + * This method provides a streamlined way to assign the 'ecs:UpdateTaskProtection' + * permission, enabling the grantee to manage task protection in the ECS cluster. + * + * @param grantee The entity (e.g., IAM role or user) to grant the permissions to. + */ public grantTaskProtection(grantee: iam.IGrantable): iam.Grant { return iam.Grant.addToPrincipal({ grantee, @@ -1068,7 +1125,7 @@ export interface CapacityProviderStrategy { /** * The weight value designates the relative percentage of the total number of tasks launched that should use the * specified -capacity provider. The weight value is taken into consideration after the base value, if defined, is satisfied. + capacity provider. The weight value is taken into consideration after the base value, if defined, is satisfied. * * @default - 0 */ @@ -1254,6 +1311,22 @@ export interface AsgCapacityProviderProps extends AddAutoScalingGroupCapacityOpt readonly instanceWarmupPeriod?: number; } +/** + * Kms Keys for encryption ECS managed storage + */ +export interface ManagedStorageConfiguration { + + /** + * KMS Key used to encrypt ECS Fargate ephemeral Storage. + * The configured KMS Key's policy will be modified to allow ECS to use the Key to encrypt the ephemeral Storage for this cluster. + * + * @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-storage-encryption.html + * + * @default No encryption will be applied + */ + readonly fargateEphemeralStorageKmsKey?: IKey; +} + /** * An Auto Scaling Group Capacity Provider. This allows an ECS cluster to target * a specific EC2 Auto Scaling Group for the placement of tasks. Optionally (and 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 ee4850409a510..cf7831598bc49 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/cluster.test.ts @@ -1763,6 +1763,110 @@ describe('cluster', () => { }); + test('enable fargate ephemeral storage encryption on cluster with random name', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'test'); + const key = new kms.Key(stack, 'key', { policy: new iam.PolicyDocument() }); + new ecs.Cluster(stack, 'EcsCluster', { managedStorageConfiguration: { fargateEphemeralStorageKmsKey: key } }); + + // THEN + const output = Template.fromStack(stack); + output.hasResourceProperties('AWS::ECS::Cluster', { + Configuration: { + ManagedStorageConfiguration: { + FargateEphemeralStorageKmsKeyId: { + Ref: 'keyFEDD6EC0', + }, + }, + }, + }); + output.hasResourceProperties('AWS::KMS::Key', { + KeyPolicy: { + Statement: [ + { + Resource: '*', + Effect: 'Allow', + Action: 'kms:GenerateDataKeyWithoutPlaintext', + Principal: { Service: 'fargate.amazonaws.com' }, + Condition: { + StringEquals: { + 'kms:EncryptionContext:aws:ecs:clusterAccount': [{ Ref: 'AWS::AccountId' }], + }, + }, + }, + { + Resource: '*', + Effect: 'Allow', + Action: 'kms:CreateGrant', + Principal: { Service: 'fargate.amazonaws.com' }, + Condition: { + 'StringEquals': { + 'kms:EncryptionContext:aws:ecs:clusterAccount': [{ Ref: 'AWS::AccountId' }], + }, + 'ForAllValues:StringEquals': { + 'kms:GrantOperations': ['Decrypt'], + }, + }, + }, + ], + }, + }); + }); + + test('enable fargate ephemeral storage encryption on cluster with defined name', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'test'); + const key = new kms.Key(stack, 'key', { policy: new iam.PolicyDocument() }); + new ecs.Cluster(stack, 'EcsCluster', { clusterName: 'cluster-name', managedStorageConfiguration: { fargateEphemeralStorageKmsKey: key } }); + + // THEN + const output = Template.fromStack(stack); + output.hasResourceProperties('AWS::ECS::Cluster', { + Configuration: { + ManagedStorageConfiguration: { + FargateEphemeralStorageKmsKeyId: { + Ref: 'keyFEDD6EC0', + }, + }, + }, + }); + output.hasResourceProperties('AWS::KMS::Key', { + KeyPolicy: { + Statement: [ + { + Resource: '*', + Effect: 'Allow', + Action: 'kms:GenerateDataKeyWithoutPlaintext', + Principal: { Service: 'fargate.amazonaws.com' }, + Condition: { + StringEquals: { + 'kms:EncryptionContext:aws:ecs:clusterAccount': [{ Ref: 'AWS::AccountId' }], + 'kms:EncryptionContext:aws:ecs:clusterName': ['cluster-name'], + }, + }, + }, + { + Resource: '*', + Effect: 'Allow', + Action: 'kms:CreateGrant', + Principal: { Service: 'fargate.amazonaws.com' }, + Condition: { + 'StringEquals': { + 'kms:EncryptionContext:aws:ecs:clusterAccount': [{ Ref: 'AWS::AccountId' }], + 'kms:EncryptionContext:aws:ecs:clusterName': ['cluster-name'], + }, + 'ForAllValues:StringEquals': { + 'kms:GrantOperations': ['Decrypt'], + }, + }, + }, + ], + }, + }); + }); + test('BottleRocketImage() returns correct AMI', () => { // GIVEN const app = new cdk.App();