From 7eae4d1358762d72d96b08c6cd020628d3cb77f2 Mon Sep 17 00:00:00 2001 From: mazyu36 Date: Wed, 7 Aug 2024 02:43:31 +0900 Subject: [PATCH] feat(elasticloadbalancingv2): support Mutual Authentication with TLS for Application Load Balancer (#30784) ### Issue # (if applicable) Closes #28206. ### Reason for this change To support mTLS for ALB ### Description of changes * Add `TrustStore` and `TrustStoreRevocation` class * Add `MutualAuthentication` property for `ApplicationListener` ### Description of how you validated changes add unit tests and integ tests ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../alb-mtls-test-stack.assets.json | 84 + .../alb-mtls-test-stack.template.json | 1352 ++++++++++++ ...efaultTestDeployAssert30225695.assets.json | 19 + ...aultTestDeployAssert30225695.template.json | 36 + .../test/integ.alb-mtls.js.snapshot/cdk.out | 1 + .../integ.alb-mtls.js.snapshot/integ.json | 14 + .../integ.alb-mtls.js.snapshot/manifest.json | 431 ++++ .../test/integ.alb-mtls.js.snapshot/tree.json | 1872 +++++++++++++++++ .../test/integ.alb-mtls.ts | 162 ++ .../test/mtls/crl.pem | 1 + .../test/mtls/rootCA_cert.pem | 1 + .../aws-elasticloadbalancingv2/README.md | 53 + .../lib/alb/application-listener.ts | 92 + .../lib/alb/trust-store-revocation.ts | 80 + .../lib/alb/trust-store.ts | 132 ++ .../aws-elasticloadbalancingv2/lib/index.ts | 2 + .../test/alb/listener.test.ts | 159 ++ .../test/alb/trust-store-revocation.test.ts | 79 + .../test/alb/trust-store.test.ts | 77 + packages/aws-cdk-lib/awslint.json | 1 + 20 files changed, 4648 insertions(+) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.ts create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/crl.pem create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/rootCA_cert.pem create mode 100644 packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts create mode 100644 packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts create mode 100644 packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store-revocation.test.ts create mode 100644 packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store.test.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.assets.json new file mode 100644 index 0000000000000..96376cfedf68a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.assets.json @@ -0,0 +1,84 @@ +{ + "version": "36.0.0", + "files": { + "44e9c4d7a5d3fd2d677e1a7e416b2b56f6b0104bd5eff9cac5557b4c65a9dc61": { + "source": { + "path": "asset.44e9c4d7a5d3fd2d677e1a7e416b2b56f6b0104bd5eff9cac5557b4c65a9dc61", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "44e9c4d7a5d3fd2d677e1a7e416b2b56f6b0104bd5eff9cac5557b4c65a9dc61.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "3322b7049fb0ed2b7cbb644a2ada8d1116ff80c32dca89e6ada846b5de26f961": { + "source": { + "path": "asset.3322b7049fb0ed2b7cbb644a2ada8d1116ff80c32dca89e6ada846b5de26f961.zip", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "3322b7049fb0ed2b7cbb644a2ada8d1116ff80c32dca89e6ada846b5de26f961.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "2d56e153cac88d3e0c2f842e8e6f6783b8725bf91f95e0673b4725448a56e96d": { + "source": { + "path": "asset.2d56e153cac88d3e0c2f842e8e6f6783b8725bf91f95e0673b4725448a56e96d", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "2d56e153cac88d3e0c2f842e8e6f6783b8725bf91f95e0673b4725448a56e96d.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "3641a095d2059a31d1fc859958f71b8ee5d665fa3b7657263b5d2607e63fa295": { + "source": { + "path": "asset.3641a095d2059a31d1fc859958f71b8ee5d665fa3b7657263b5d2607e63fa295", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "3641a095d2059a31d1fc859958f71b8ee5d665fa3b7657263b5d2607e63fa295.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1": { + "source": { + "path": "asset.bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "0a87c14e32369e6154b50e10726881c54b3ea07abefb1b01a8ebd0388b64e857": { + "source": { + "path": "alb-mtls-test-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "0a87c14e32369e6154b50e10726881c54b3ea07abefb1b01a8ebd0388b64e857.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-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.template.json new file mode 100644 index 0000000000000..4d59bd91353a1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/alb-mtls-test-stack.template.json @@ -0,0 +1,1352 @@ +{ + "Resources": { + "Bucket83908E77": { + "Type": "AWS::S3::Bucket", + "Properties": { + "Tags": [ + { + "Key": "aws-cdk:auto-delete-objects", + "Value": "true" + }, + { + "Key": "aws-cdk:cr-owned:987d6a23", + "Value": "true" + } + ] + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "BucketPolicyE9A3008A": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "Bucket83908E77" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "BucketAutoDeleteObjectsCustomResourceBAFD23C2": { + "Type": "Custom::S3AutoDeleteObjects", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F", + "Arn" + ] + }, + "BucketName": { + "Ref": "Bucket83908E77" + } + }, + "DependsOn": [ + "BucketPolicyE9A3008A" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ] + } + }, + "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "44e9c4d7a5d3fd2d677e1a7e416b2b56f6b0104bd5eff9cac5557b4c65a9dc61.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + }, + "Runtime": { + "Fn::FindInMap": [ + "LatestNodeRuntimeMap", + { + "Ref": "AWS::Region" + }, + "value" + ] + }, + "Description": { + "Fn::Join": [ + "", + [ + "Lambda function for auto-deleting objects in ", + { + "Ref": "Bucket83908E77" + }, + " S3 bucket." + ] + ] + } + }, + "DependsOn": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + ] + }, + "DeployCaCertAwsCliLayer0CCD78B3": { + "Type": "AWS::Lambda::LayerVersion", + "Properties": { + "Content": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "3322b7049fb0ed2b7cbb644a2ada8d1116ff80c32dca89e6ada846b5de26f961.zip" + }, + "Description": "/opt/awscli/aws" + } + }, + "DeployCaCertCustomResourceCDD68C79": { + "Type": "Custom::CDKBucketDeployment", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536", + "Arn" + ] + }, + "SourceBucketNames": [ + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ], + "SourceObjectKeys": [ + "3641a095d2059a31d1fc859958f71b8ee5d665fa3b7657263b5d2607e63fa295.zip" + ], + "DestinationBucketName": { + "Ref": "Bucket83908E77" + }, + "Prune": true + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265": { + "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" + ] + ] + } + ] + } + }, + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + ] + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", + "Roles": [ + { + "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + } + ] + } + }, + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "2d56e153cac88d3e0c2f842e8e6f6783b8725bf91f95e0673b4725448a56e96d.zip" + }, + "Environment": { + "Variables": { + "AWS_CA_BUNDLE": "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" + } + }, + "Handler": "index.handler", + "Layers": [ + { + "Ref": "DeployCaCertAwsCliLayer0CCD78B3" + } + ], + "Role": { + "Fn::GetAtt": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265", + "Arn" + ] + }, + "Runtime": "python3.9", + "Timeout": 900 + }, + "DependsOn": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + ] + }, + "Stack8A423254": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack" + } + ] + } + }, + "StackPublicSubnet1Subnet0AD81D22": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "test-region-1a", + "CidrBlock": "10.0.0.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPublicSubnet1RouteTable5057189D": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet1" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPublicSubnet1RouteTableAssociation74F1C1B6": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "StackPublicSubnet1RouteTable5057189D" + }, + "SubnetId": { + "Ref": "StackPublicSubnet1Subnet0AD81D22" + } + } + }, + "StackPublicSubnet1DefaultRoute16154E3D": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "RouteTableId": { + "Ref": "StackPublicSubnet1RouteTable5057189D" + } + }, + "DependsOn": [ + "StackVPCGWFFCB6290" + ] + }, + "StackPublicSubnet1EIPBDAAB2A5": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet1" + } + ] + } + }, + "StackPublicSubnet1NATGatewayD2E1ABF7": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "StackPublicSubnet1EIPBDAAB2A5", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "StackPublicSubnet1Subnet0AD81D22" + }, + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "StackPublicSubnet1DefaultRoute16154E3D", + "StackPublicSubnet1RouteTableAssociation74F1C1B6" + ] + }, + "StackPublicSubnet2Subnet3C7D2288": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "test-region-1b", + "CidrBlock": "10.0.32.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPublicSubnet2RouteTableCD306445": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet2" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPublicSubnet2RouteTableAssociation5E8F73F1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "StackPublicSubnet2RouteTableCD306445" + }, + "SubnetId": { + "Ref": "StackPublicSubnet2Subnet3C7D2288" + } + } + }, + "StackPublicSubnet2DefaultRoute0319539B": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "RouteTableId": { + "Ref": "StackPublicSubnet2RouteTableCD306445" + } + }, + "DependsOn": [ + "StackVPCGWFFCB6290" + ] + }, + "StackPublicSubnet2EIP8CDBC8C2": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet2" + } + ] + } + }, + "StackPublicSubnet2NATGatewayA8E03AB3": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "StackPublicSubnet2EIP8CDBC8C2", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "StackPublicSubnet2Subnet3C7D2288" + }, + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet2" + } + ] + }, + "DependsOn": [ + "StackPublicSubnet2DefaultRoute0319539B", + "StackPublicSubnet2RouteTableAssociation5E8F73F1" + ] + }, + "StackPublicSubnet3SubnetCC1055D9": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "test-region-1c", + "CidrBlock": "10.0.64.0/19", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPublicSubnet3RouteTable44D8F838": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPublicSubnet3RouteTableAssociationD026A62D": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "StackPublicSubnet3RouteTable44D8F838" + }, + "SubnetId": { + "Ref": "StackPublicSubnet3SubnetCC1055D9" + } + } + }, + "StackPublicSubnet3DefaultRouteBC0DA152": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "RouteTableId": { + "Ref": "StackPublicSubnet3RouteTable44D8F838" + } + }, + "DependsOn": [ + "StackVPCGWFFCB6290" + ] + }, + "StackPublicSubnet3EIP3201E7C8": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ] + } + }, + "StackPublicSubnet3NATGatewayAB6A10EF": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "AllocationId": { + "Fn::GetAtt": [ + "StackPublicSubnet3EIP3201E7C8", + "AllocationId" + ] + }, + "SubnetId": { + "Ref": "StackPublicSubnet3SubnetCC1055D9" + }, + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ] + }, + "DependsOn": [ + "StackPublicSubnet3DefaultRouteBC0DA152", + "StackPublicSubnet3RouteTableAssociationD026A62D" + ] + }, + "StackPrivateSubnet1Subnet47AC2BC7": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "test-region-1a", + "CidrBlock": "10.0.96.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPrivateSubnet1RouteTable8ADA6A0C": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PrivateSubnet1" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPrivateSubnet1RouteTableAssociationFFE38495": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "StackPrivateSubnet1RouteTable8ADA6A0C" + }, + "SubnetId": { + "Ref": "StackPrivateSubnet1Subnet47AC2BC7" + } + } + }, + "StackPrivateSubnet1DefaultRouteFBF81BA5": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "StackPublicSubnet1NATGatewayD2E1ABF7" + }, + "RouteTableId": { + "Ref": "StackPrivateSubnet1RouteTable8ADA6A0C" + } + } + }, + "StackPrivateSubnet2SubnetA2F8EDD8": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "test-region-1b", + "CidrBlock": "10.0.128.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPrivateSubnet2RouteTableA5546697": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PrivateSubnet2" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPrivateSubnet2RouteTableAssociation68ACB8C1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "StackPrivateSubnet2RouteTableA5546697" + }, + "SubnetId": { + "Ref": "StackPrivateSubnet2SubnetA2F8EDD8" + } + } + }, + "StackPrivateSubnet2DefaultRoute22004492": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "StackPublicSubnet2NATGatewayA8E03AB3" + }, + "RouteTableId": { + "Ref": "StackPrivateSubnet2RouteTableA5546697" + } + } + }, + "StackPrivateSubnet3Subnet28548F2E": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "test-region-1c", + "CidrBlock": "10.0.160.0/19", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PrivateSubnet3" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPrivateSubnet3RouteTable9B1F2842": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack/PrivateSubnet3" + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackPrivateSubnet3RouteTableAssociationC9C6644E": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "StackPrivateSubnet3RouteTable9B1F2842" + }, + "SubnetId": { + "Ref": "StackPrivateSubnet3Subnet28548F2E" + } + } + }, + "StackPrivateSubnet3DefaultRoute361AE708": { + "Type": "AWS::EC2::Route", + "Properties": { + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "StackPublicSubnet3NATGatewayAB6A10EF" + }, + "RouteTableId": { + "Ref": "StackPrivateSubnet3RouteTable9B1F2842" + } + } + }, + "StackIGW2F0A1126": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Stack" + } + ] + } + }, + "StackVPCGWFFCB6290": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "InternetGatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "StackRestrictDefaultSecurityGroupCustomResource804DC9E2": { + "Type": "Custom::VpcRestrictDefaultSG", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E", + "Arn" + ] + }, + "DefaultSecurityGroupId": { + "Fn::GetAtt": [ + "Stack8A423254", + "DefaultSecurityGroup" + ] + }, + "Account": { + "Ref": "AWS::AccountId" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RevokeSecurityGroupEgress" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ec2:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":security-group/", + { + "Fn::GetAtt": [ + "Stack8A423254", + "DefaultSecurityGroup" + ] + } + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "bde7b5c89cb43285f884c94f0b9e17cdb0f5eb5345005114dd60342e0b8a85a1.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0", + "Arn" + ] + }, + "Runtime": { + "Fn::FindInMap": [ + "LatestNodeRuntimeMap", + { + "Ref": "AWS::Region" + }, + "value" + ] + }, + "Description": "Lambda function for removing all inbound/outbound rules from the VPC default security group" + }, + "DependsOn": [ + "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + ] + }, + "Certificate4E7ABB08": { + "Type": "AWS::CertificateManager::Certificate", + "Properties": { + "DomainName": "*.example.com", + "DomainValidationOptions": [ + { + "DomainName": "*.example.com", + "HostedZoneId": "Z23ABC4XYZL05B" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "alb-mtls-test-stack/Certificate" + } + ], + "ValidationMethod": "DNS" + } + }, + "LB8A12904C": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "LoadBalancerAttributes": [ + { + "Key": "deletion_protection.enabled", + "Value": "false" + } + ], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "StackPublicSubnet1Subnet0AD81D22" + }, + { + "Ref": "StackPublicSubnet2Subnet3C7D2288" + }, + { + "Ref": "StackPublicSubnet3SubnetCC1055D9" + } + ], + "Type": "application" + }, + "DependsOn": [ + "StackPublicSubnet1DefaultRoute16154E3D", + "StackPublicSubnet1RouteTableAssociation74F1C1B6", + "StackPublicSubnet2DefaultRoute0319539B", + "StackPublicSubnet2RouteTableAssociation5E8F73F1", + "StackPublicSubnet3DefaultRouteBC0DA152", + "StackPublicSubnet3RouteTableAssociationD026A62D" + ] + }, + "LBSecurityGroup8A41EA2B": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Automatically created Security Group for ELB albmtlsteststackLBDC4031A8", + "SecurityGroupEgress": [ + { + "CidrIp": "255.255.255.255/32", + "Description": "Disallow all traffic", + "FromPort": 252, + "IpProtocol": "icmp", + "ToPort": 86 + } + ], + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow from anyone on port 443", + "FromPort": 443, + "IpProtocol": "tcp", + "ToPort": 443 + } + ], + "VpcId": { + "Ref": "Stack8A423254" + } + } + }, + "LBListener49E825B4": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "Certificates": [ + { + "CertificateArn": { + "Ref": "Certificate4E7ABB08" + } + } + ], + "DefaultActions": [ + { + "FixedResponseConfig": { + "ContentType": "text/plain", + "MessageBody": "Success mTLS", + "StatusCode": "200" + }, + "Type": "fixed-response" + } + ], + "LoadBalancerArn": { + "Ref": "LB8A12904C" + }, + "MutualAuthentication": { + "IgnoreClientCertificateExpiry": false, + "Mode": "verify", + "TrustStoreArn": { + "Fn::GetAtt": [ + "Store1D2A845B", + "TrustStoreArn" + ] + } + }, + "Port": 443, + "Protocol": "HTTPS" + } + }, + "Store1D2A845B": { + "Type": "AWS::ElasticLoadBalancingV2::TrustStore", + "Properties": { + "CaCertificatesBundleS3Bucket": { + "Ref": "Bucket83908E77" + }, + "CaCertificatesBundleS3Key": "rootCA_cert.pem", + "Name": "albmtlsteststackStore63864577" + }, + "DependsOn": [ + "DeployCaCertAwsCliLayer0CCD78B3", + "DeployCaCertCustomResourceCDD68C79" + ] + }, + "Revocation2857AF0C": { + "Type": "AWS::ElasticLoadBalancingV2::TrustStoreRevocation", + "Properties": { + "RevocationContents": [ + { + "S3Bucket": { + "Ref": "Bucket83908E77" + }, + "S3Key": "crl.pem" + } + ], + "TrustStoreArn": { + "Fn::GetAtt": [ + "Store1D2A845B", + "TrustStoreArn" + ] + } + }, + "DependsOn": [ + "DeployCaCertAwsCliLayer0CCD78B3", + "DeployCaCertCustomResourceCDD68C79" + ] + }, + "ARecordE7B57761": { + "Type": "AWS::Route53::RecordSet", + "Properties": { + "AliasTarget": { + "DNSName": { + "Fn::Join": [ + "", + [ + "dualstack.", + { + "Fn::GetAtt": [ + "LB8A12904C", + "DNSName" + ] + } + ] + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "LB8A12904C", + "CanonicalHostedZoneID" + ] + } + }, + "HostedZoneId": "Z23ABC4XYZL05B", + "Name": "example.com.", + "Type": "A" + } + } + }, + "Mappings": { + "LatestNodeRuntimeMap": { + "af-south-1": { + "value": "nodejs20.x" + }, + "ap-east-1": { + "value": "nodejs20.x" + }, + "ap-northeast-1": { + "value": "nodejs20.x" + }, + "ap-northeast-2": { + "value": "nodejs20.x" + }, + "ap-northeast-3": { + "value": "nodejs20.x" + }, + "ap-south-1": { + "value": "nodejs20.x" + }, + "ap-south-2": { + "value": "nodejs20.x" + }, + "ap-southeast-1": { + "value": "nodejs20.x" + }, + "ap-southeast-2": { + "value": "nodejs20.x" + }, + "ap-southeast-3": { + "value": "nodejs20.x" + }, + "ap-southeast-4": { + "value": "nodejs20.x" + }, + "ap-southeast-5": { + "value": "nodejs20.x" + }, + "ap-southeast-7": { + "value": "nodejs20.x" + }, + "ca-central-1": { + "value": "nodejs20.x" + }, + "ca-west-1": { + "value": "nodejs20.x" + }, + "cn-north-1": { + "value": "nodejs18.x" + }, + "cn-northwest-1": { + "value": "nodejs18.x" + }, + "eu-central-1": { + "value": "nodejs20.x" + }, + "eu-central-2": { + "value": "nodejs20.x" + }, + "eu-isoe-west-1": { + "value": "nodejs18.x" + }, + "eu-north-1": { + "value": "nodejs20.x" + }, + "eu-south-1": { + "value": "nodejs20.x" + }, + "eu-south-2": { + "value": "nodejs20.x" + }, + "eu-west-1": { + "value": "nodejs20.x" + }, + "eu-west-2": { + "value": "nodejs20.x" + }, + "eu-west-3": { + "value": "nodejs20.x" + }, + "il-central-1": { + "value": "nodejs20.x" + }, + "me-central-1": { + "value": "nodejs20.x" + }, + "me-south-1": { + "value": "nodejs20.x" + }, + "mx-central-1": { + "value": "nodejs20.x" + }, + "sa-east-1": { + "value": "nodejs20.x" + }, + "us-east-1": { + "value": "nodejs20.x" + }, + "us-east-2": { + "value": "nodejs20.x" + }, + "us-gov-east-1": { + "value": "nodejs18.x" + }, + "us-gov-west-1": { + "value": "nodejs18.x" + }, + "us-iso-east-1": { + "value": "nodejs18.x" + }, + "us-iso-west-1": { + "value": "nodejs18.x" + }, + "us-isob-east-1": { + "value": "nodejs18.x" + }, + "us-west-1": { + "value": "nodejs20.x" + }, + "us-west-2": { + "value": "nodejs20.x" + } + } + }, + "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-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.assets.json new file mode 100644 index 0000000000000..2cdadacf0eb8c --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "albmtlsintegDefaultTestDeployAssert30225695.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-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/albmtlsintegDefaultTestDeployAssert30225695.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-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.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-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/integ.json new file mode 100644 index 0000000000000..a9e3fe653cba5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/integ.json @@ -0,0 +1,14 @@ +{ + "enableLookups": true, + "version": "36.0.0", + "testCases": { + "alb-mtls-integ/DefaultTest": { + "stacks": [ + "alb-mtls-test-stack" + ], + "stackUpdateWorkflow": false, + "assertionStack": "alb-mtls-integ/DefaultTest/DeployAssert", + "assertionStackName": "albmtlsintegDefaultTestDeployAssert30225695" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/manifest.json new file mode 100644 index 0000000000000..32e54f1dad29c --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/manifest.json @@ -0,0 +1,431 @@ +{ + "version": "36.0.0", + "artifacts": { + "alb-mtls-test-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "alb-mtls-test-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "alb-mtls-test-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "alb-mtls-test-stack.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}/0a87c14e32369e6154b50e10726881c54b3ea07abefb1b01a8ebd0388b64e857.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "alb-mtls-test-stack.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": [ + "alb-mtls-test-stack.assets" + ], + "metadata": { + "/alb-mtls-test-stack/Bucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Bucket83908E77" + } + ], + "/alb-mtls-test-stack/Bucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BucketPolicyE9A3008A" + } + ], + "/alb-mtls-test-stack/Bucket/AutoDeleteObjectsCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "BucketAutoDeleteObjectsCustomResourceBAFD23C2" + } + ], + "/alb-mtls-test-stack/LatestNodeRuntimeMap": [ + { + "type": "aws:cdk:logicalId", + "data": "LatestNodeRuntimeMap" + } + ], + "/alb-mtls-test-stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092" + } + ], + "/alb-mtls-test-stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F" + } + ], + "/alb-mtls-test-stack/DeployCaCert/AwsCliLayer/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DeployCaCertAwsCliLayer0CCD78B3" + } + ], + "/alb-mtls-test-stack/DeployCaCert/CustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "DeployCaCertCustomResourceCDD68C79" + } + ], + "/alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + } + ], + "/alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF" + } + ], + "/alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536" + } + ], + "/alb-mtls-test-stack/Stack/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Stack8A423254" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet1Subnet0AD81D22" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet1RouteTable5057189D" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet1RouteTableAssociation74F1C1B6" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet1DefaultRoute16154E3D" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet1EIPBDAAB2A5" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet1NATGatewayD2E1ABF7" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet2Subnet3C7D2288" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet2RouteTableCD306445" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet2RouteTableAssociation5E8F73F1" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet2DefaultRoute0319539B" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet2/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet2EIP8CDBC8C2" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet2/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet2NATGatewayA8E03AB3" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet3/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet3SubnetCC1055D9" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet3/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet3RouteTable44D8F838" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet3/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet3RouteTableAssociationD026A62D" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet3/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet3DefaultRouteBC0DA152" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet3/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet3EIP3201E7C8" + } + ], + "/alb-mtls-test-stack/Stack/PublicSubnet3/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPublicSubnet3NATGatewayAB6A10EF" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet1Subnet47AC2BC7" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet1RouteTable8ADA6A0C" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet1RouteTableAssociationFFE38495" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet1DefaultRouteFBF81BA5" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet2/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet2SubnetA2F8EDD8" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet2/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet2RouteTableA5546697" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet2/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet2RouteTableAssociation68ACB8C1" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet2/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet2DefaultRoute22004492" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet3/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet3Subnet28548F2E" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet3/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet3RouteTable9B1F2842" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet3/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet3RouteTableAssociationC9C6644E" + } + ], + "/alb-mtls-test-stack/Stack/PrivateSubnet3/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "StackPrivateSubnet3DefaultRoute361AE708" + } + ], + "/alb-mtls-test-stack/Stack/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "StackIGW2F0A1126" + } + ], + "/alb-mtls-test-stack/Stack/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "StackVPCGWFFCB6290" + } + ], + "/alb-mtls-test-stack/Stack/RestrictDefaultSecurityGroupCustomResource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "StackRestrictDefaultSecurityGroupCustomResource804DC9E2" + } + ], + "/alb-mtls-test-stack/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0" + } + ], + "/alb-mtls-test-stack/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E" + } + ], + "/alb-mtls-test-stack/Certificate/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Certificate4E7ABB08" + } + ], + "/alb-mtls-test-stack/LB/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LB8A12904C" + } + ], + "/alb-mtls-test-stack/LB/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBSecurityGroup8A41EA2B" + } + ], + "/alb-mtls-test-stack/LB/Listener/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBListener49E825B4" + } + ], + "/alb-mtls-test-stack/Store/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Store1D2A845B" + } + ], + "/alb-mtls-test-stack/Revocation/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Revocation2857AF0C" + } + ], + "/alb-mtls-test-stack/ARecord/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ARecordE7B57761" + } + ], + "/alb-mtls-test-stack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/alb-mtls-test-stack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "alb-mtls-test-stack" + }, + "albmtlsintegDefaultTestDeployAssert30225695.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "albmtlsintegDefaultTestDeployAssert30225695.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "albmtlsintegDefaultTestDeployAssert30225695": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "albmtlsintegDefaultTestDeployAssert30225695.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": [ + "albmtlsintegDefaultTestDeployAssert30225695.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": [ + "albmtlsintegDefaultTestDeployAssert30225695.assets" + ], + "metadata": { + "/alb-mtls-integ/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/alb-mtls-integ/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "alb-mtls-integ/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-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/tree.json new file mode 100644 index 0000000000000..868262d5007a3 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.js.snapshot/tree.json @@ -0,0 +1,1872 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "alb-mtls-test-stack": { + "id": "alb-mtls-test-stack", + "path": "alb-mtls-test-stack", + "children": { + "Bucket": { + "id": "Bucket", + "path": "alb-mtls-test-stack/Bucket", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Bucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "aws-cdk:auto-delete-objects", + "value": "true" + }, + { + "key": "aws-cdk:cr-owned:987d6a23", + "value": "true" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "alb-mtls-test-stack/Bucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Bucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "Bucket83908E77" + }, + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:List*", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092", + "Arn" + ] + } + }, + "Resource": [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "version": "0.0.0" + } + }, + "AutoDeleteObjectsCustomResource": { + "id": "AutoDeleteObjectsCustomResource", + "path": "alb-mtls-test-stack/Bucket/AutoDeleteObjectsCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "alb-mtls-test-stack/Bucket/AutoDeleteObjectsCustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, + "LatestNodeRuntimeMap": { + "id": "LatestNodeRuntimeMap", + "path": "alb-mtls-test-stack/LatestNodeRuntimeMap", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnMapping", + "version": "0.0.0" + } + }, + "Custom::S3AutoDeleteObjectsCustomResourceProvider": { + "id": "Custom::S3AutoDeleteObjectsCustomResourceProvider", + "path": "alb-mtls-test-stack/Custom::S3AutoDeleteObjectsCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "alb-mtls-test-stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "alb-mtls-test-stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "alb-mtls-test-stack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProviderBase", + "version": "0.0.0" + } + }, + "DeployCaCert": { + "id": "DeployCaCert", + "path": "alb-mtls-test-stack/DeployCaCert", + "children": { + "AwsCliLayer": { + "id": "AwsCliLayer", + "path": "alb-mtls-test-stack/DeployCaCert/AwsCliLayer", + "children": { + "Code": { + "id": "Code", + "path": "alb-mtls-test-stack/DeployCaCert/AwsCliLayer/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "alb-mtls-test-stack/DeployCaCert/AwsCliLayer/Code/Stage", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "alb-mtls-test-stack/DeployCaCert/AwsCliLayer/Code/AssetBucket", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3_assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/DeployCaCert/AwsCliLayer/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::LayerVersion", + "aws:cdk:cloudformation:props": { + "content": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "3322b7049fb0ed2b7cbb644a2ada8d1116ff80c32dca89e6ada846b5de26f961.zip" + }, + "description": "/opt/awscli/aws" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnLayerVersion", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.lambda_layer_awscli.AwsCliLayer", + "version": "0.0.0" + } + }, + "CustomResourceHandler": { + "id": "CustomResourceHandler", + "path": "alb-mtls-test-stack/DeployCaCert/CustomResourceHandler", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.SingletonFunction", + "version": "0.0.0" + } + }, + "Asset1": { + "id": "Asset1", + "path": "alb-mtls-test-stack/DeployCaCert/Asset1", + "children": { + "Stage": { + "id": "Stage", + "path": "alb-mtls-test-stack/DeployCaCert/Asset1/Stage", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "alb-mtls-test-stack/DeployCaCert/Asset1/AssetBucket", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3_assets.Asset", + "version": "0.0.0" + } + }, + "CustomResource": { + "id": "CustomResource", + "path": "alb-mtls-test-stack/DeployCaCert/CustomResource", + "children": { + "Default": { + "id": "Default", + "path": "alb-mtls-test-stack/DeployCaCert/CustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3_deployment.BucketDeployment", + "version": "0.0.0" + } + }, + "Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C": { + "id": "Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/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" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + ] + }, + { + "Action": [ + "s3:Abort*", + "s3:DeleteObject*", + "s3:GetBucket*", + "s3:GetObject*", + "s3:List*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", + "roles": [ + { + "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" + } + ] + } + }, + "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" + } + }, + "Code": { + "id": "Code", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Code/Stage", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Code/AssetBucket", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3_assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "2d56e153cac88d3e0c2f842e8e6f6783b8725bf91f95e0673b4725448a56e96d.zip" + }, + "environment": { + "variables": { + "AWS_CA_BUNDLE": "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" + } + }, + "handler": "index.handler", + "layers": [ + { + "Ref": "DeployCaCertAwsCliLayer0CCD78B3" + } + ], + "role": { + "Fn::GetAtt": [ + "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265", + "Arn" + ] + }, + "runtime": "python3.9", + "timeout": 900 + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.Function", + "version": "0.0.0" + } + }, + "Stack": { + "id": "Stack", + "path": "alb-mtls-test-stack/Stack", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Stack/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": "alb-mtls-test-stack/Stack" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": "test-region-1a", + "cidrBlock": "10.0.0.0/19", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet1" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "StackPublicSubnet1RouteTable5057189D" + }, + "subnetId": { + "Ref": "StackPublicSubnet1Subnet0AD81D22" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "routeTableId": { + "Ref": "StackPublicSubnet1RouteTable5057189D" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "alb-mtls-test-stack/Stack/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "StackPublicSubnet1EIPBDAAB2A5", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "StackPublicSubnet1Subnet0AD81D22" + }, + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/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": "alb-mtls-test-stack/Stack/PublicSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "alb-mtls-test-stack/Stack/PublicSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": "test-region-1b", + "cidrBlock": "10.0.32.0/19", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "alb-mtls-test-stack/Stack/PublicSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "alb-mtls-test-stack/Stack/PublicSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet2" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "alb-mtls-test-stack/Stack/PublicSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "StackPublicSubnet2RouteTableCD306445" + }, + "subnetId": { + "Ref": "StackPublicSubnet2Subnet3C7D2288" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "alb-mtls-test-stack/Stack/PublicSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "routeTableId": { + "Ref": "StackPublicSubnet2RouteTableCD306445" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "alb-mtls-test-stack/Stack/PublicSubnet2/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet2" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "alb-mtls-test-stack/Stack/PublicSubnet2/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "StackPublicSubnet2EIP8CDBC8C2", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "StackPublicSubnet2Subnet3C7D2288" + }, + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/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" + } + }, + "PublicSubnet3": { + "id": "PublicSubnet3", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3", + "children": { + "Subnet": { + "id": "Subnet", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": "test-region-1c", + "cidrBlock": "10.0.64.0/19", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "StackPublicSubnet3RouteTable44D8F838" + }, + "subnetId": { + "Ref": "StackPublicSubnet3SubnetCC1055D9" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "routeTableId": { + "Ref": "StackPublicSubnet3RouteTable44D8F838" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "alb-mtls-test-stack/Stack/PublicSubnet3/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "allocationId": { + "Fn::GetAtt": [ + "StackPublicSubnet3EIP3201E7C8", + "AllocationId" + ] + }, + "subnetId": { + "Ref": "StackPublicSubnet3SubnetCC1055D9" + }, + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PublicSubnet3" + } + ] + } + }, + "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": "alb-mtls-test-stack/Stack/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": "test-region-1a", + "cidrBlock": "10.0.96.0/19", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PrivateSubnet1" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "StackPrivateSubnet1RouteTable8ADA6A0C" + }, + "subnetId": { + "Ref": "StackPrivateSubnet1Subnet47AC2BC7" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "StackPublicSubnet1NATGatewayD2E1ABF7" + }, + "routeTableId": { + "Ref": "StackPrivateSubnet1RouteTable8ADA6A0C" + } + } + }, + "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": "alb-mtls-test-stack/Stack/PrivateSubnet2", + "children": { + "Subnet": { + "id": "Subnet", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet2/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": "test-region-1b", + "cidrBlock": "10.0.128.0/19", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet2/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet2/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PrivateSubnet2" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet2/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "StackPrivateSubnet2RouteTableA5546697" + }, + "subnetId": { + "Ref": "StackPrivateSubnet2SubnetA2F8EDD8" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet2/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "StackPublicSubnet2NATGatewayA8E03AB3" + }, + "routeTableId": { + "Ref": "StackPrivateSubnet2RouteTableA5546697" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet3": { + "id": "PrivateSubnet3", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet3", + "children": { + "Subnet": { + "id": "Subnet", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet3/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "availabilityZone": "test-region-1c", + "cidrBlock": "10.0.160.0/19", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PrivateSubnet3" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet3/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet3/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack/PrivateSubnet3" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet3/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "StackPrivateSubnet3RouteTable9B1F2842" + }, + "subnetId": { + "Ref": "StackPrivateSubnet3Subnet28548F2E" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "alb-mtls-test-stack/Stack/PrivateSubnet3/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "StackPublicSubnet3NATGatewayAB6A10EF" + }, + "routeTableId": { + "Ref": "StackPrivateSubnet3RouteTable9B1F2842" + } + } + }, + "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": "alb-mtls-test-stack/Stack/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Stack" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "alb-mtls-test-stack/Stack/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "internetGatewayId": { + "Ref": "StackIGW2F0A1126" + }, + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + }, + "RestrictDefaultSecurityGroupCustomResource": { + "id": "RestrictDefaultSecurityGroupCustomResource", + "path": "alb-mtls-test-stack/Stack/RestrictDefaultSecurityGroupCustomResource", + "children": { + "Default": { + "id": "Default", + "path": "alb-mtls-test-stack/Stack/RestrictDefaultSecurityGroupCustomResource/Default", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.Vpc", + "version": "0.0.0" + } + }, + "Custom::VpcRestrictDefaultSGCustomResourceProvider": { + "id": "Custom::VpcRestrictDefaultSGCustomResourceProvider", + "path": "alb-mtls-test-stack/Custom::VpcRestrictDefaultSGCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "alb-mtls-test-stack/Custom::VpcRestrictDefaultSGCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "alb-mtls-test-stack/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "alb-mtls-test-stack/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.CustomResourceProviderBase", + "version": "0.0.0" + } + }, + "HostedZone": { + "id": "HostedZone", + "path": "alb-mtls-test-stack/HostedZone", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Certificate": { + "id": "Certificate", + "path": "alb-mtls-test-stack/Certificate", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Certificate/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CertificateManager::Certificate", + "aws:cdk:cloudformation:props": { + "domainName": "*.example.com", + "domainValidationOptions": [ + { + "domainName": "*.example.com", + "hostedZoneId": "Z23ABC4XYZL05B" + } + ], + "tags": [ + { + "key": "Name", + "value": "alb-mtls-test-stack/Certificate" + } + ], + "validationMethod": "DNS" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_certificatemanager.CfnCertificate", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_certificatemanager.Certificate", + "version": "0.0.0" + } + }, + "LB": { + "id": "LB", + "path": "alb-mtls-test-stack/LB", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/LB/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "aws:cdk:cloudformation:props": { + "loadBalancerAttributes": [ + { + "key": "deletion_protection.enabled", + "value": "false" + } + ], + "scheme": "internet-facing", + "securityGroups": [ + { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + } + ], + "subnets": [ + { + "Ref": "StackPublicSubnet1Subnet0AD81D22" + }, + { + "Ref": "StackPublicSubnet2Subnet3C7D2288" + }, + { + "Ref": "StackPublicSubnet3SubnetCC1055D9" + } + ], + "type": "application" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer", + "version": "0.0.0" + } + }, + "SecurityGroup": { + "id": "SecurityGroup", + "path": "alb-mtls-test-stack/LB/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/LB/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "Automatically created Security Group for ELB albmtlsteststackLBDC4031A8", + "securityGroupEgress": [ + { + "cidrIp": "255.255.255.255/32", + "description": "Disallow all traffic", + "ipProtocol": "icmp", + "fromPort": 252, + "toPort": 86 + } + ], + "securityGroupIngress": [ + { + "cidrIp": "0.0.0.0/0", + "ipProtocol": "tcp", + "fromPort": 443, + "toPort": 443, + "description": "Allow from anyone on port 443" + } + ], + "vpcId": { + "Ref": "Stack8A423254" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "Listener": { + "id": "Listener", + "path": "alb-mtls-test-stack/LB/Listener", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/LB/Listener/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::Listener", + "aws:cdk:cloudformation:props": { + "certificates": [ + { + "certificateArn": { + "Ref": "Certificate4E7ABB08" + } + } + ], + "defaultActions": [ + { + "type": "fixed-response", + "fixedResponseConfig": { + "statusCode": "200", + "contentType": "text/plain", + "messageBody": "Success mTLS" + } + } + ], + "loadBalancerArn": { + "Ref": "LB8A12904C" + }, + "mutualAuthentication": { + "ignoreClientCertificateExpiry": false, + "mode": "verify", + "trustStoreArn": { + "Fn::GetAtt": [ + "Store1D2A845B", + "TrustStoreArn" + ] + } + }, + "port": 443, + "protocol": "HTTPS" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.CfnListener", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationListener", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer", + "version": "0.0.0" + } + }, + "Store": { + "id": "Store", + "path": "alb-mtls-test-stack/Store", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Store/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TrustStore", + "aws:cdk:cloudformation:props": { + "caCertificatesBundleS3Bucket": { + "Ref": "Bucket83908E77" + }, + "caCertificatesBundleS3Key": "rootCA_cert.pem", + "name": "albmtlsteststackStore63864577" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.CfnTrustStore", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.TrustStore", + "version": "0.0.0" + } + }, + "Revocation": { + "id": "Revocation", + "path": "alb-mtls-test-stack/Revocation", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/Revocation/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::TrustStoreRevocation", + "aws:cdk:cloudformation:props": { + "revocationContents": [ + { + "s3Bucket": { + "Ref": "Bucket83908E77" + }, + "s3Key": "crl.pem" + } + ], + "trustStoreArn": { + "Fn::GetAtt": [ + "Store1D2A845B", + "TrustStoreArn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.CfnTrustStoreRevocation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_elasticloadbalancingv2.TrustStoreRevocation", + "version": "0.0.0" + } + }, + "ARecord": { + "id": "ARecord", + "path": "alb-mtls-test-stack/ARecord", + "children": { + "Resource": { + "id": "Resource", + "path": "alb-mtls-test-stack/ARecord/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Route53::RecordSet", + "aws:cdk:cloudformation:props": { + "aliasTarget": { + "hostedZoneId": { + "Fn::GetAtt": [ + "LB8A12904C", + "CanonicalHostedZoneID" + ] + }, + "dnsName": { + "Fn::Join": [ + "", + [ + "dualstack.", + { + "Fn::GetAtt": [ + "LB8A12904C", + "DNSName" + ] + } + ] + ] + } + }, + "hostedZoneId": "Z23ABC4XYZL05B", + "name": "example.com.", + "type": "A" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_route53.CfnRecordSet", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_route53.ARecord", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "alb-mtls-test-stack/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "alb-mtls-test-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "alb-mtls-integ": { + "id": "alb-mtls-integ", + "path": "alb-mtls-integ", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "alb-mtls-integ/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "alb-mtls-integ/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "alb-mtls-integ/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "alb-mtls-integ/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "alb-mtls-integ/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-elasticloadbalancingv2/test/integ.alb-mtls.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.ts new file mode 100644 index 0000000000000..90a634fc2cc89 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb-mtls.ts @@ -0,0 +1,162 @@ +import * as path from 'path'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import * as acm from 'aws-cdk-lib/aws-certificatemanager'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as route53 from 'aws-cdk-lib/aws-route53'; +import * as route53targets from 'aws-cdk-lib/aws-route53-targets'; +import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment'; +import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import { Construct } from 'constructs'; + +/** + * In order to test this you must create certificates, keys and Certificate Revocation List (CRL). + * + * 1. Generate root Certificate Authority (CA) certificate and private key (valid for 7 days): + * `openssl req -x509 -new -days 7 -keyout rootCA_key.pem -out rootCA_cert.pem` + * + * 2. Generate client certificate and private key (valid for 7 days): + * `openssl req -x509 -CA rootCA_cert.pem -CAkey rootCA_key.pem -days 7 -new -nodes -keyout client_key.pem -out client_cert.pem` + * + * 3. Create OpenSSL configuration file (openssl.cnf): +``` +cat << EOF > openssl.cnf +[ ca ] +default_ca = CA_default + +[ CA_default ] +dir = . +database = \$dir/index.txt +new_certs_dir = \$dir/newcerts +certificate = \$dir/rootCA_cert.pem +serial = \$dir/serial +private_key = \$dir/rootCA_key.pem +RANDFILE = \$dir/private/.rand +default_crl_days = 30 +default_md = sha256 +preserve = no +policy = policy_match +crl_extensions = crl_ext + +[ policy_match ] +countryName = optional +stateOrProvinceName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ crl_ext ] +authorityKeyIdentifier=keyid:always +EOF +``` + * + * 4. Generate Certificate Revocation List (CRL) (valid for 30 days): + * `openssl ca -config openssl.cnf -gencrl -out crl.pem -crldays 30 -md sha256` + * + * 5. Place `rootCA_cert.pem` and `crl.pem` into the `mtls` directory. + * + * 6. Perform an HTTPS request using the generated client key and certificate: + * `curl https://YOUR-DOMAIN --key client_key.pem --cert client_cert.pem -v` + */ + +interface MutualTlsStackProps extends StackProps { + hostedZoneId: string; + hostedZoneName: string; + domainName: string; +} + +class MutualTls extends Stack { + constructor(scope: Construct, id: string, props: MutualTlsStackProps) { + super(scope, id); + + const bucket = new s3.Bucket(this, 'Bucket', { + autoDeleteObjects: true, + removalPolicy: RemovalPolicy.DESTROY, + }); + + const deploy = new s3deploy.BucketDeployment(this, 'DeployCaCert', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'mtls'))], + destinationBucket: bucket, + }); + + const vpc = new ec2.Vpc(this, 'Stack'); + + const hostedZone = route53.PublicHostedZone.fromHostedZoneAttributes(this, 'HostedZone', { + hostedZoneId: props.hostedZoneId, + zoneName: props.hostedZoneName, + }); + const certificate = new acm.Certificate(this, 'Certificate', { + domainName: props.domainName, + validation: acm.CertificateValidation.fromDns(hostedZone), + }); + + const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { + vpc, + internetFacing: true, + }); + + const trustStore = new elbv2.TrustStore(this, 'Store', { + bucket, + key: 'rootCA_cert.pem', + }); + + trustStore.node.addDependency(deploy); + + const trustStoreRevocation = new elbv2.TrustStoreRevocation(this, 'Revocation', { + trustStore, + revocationContents: [ + { + bucket, + key: 'crl.pem', + }, + ], + }); + + trustStoreRevocation.node.addDependency(deploy); + + lb.addListener('Listener', { + port: 443, + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [certificate], + mutualAuthentication: { + ignoreClientCertificateExpiry: false, + mutualAuthenticationMode: elbv2.MutualAuthenticationMode.VERIFY, + trustStore, + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), + }); + + new route53.ARecord(this, 'ARecord', { + target: route53.RecordTarget.fromAlias(new route53targets.LoadBalancerTarget(lb)), + zone: hostedZone, + }); + } +} + +/** + * In order to test this you need to have a valid public hosted zone that you can use + * to request certificates for. + * +*/ +const hostedZoneId = process.env.CDK_INTEG_HOSTED_ZONE_ID ?? process.env.HOSTED_ZONE_ID; +if (!hostedZoneId) throw new Error('For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.'); +const hostedZoneName = process.env.CDK_INTEG_HOSTED_ZONE_NAME ?? process.env.HOSTED_ZONE_NAME; +if (!hostedZoneName) throw new Error('For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.'); +const domainName = process.env.CDK_INTEG_DOMAIN_NAME ?? process.env.DOMAIN_NAME; +if (!domainName) throw new Error('For this test you must provide your own DomainName as an env var "DOMAIN_NAME". See framework-integ/README.md for details.'); + +const app = new App(); +const stack = new MutualTls(app, 'alb-mtls-test-stack', { + hostedZoneId, + hostedZoneName, + domainName, +}); + +new IntegTest(app, 'alb-mtls-integ', { + testCases: [stack], + enableLookups: true, + stackUpdateWorkflow: false, +}); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/crl.pem b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/crl.pem new file mode 100644 index 0000000000000..2995a4d0e7491 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/crl.pem @@ -0,0 +1 @@ +dummy \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/rootCA_cert.pem b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/rootCA_cert.pem new file mode 100644 index 0000000000000..2995a4d0e7491 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/mtls/rootCA_cert.pem @@ -0,0 +1 @@ +dummy \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md index 6803aff67073b..0f16e99b08917 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md @@ -798,3 +798,56 @@ then you will need to enable the `removeRuleSuffixFromLogicalId: true` property `ListenerRule`s have a unique `priority` for a given `Listener`. Because the `priority` must be unique, CloudFormation will always fail when creating a new `ListenerRule` to replace the existing one, unless you change the `priority` as well as the logicalId. + +## Configuring Mutual authentication with TLS in Application Load Balancer + +You can configure Mutual authentication with TLS (mTLS) for Application Load Balancer. + +To set mTLS, you must create an instance of `TrustStore` and set it to `ApplicationListener`. + +For more information, see [Mutual authentication with TLS in Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/mutual-authentication.html) + +```ts +import * as acm from 'aws-cdk-lib/aws-certificatemanager'; + +declare const certificate: acm.Certificate; +declare const lb: elbv2.ApplicationLoadBalancer; +declare const bucket: s3.Bucket; + +const trustStore = new elbv2.TrustStore(this, 'Store', { + bucket, + key: 'rootCA_cert.pem', +}); + +lb.addListener('Listener', { + port: 443, + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [certificate], + // mTLS settings + mutualAuthentication: { + ignoreClientCertificateExpiry: false, + mutualAuthenticationMode: elbv2.MutualAuthenticationMode.VERIFY, + trustStore, + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), +}); +``` + +Optionally, you can create a certificate revocation list for a trust store by creating an instance of `TrustStoreRevocation`. + +```ts +declare const trustStore: elbv2.TrustStore; +declare const bucket: s3.Bucket; + +new elbv2.TrustStoreRevocation(this, 'Revocation', { + trustStore, + revocationContents: [ + { + revocationType: elbv2.RevocationType.CRL, + bucket, + key: 'crl.pem', + }, + ], +}); +``` diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index e01dd5b83f29e..c4c75ea0c8fda 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -5,6 +5,7 @@ import { ApplicationListenerRule, FixedResponse, RedirectResponse } from './appl import { IApplicationLoadBalancer } from './application-load-balancer'; import { ApplicationTargetGroup, IApplicationLoadBalancerTarget, IApplicationTargetGroup } from './application-target-group'; import { ListenerCondition } from './conditions'; +import { ITrustStore } from './trust-store'; import * as ec2 from '../../../aws-ec2'; import * as cxschema from '../../../cloud-assembly-schema'; import { Duration, Lazy, Resource, Token } from '../../../core'; @@ -96,6 +97,66 @@ export interface BaseApplicationListenerProps { * @default true */ readonly open?: boolean; + + /** + * The mutual authentication configuration information + * + * @default - No mutual authentication configuration + * + * @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/mutual-authentication.html + */ + readonly mutualAuthentication?: MutualAuthentication; +} + +/** + * The mutual authentication configuration information + * + */ +export interface MutualAuthentication { + /** + * The client certificate handling method + * + * @default MutualAuthenticationMode.OFF + */ + readonly mutualAuthenticationMode?: MutualAuthenticationMode; + + /** + * The trust store + * + * Cannot be used with MutualAuthenticationMode.OFF or MutualAuthenticationMode.PASS_THROUGH + * + * @default - no trust store + */ + readonly trustStore?: ITrustStore; + + /** + * Indicates whether expired client certificates are ignored + * + * Cannot be used with MutualAuthenticationMode.OFF or MutualAuthenticationMode.PASS_THROUGH + * + * @default false + */ + readonly ignoreClientCertificateExpiry?: boolean; +} + +/** + * The client certificate handling method + */ +export enum MutualAuthenticationMode { + /** + * Off + */ + OFF = 'off', + + /** + * Application Load Balancer sends the whole client certificate chain to the target using HTTP headers + */ + PASS_THROUGH = 'passthrough', + + /** + * Application Load Balancer performs X.509 client certificate authentication for clients when a load balancer negotiates TLS connections + */ + VERIFY = 'verify', } /** @@ -188,12 +249,19 @@ export class ApplicationListener extends BaseListener implements IApplicationLis throw new Error('At least one of \'port\' or \'protocol\' is required'); } + validateMutualAuthentication(props.mutualAuthentication); + super(scope, id, { loadBalancerArn: props.loadBalancer.loadBalancerArn, certificates: Lazy.any({ produce: () => this.certificateArns.map(certificateArn => ({ certificateArn })) }, { omitEmptyArray: true }), protocol, port, sslPolicy: props.sslPolicy, + mutualAuthentication: props.mutualAuthentication ? { + ignoreClientCertificateExpiry: props.mutualAuthentication?.ignoreClientCertificateExpiry, + mode: props.mutualAuthentication?.mutualAuthenticationMode, + trustStoreArn: props.mutualAuthentication?.trustStore?.trustStoreArn, + } : undefined, }); this.loadBalancer = props.loadBalancer; @@ -969,3 +1037,27 @@ function checkAddRuleProps(props: AddRuleProps) { throw new Error('Setting \'conditions\', \'pathPattern\' or \'hostHeader\' also requires \'priority\', and vice versa'); } } + +function validateMutualAuthentication(mutualAuthentication?: MutualAuthentication): void { + if (!mutualAuthentication) { + return; + } + + const currentMode = mutualAuthentication.mutualAuthenticationMode; + + if (currentMode === MutualAuthenticationMode.VERIFY) { + if (!mutualAuthentication.trustStore) { + throw new Error(`You must set 'trustStore' when 'mode' is '${MutualAuthenticationMode.VERIFY}'`); + } + } + + if (currentMode === MutualAuthenticationMode.OFF || currentMode === MutualAuthenticationMode.PASS_THROUGH) { + if (mutualAuthentication.trustStore) { + throw new Error(`You cannot set 'trustStore' when 'mode' is '${MutualAuthenticationMode.OFF}' or '${MutualAuthenticationMode.PASS_THROUGH}'`); + } + + if (mutualAuthentication.ignoreClientCertificateExpiry !== undefined) { + throw new Error(`You cannot set 'ignoreClientCertificateExpiry' when 'mode' is '${MutualAuthenticationMode.OFF}' or '${MutualAuthenticationMode.PASS_THROUGH}'`); + } + } +} diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts new file mode 100644 index 0000000000000..67cd5f7eda79d --- /dev/null +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store-revocation.ts @@ -0,0 +1,80 @@ +import { Construct } from 'constructs'; +import { ITrustStore } from './trust-store'; +import { IBucket } from '../../../aws-s3'; +import { Resource } from '../../../core'; +import { CfnTrustStoreRevocation } from '../elasticloadbalancingv2.generated'; + +/** + * Properties for the trust store revocation + */ +export interface TrustStoreRevocationProps { + + /** + * The trust store + */ + readonly trustStore: ITrustStore; + + /** + * The revocation file to add + */ + readonly revocationContents: RevocationContent[]; +} + +/** + * Information about a revocation file + */ +export interface RevocationContent { + /** + * The type of revocation file + * + * @default RevocationType.CRL + */ + readonly revocationType?: RevocationType; + + /** + * The Amazon S3 bucket for the revocation file + */ + readonly bucket: IBucket; + + /** + * The Amazon S3 path for the revocation file + */ + readonly key: string; + + /** + * The Amazon S3 object version of the revocation file + * + * @default - latest version + */ + readonly version?: string; +} + +/** + * The type of revocation file + */ +export enum RevocationType { + /** + * A signed list of revoked certificates + */ + CRL = 'CRL', +} + +/** + * A new Trust Store Revocation + */ +export class TrustStoreRevocation extends Resource { + + constructor(scope: Construct, id: string, props: TrustStoreRevocationProps) { + super(scope, id); + + new CfnTrustStoreRevocation(this, 'Resource', { + trustStoreArn: props.trustStore.trustStoreArn, + revocationContents: props.revocationContents?.map(content => ({ + revocationType: content.revocationType, + s3Bucket: content.bucket.bucketName, + s3Key: content.key, + s3ObjectVersion: content.version, + })), + }); + } +} diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts new file mode 100644 index 0000000000000..75a0841f1b45e --- /dev/null +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/trust-store.ts @@ -0,0 +1,132 @@ +import { Construct } from 'constructs'; +import { IBucket } from '../../../aws-s3'; +import { IResource, Resource, Fn, Names, Lazy, Token } from '../../../core'; +import { CfnTrustStore } from '../elasticloadbalancingv2.generated'; + +/** + * Represents a Trust Store + */ +export interface ITrustStore extends IResource { + /** + * The name of the trust store + * @attribute + */ + readonly trustStoreName: string; + + /** + * The ARN of the trust store + * @attribute + */ + readonly trustStoreArn: string; +} + +/** + * Properties used for the Trust Store + */ +export interface TrustStoreProps { + + /** + * The name of the trust store + * + * @default - Auto generated + */ + readonly trustStoreName?: string; + + /** + * The bucket that the trust store is hosted in + */ + readonly bucket: IBucket; + + /** + * The key in S3 to look at for the trust store + */ + readonly key: string; + + /** + * The version of the S3 object that contains your truststore. + * To specify a version, you must have versioning enabled for the S3 bucket. + * + * @default - latest version + */ + readonly version?: string; +} + +/** + * A new Trust Store + */ +export class TrustStore extends Resource implements ITrustStore { + /** + * Import from ARN + */ + public static fromTrustStoreArn(scope: Construct, id: string, trustStoreArn: string): ITrustStore { + const resourceParts = Fn.split('/', trustStoreArn); + + const trustStoreName = Fn.select(0, resourceParts); + + class Import extends Resource implements ITrustStore { + public readonly trustStoreArn = trustStoreArn; + public readonly trustStoreName = trustStoreName; + } + return new Import(scope, id); + } + + /** + * The name of the trust store + * + * @attribute + */ + public readonly trustStoreName: string; + + /** + * The number of CA certificates in the trust store + * + * @attribute + */ + public readonly numberOfCaCertificates: number; + + /** + * The status of the trust store + * + * @attribute + */ + public readonly status: string; + + /** + * The ARN of the trust store + * + * @attribute + */ + public readonly trustStoreArn: string; + + constructor(scope: Construct, id: string, props: TrustStoreProps) { + super(scope, id, { + physicalName: props.trustStoreName ?? Lazy.string({ + produce: () => Names.uniqueResourceName(this, { maxLength: 32 }), + }), + }); + + if (props.trustStoreName !== undefined && !Token.isUnresolved(props.trustStoreName)) { + + if (props.trustStoreName.length < 1 || props.trustStoreName.length > 32) { + throw new Error(`trustStoreName '${props.trustStoreName}' must be 1-32 characters long.`); + } + const validNameRegex = /^([a-zA-Z0-9]+-)*[a-zA-Z0-9]+$/; + if (!validNameRegex.test(props.trustStoreName)) { + throw new Error(`trustStoreName '${props.trustStoreName}' must contain only alphanumeric characters and hyphens, and cannot begin or end with a hyphen.`); + } + + } + + const resource = new CfnTrustStore(this, 'Resource', { + name: this.physicalName, + caCertificatesBundleS3Bucket: props.bucket.bucketName, + caCertificatesBundleS3Key: props.key, + caCertificatesBundleS3ObjectVersion: props.version, + }); + + this.trustStoreName = resource.ref; + this.numberOfCaCertificates = resource.attrNumberOfCaCertificates; + this.status = resource.attrStatus; + this.trustStoreArn = resource.attrTrustStoreArn; + } +} diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/index.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/index.ts index 9f8833b15bfda..575c30b5dfe9d 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/index.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/index.ts @@ -8,6 +8,8 @@ export * from './alb/application-load-balancer'; export * from './alb/application-target-group'; export * from './alb/application-listener-action'; export * from './alb/conditions'; +export * from './alb/trust-store'; +export * from './alb/trust-store-revocation'; export * from './nlb/network-listener'; export * from './nlb/network-load-balancer'; diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts index 4c59f89c674d5..4399b50a4ec72 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts @@ -4,6 +4,7 @@ import { Match, Template } from '../../../assertions'; import * as acm from '../../../aws-certificatemanager'; import { Metric } from '../../../aws-cloudwatch'; import * as ec2 from '../../../aws-ec2'; +import * as s3 from '../../../aws-s3'; import * as cdk from '../../../core'; import { SecretValue } from '../../../core'; import * as elbv2 from '../../lib'; @@ -1933,6 +1934,164 @@ describe('tests', () => { }); }); + + describe('Mutual Authentication', () => { + test('Mutual Authentication settings with all properties when mutualAuthenticationMode is verify', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + const bucket = new s3.Bucket(stack, 'Bucket'); + + const trustStore = new elbv2.TrustStore(stack, 'TrustStore', { + bucket, + key: 'dummy.pem', + }); + + // WHEN + lb.addListener('Listener', { + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [importedCertificate(stack)], + mutualAuthentication: { + ignoreClientCertificateExpiry: true, + mutualAuthenticationMode: elbv2.MutualAuthenticationMode.VERIFY, + trustStore, + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { + MutualAuthentication: { + IgnoreClientCertificateExpiry: true, + Mode: 'verify', + TrustStoreArn: stack.resolve(trustStore.trustStoreArn), + }, + }); + }); + + test.each([elbv2.MutualAuthenticationMode.OFF, elbv2.MutualAuthenticationMode.PASS_THROUGH])('Mutual Authentication settings with all properties when mutualAuthenticationMode is %s', (mutualAuthenticationMode) => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + + // WHEN + lb.addListener('Listener', { + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [importedCertificate(stack)], + mutualAuthentication: { + mutualAuthenticationMode, + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { + MutualAuthentication: { + Mode: mutualAuthenticationMode, + }, + }); + }); + + test('Mutual Authentication settings without all properties', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + + // WHEN + lb.addListener('Listener', { + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [importedCertificate(stack)], + mutualAuthentication: { + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', { + MutualAuthentication: { + IgnoreClientCertificateExpiry: Match.absent(), + Mode: Match.absent(), + TrustStoreArn: Match.absent(), + }, + }); + }); + + test('Throw an error when mode is verify without TrustStore', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + + // WHEN + expect(() => { + lb.addListener('Listener', { + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [importedCertificate(stack)], + mutualAuthentication: { + ignoreClientCertificateExpiry: true, + mutualAuthenticationMode: elbv2.MutualAuthenticationMode.VERIFY, + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), + }); + }).toThrow('You must set \'trustStore\' when \'mode\' is \'verify\''); + }); + + test.each([elbv2.MutualAuthenticationMode.OFF, elbv2.MutualAuthenticationMode.PASS_THROUGH])('Throw an error when mode is %s with trustStore', (mutualAuthenticationMode) => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + const bucket = new s3.Bucket(stack, 'Bucket'); + + const trustStore = new elbv2.TrustStore(stack, 'TrustStore', { + bucket, + key: 'dummy.pem', + }); + + // WHEN + expect(() => { + lb.addListener('Listener', { + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [importedCertificate(stack)], + mutualAuthentication: { + mutualAuthenticationMode, + trustStore, + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), + }); + }).toThrow('You cannot set \'trustStore\' when \'mode\' is \'off\' or \'passthrough\''); + }); + + test.each([elbv2.MutualAuthenticationMode.OFF, elbv2.MutualAuthenticationMode.PASS_THROUGH])('Throw an error when mode is %s with ignoreClientCertificateExpiry', (mutualAuthenticationMode) => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + + // WHEN + expect(() => { + lb.addListener('Listener', { + protocol: elbv2.ApplicationProtocol.HTTPS, + certificates: [importedCertificate(stack)], + mutualAuthentication: { + mutualAuthenticationMode, + ignoreClientCertificateExpiry: true, + }, + defaultAction: elbv2.ListenerAction.fixedResponse(200, + { contentType: 'text/plain', messageBody: 'Success mTLS' }), + }); + }).toThrow('You cannot set \'ignoreClientCertificateExpiry\' when \'mode\' is \'off\' or \'passthrough\''); + }); + }); + }); class ResourceWithLBDependency extends cdk.CfnResource { diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store-revocation.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store-revocation.test.ts new file mode 100644 index 0000000000000..0fc003de5b1ed --- /dev/null +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store-revocation.test.ts @@ -0,0 +1,79 @@ +import { Match, Template } from '../../../assertions'; +import * as s3 from '../../../aws-s3'; +import * as cdk from '../../../core'; +import * as elbv2 from '../../lib'; + +let stack: cdk.Stack; +beforeEach(() => { + stack = new cdk.Stack(); +}); + +test('Trust Store Revocation with all properties', () => { + // GIVEN + const bucket = new s3.Bucket(stack, 'Bucket'); + + const trustStore = new elbv2.TrustStore(stack, 'TrustStore', { + bucket, + key: 'dummy.pem', + }); + + // WHEN + new elbv2.TrustStoreRevocation(stack, 'Revocation', { + trustStore, + revocationContents: [ + { + revocationType: elbv2.RevocationType.CRL, + bucket, + key: 'crl.pem', + version: 'test-version', + }, + ], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TrustStoreRevocation', { + TrustStoreArn: stack.resolve(trustStore.trustStoreArn), + RevocationContents: [ + { + RevocationType: 'CRL', + S3Bucket: stack.resolve(bucket.bucketName), + S3Key: 'crl.pem', + S3ObjectVersion: 'test-version', + }, + ], + }); +}); + +test('Trust Store Revocation with required properties', () => { + // GIVEN + const bucket = new s3.Bucket(stack, 'Bucket'); + + const trustStore = new elbv2.TrustStore(stack, 'TrustStore', { + bucket, + key: 'dummy.pem', + }); + + // WHEN + new elbv2.TrustStoreRevocation(stack, 'Revocation', { + trustStore, + revocationContents: [ + { + bucket, + key: 'crl.pem', + }, + ], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TrustStoreRevocation', { + TrustStoreArn: stack.resolve(trustStore.trustStoreArn), + RevocationContents: [ + { + RevocationType: Match.absent(), + S3Bucket: stack.resolve(bucket.bucketName), + S3Key: 'crl.pem', + S3ObjectVersion: Match.absent(), + }, + ], + }); +}); diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store.test.ts new file mode 100644 index 0000000000000..52649f273ca81 --- /dev/null +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/trust-store.test.ts @@ -0,0 +1,77 @@ +import { Match, Template } from '../../../assertions'; +import * as s3 from '../../../aws-s3'; +import * as cdk from '../../../core'; +import * as elbv2 from '../../lib'; + +let stack: cdk.Stack; +beforeEach(() => { + stack = new cdk.Stack(); +}); + +test('Trust Store with all properties', () => { + // GIVEN + const bucket = new s3.Bucket(stack, 'Bucket'); + + // WHEN + new elbv2.TrustStore(stack, 'TrustStore', { + trustStoreName: 'MyTrustStore', + bucket, + key: 'dummy.pem', + version: 'test-version', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TrustStore', { + CaCertificatesBundleS3Bucket: stack.resolve(bucket.bucketName), + CaCertificatesBundleS3Key: 'dummy.pem', + CaCertificatesBundleS3ObjectVersion: 'test-version', + Name: 'MyTrustStore', + }); +}); + +test('Trust Store with required properties', () => { + // GIVEN + const bucket = new s3.Bucket(stack, 'Bucket'); + + // WHEN + new elbv2.TrustStore(stack, 'TrustStore', { + bucket, + key: 'dummy.pem', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TrustStore', { + CaCertificatesBundleS3Bucket: stack.resolve(bucket.bucketName), + CaCertificatesBundleS3Key: 'dummy.pem', + CaCertificatesBundleS3ObjectVersion: Match.absent(), + Name: 'TrustStore', + }); +}); + +test.each(['', 'a'.repeat(33)])('Throw an error when trustStoreName length is invalid, trustStoreName: %s', (trustStoreName) => { + // GIVEN + const bucket = new s3.Bucket(stack, 'Bucket'); + + // WHEN + expect(() => { + new elbv2.TrustStore(stack, 'TrustStore', { + bucket, + key: 'dummy.pem', + trustStoreName, + }); + }).toThrow(`trustStoreName '${trustStoreName}' must be 1-32 characters long.`); +}); + +test.each(['-test', 'test-', '$test'])('Throw an error when trustStoreName has invalid patten, trustStoreName: %s', (trustStoreName) => { + // GIVEN + const bucket = new s3.Bucket(stack, 'Bucket'); + + // WHEN + expect(() => { + new elbv2.TrustStore(stack, 'TrustStore', { + bucket, + key: 'dummy.pem', + trustStoreName, + }); + }).toThrow(`trustStoreName '${trustStoreName}' must contain only alphanumeric characters and hyphens, and cannot begin or end with a hyphen.`); +}); diff --git a/packages/aws-cdk-lib/awslint.json b/packages/aws-cdk-lib/awslint.json index 8db48224a89b1..c90adb9837fe1 100644 --- a/packages/aws-cdk-lib/awslint.json +++ b/packages/aws-cdk-lib/awslint.json @@ -115,6 +115,7 @@ "props-physical-name:aws-cdk-lib.aws_elasticloadbalancing.LoadBalancerProps", "props-physical-name:aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationListenerProps", "props-physical-name:aws-cdk-lib.aws_elasticloadbalancingv2.NetworkListenerProps", + "props-physical-name:aws-cdk-lib.aws_elasticloadbalancingv2.TrustStoreRevocationProps", "props-physical-name:aws-cdk-lib.aws_events.EventBusPolicyProps", "props-physical-name:aws-cdk-lib.aws_fsx.LustreFileSystemProps", "props-physical-name:aws-cdk-lib.aws_iam.AccessKeyProps",