From 7c4f423bf14af996203b090429b8c59bd32f50d8 Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Sat, 10 Aug 2024 04:24:32 +0900 Subject: [PATCH] feat(elasticloadbalancingv2): connection logs for ALB (#30599) ### Reason for this change ALB can output connection logs as well as access logs to the S3 bucket, but this is not yet supported by L2 Construct. https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html ### Description of changes The implementation is almost the same as for access logs. However, since connection logs are not supported by NLB, but only by ALB, the `logConnectionLogs` method is added to the `ApplicationLoadBalancer` instead of the `BaseLoadBalancer`. The needed BucketPolicy is described in the documentation only as follows, but to support buckets that still use the ACL, it is necessary to set the same policy that is currently set in the access logs. ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::elb-account-id:root" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::bucket-name/prefix/AWSLogs/aws-account-id/*" } ] } ``` https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html#attach-bucket-policy-connection ### 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* --- .../aws-cdk-elbv2-integ.assets.json | 6 +- .../aws-cdk-elbv2-integ.template.json | 196 +++++++++- .../cdk.out | 2 +- ...efaultTestDeployAssertAEFAB19B.assets.json | 2 +- .../integ.json | 2 +- .../manifest.json | 16 +- .../tree.json | 231 +++++++++++- .../test/integ.alb.extended.log.ts | 10 +- ...-alb-log-imported-bucket-integ.assets.json | 6 +- ...lb-log-imported-bucket-integ.template.json | 73 +++- .../cdk.out | 2 +- ...efaultTestDeployAssert163162C1.assets.json | 2 +- .../integ.json | 2 +- .../manifest.json | 8 +- .../tree.json | 225 +++++++----- .../test/integ.alb.log.imported-bucket.ts | 1 + .../aws-cdk-elbv2-integ.assets.json | 4 +- .../aws-cdk-elbv2-integ.template.json | 87 ++++- .../integ.alb.log.js.snapshot/manifest.json | 2 +- .../test/integ.alb.log.js.snapshot/tree.json | 87 ++++- .../test/integ.alb.log.ts | 1 + .../aws-elasticloadbalancingv2/README.md | 16 + .../lib/alb/application-load-balancer.ts | 62 ++++ .../test/alb/load-balancer.test.ts | 339 ++++++++++++++++++ 24 files changed, 1234 insertions(+), 148 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json index 5f6c1f273d748..627c94b6f11d6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "33.0.0", + "version": "36.0.0", "files": { - "07df570609ba80d7ccc6a61dc96229756a5e4fc6a10d9a68ac076b94a8ce3e55": { + "dd9140945011edcbce692a37f5f7cbd8334730c6955bb30907758d7bda777b77": { "source": { "path": "aws-cdk-elbv2-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-us-west-2": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", - "objectKey": "07df570609ba80d7ccc6a61dc96229756a5e4fc6a10d9a68ac076b94a8ce3e55.json", + "objectKey": "dd9140945011edcbce692a37f5f7cbd8334730c6955bb30907758d7bda777b77.json", "region": "us-west-2", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json index ce3d2ff8e018f..428814b9ed734 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/aws-cdk-elbv2-integ.template.json @@ -412,6 +412,20 @@ { "Key": "access_logs.s3.prefix", "Value": "" + }, + { + "Key": "connection_logs.s3.enabled", + "Value": "true" + }, + { + "Key": "connection_logs.s3.bucket", + "Value": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + } + }, + { + "Key": "connection_logs.s3.prefix", + "Value": "" } ], "Scheme": "internet-facing", @@ -434,7 +448,8 @@ "Type": "application" }, "DependsOn": [ - "LBALBAccessLogsBucket6AE92937", + "LBALBAccessLogsBucketPolicy1E4EBAFE", + "LBALBConnectionLogsBucketPolicy62509153", "VPCPublicSubnet1DefaultRoute91CEF279", "VPCPublicSubnet1RouteTableAssociation0B0896DC", "VPCPublicSubnet2DefaultRouteB7481BBA", @@ -647,6 +662,185 @@ } } }, + "LBALBConnectionLogsBucket4BFA48DB": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketEncryption": { + "ServerSideEncryptionConfiguration": [ + { + "ServerSideEncryptionByDefault": { + "SSEAlgorithm": "AES256" + } + } + ] + }, + "LoggingConfiguration": { + "LogFilePrefix": "selflog/" + }, + "PublicAccessBlockConfiguration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + }, + "VersioningConfiguration": { + "Status": "Enabled" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "LBALBConnectionLogsBucketPolicy62509153": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:PutObject", + "Condition": { + "ArnLike": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + } + }, + "StringEquals": { + "aws:SourceAccount": { + "Ref": "AWS::AccountId" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "logging.s3.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/selflog/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + } + } + }, "LBListener49E825B4": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "Properties": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out index 560dae10d018f..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"33.0.0"} \ No newline at end of file +{"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.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json index c98fca8690504..dc7f5be9c0bd5 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/cdkintegalbextendedlogDefaultTestDeployAssertAEFAB19B.assets.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json index b013204787762..28a35b8f9fe2f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.0", "testCases": { "cdk-integ-alb-extended-log/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json index e13264e6591cb..0e3250c83fd85 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "33.0.0", + "version": "36.0.0", "artifacts": { "aws-cdk-elbv2-integ.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/07df570609ba80d7ccc6a61dc96229756a5e4fc6a10d9a68ac076b94a8ce3e55.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/dd9140945011edcbce692a37f5f7cbd8334730c6955bb30907758d7bda777b77.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -196,6 +196,18 @@ "data": "LBALBAccessLogsBucketPolicy1E4EBAFE" } ], + "/aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBALBConnectionLogsBucket4BFA48DB" + } + ], + "/aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBALBConnectionLogsBucketPolicy62509153" + } + ], "/aws-cdk-elbv2-integ/LB/Listener/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json index 42f17234eebb4..c87d487493897 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.js.snapshot/tree.json @@ -679,6 +679,20 @@ { "key": "access_logs.s3.prefix", "value": "" + }, + { + "key": "connection_logs.s3.enabled", + "value": "true" + }, + { + "key": "connection_logs.s3.bucket", + "value": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + } + }, + { + "key": "connection_logs.s3.prefix", + "value": "" } ], "scheme": "internet-facing", @@ -964,6 +978,219 @@ "version": "0.0.0" } }, + "ALBConnectionLogsBucket": { + "id": "ALBConnectionLogsBucket", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "bucketEncryption": { + "serverSideEncryptionConfiguration": [ + { + "serverSideEncryptionByDefault": { + "sseAlgorithm": "AES256" + } + } + ] + }, + "loggingConfiguration": { + "logFilePrefix": "selflog/" + }, + "publicAccessBlockConfiguration": { + "blockPublicAcls": true, + "blockPublicPolicy": true, + "ignorePublicAcls": true, + "restrictPublicBuckets": true + }, + "versioningConfiguration": { + "status": "Enabled" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-elbv2-integ/LB/ALBConnectionLogsBucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "LBALBConnectionLogsBucket4BFA48DB" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:*", + "Condition": { + "Bool": { + "aws:SecureTransport": "false" + } + }, + "Effect": "Deny", + "Principal": { + "AWS": "*" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:PutObject", + "Condition": { + "ArnLike": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + } + }, + "StringEquals": { + "aws:SourceAccount": { + "Ref": "AWS::AccountId" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "logging.s3.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/selflog/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "Arn" + ] + }, + "/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "LBALBConnectionLogsBucket4BFA48DB", + "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" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, "Listener": { "id": "Listener", "path": "aws-cdk-elbv2-integ/LB/Listener", @@ -1089,7 +1316,7 @@ "path": "cdk-integ-alb-extended-log/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } }, "DeployAssert": { @@ -1135,7 +1362,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts index 17b1a0009461e..5fc676d118357 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.extended.log.ts @@ -18,8 +18,16 @@ class ExtendedLB extends elbv2.ApplicationLoadBalancer { serverAccessLogsPrefix: 'selflog/', enforceSSL: true, }); - this.logAccessLogs(accessLogsBucket); + + const connectionLogsBucket = new s3.Bucket(this, 'ALBConnectionLogsBucket', { + blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, + encryption: s3.BucketEncryption.S3_MANAGED, + versioned: true, + serverAccessLogsPrefix: 'selflog/', + enforceSSL: true, + }); + this.logConnectionLogs(connectionLogsBucket); } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json index 3e91c58d25201..9234509c27957 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "34.0.0", + "version": "36.0.0", "files": { - "d102d01a93a63d71a570164bdea30b0eca472ac745027643a4a1b0adb9b0640b": { + "7bcbcac4ed21e823d8252892771a6da060dd1d6110cdf42e73693f1e5c831046": { "source": { "path": "aws-cdk-alb-log-imported-bucket-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-us-west-2": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", - "objectKey": "d102d01a93a63d71a570164bdea30b0eca472ac745027643a4a1b0adb9b0640b.json", + "objectKey": "7bcbcac4ed21e823d8252892771a6da060dd1d6110cdf42e73693f1e5c831046.json", "region": "us-west-2", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json index e596a9c1e41e8..ff10559471e6d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/aws-cdk-alb-log-imported-bucket-integ.template.json @@ -438,6 +438,47 @@ "Principal": { "Service": "delivery.logs.amazonaws.com" }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, "Resource": { "Fn::Join": [ "", @@ -445,21 +486,16 @@ "arn:aws:s3:::", { "Ref": "Bucket83908E77" - }, - "/prefix/AWSLogs/", - { - "Ref": "AWS::AccountId" - }, - "/*" + } ] ] } }, { - "Action": "s3:GetBucketAcl", + "Action": "s3:PutObject", "Effect": "Allow", "Principal": { - "Service": "delivery.logs.amazonaws.com" + "AWS": "arn:aws:iam::797873946194:root" }, "Resource": { "Fn::Join": [ @@ -468,7 +504,12 @@ "arn:aws:s3:::", { "Ref": "Bucket83908E77" - } + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" ] ] } @@ -499,6 +540,20 @@ { "Key": "access_logs.s3.prefix", "Value": "prefix" + }, + { + "Key": "connection_logs.s3.enabled", + "Value": "true" + }, + { + "Key": "connection_logs.s3.bucket", + "Value": { + "Ref": "Bucket83908E77" + } + }, + { + "Key": "connection_logs.s3.prefix", + "Value": "prefix-connection-log" } ], "Scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out index 2313ab5436501..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"34.0.0"} \ No newline at end of file +{"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.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json index e45f2e7f3aa99..33278825135ec 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/cdkintegalblogimportedbucketDefaultTestDeployAssert163162C1.assets.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json index 5198aa8d08cc7..c2f7d046cc525 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "testCases": { "cdk-integ-alb-log-imported-bucket/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json index 4c9a325295e57..e0362c5216bff 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "artifacts": { "aws-cdk-alb-log-imported-bucket-integ.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/d102d01a93a63d71a570164bdea30b0eca472ac745027643a4a1b0adb9b0640b.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/7bcbcac4ed21e823d8252892771a6da060dd1d6110cdf42e73693f1e5c831046.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -178,10 +178,10 @@ "data": "Bucket83908E77" } ], - "/aws-cdk-alb-log-imported-bucket-integ/ImportedBucket/Policy/Resource": [ + "/aws-cdk-alb-log-imported-bucket-integ/ImportedBucketPolicy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "ImportedBucketPolicy71C80354" + "data": "ImportedBucketPolicyAE50CA2C" } ], "/aws-cdk-alb-log-imported-bucket-integ/LB/Resource": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json index ebc9d24af07a2..f5423598f7b90 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.js.snapshot/tree.json @@ -676,110 +676,149 @@ "ImportedBucket": { "id": "ImportedBucket", "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucket", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + }, + "ImportedBucketPolicy": { + "id": "ImportedBucketPolicy", + "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucketPolicy", "children": { - "Policy": { - "id": "Policy", - "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucket/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucket/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", - "aws:cdk:cloudformation:props": { - "bucket": { - "Ref": "Bucket83908E77" + "Resource": { + "id": "Resource", + "path": "aws-cdk-alb-log-imported-bucket-integ/ImportedBucketPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "Bucket83908E77" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } }, - "policyDocument": { - "Statement": [ + { + "Action": "s3:PutObject", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": [ { - "Action": "s3:PutObject", - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam::797873946194:root" - }, - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "Bucket83908E77" - }, - "/prefix/AWSLogs/", - { - "Ref": "AWS::AccountId" - }, - "/*" - ] + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" ] - } + ] }, { - "Action": "s3:PutObject", - "Condition": { - "StringEquals": { - "s3:x-amz-acl": "bucket-owner-full-control" - } - }, - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "Bucket83908E77" - }, - "/prefix/AWSLogs/", - { - "Ref": "AWS::AccountId" - }, - "/*" - ] + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" ] - } - }, - { - "Action": "s3:GetBucketAcl", - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "Bucket83908E77" - } - ] - ] - } + ] } - ], - "Version": "2012-10-17" + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + } + ] + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "Bucket83908E77" + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", - "version": "0.0.0" + ], + "Version": "2012-10-17" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", "version": "0.0.0" } }, @@ -811,6 +850,20 @@ { "key": "access_logs.s3.prefix", "value": "prefix" + }, + { + "key": "connection_logs.s3.enabled", + "value": "true" + }, + { + "key": "connection_logs.s3.bucket", + "value": { + "Ref": "Bucket83908E77" + } + }, + { + "key": "connection_logs.s3.prefix", + "value": "prefix-connection-log" } ], "scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts index 0aefeaa37378e..cd79500605179 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.imported-bucket.ts @@ -27,6 +27,7 @@ const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { }); lb.logAccessLogs(importedBucket, 'prefix'); +lb.logConnectionLogs(importedBucket, 'prefix-connection-log'); const listener = lb.addListener('Listener', { port: 80, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json index 462409afac89d..19a55187da880 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.assets.json @@ -15,7 +15,7 @@ } } }, - "e8dcef11b871328ec18d29401ebba343dec78affd3ec6055ab6d8be5b9223c97": { + "c4df03d0ac9684e50da08e315219cabc9dd964956b22ef483cb737334b396ac8": { "source": { "path": "aws-cdk-elbv2-integ.template.json", "packaging": "file" @@ -23,7 +23,7 @@ "destinations": { "current_account-us-west-2": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2", - "objectKey": "e8dcef11b871328ec18d29401ebba343dec78affd3ec6055ab6d8be5b9223c97.json", + "objectKey": "c4df03d0ac9684e50da08e315219cabc9dd964956b22ef483cb737334b396ac8.json", "region": "us-west-2", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-west-2" } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json index 49fdcd32c9472..77f2b0a8c6b32 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/aws-cdk-elbv2-integ.template.json @@ -487,6 +487,64 @@ "Principal": { "Service": "delivery.logs.amazonaws.com" }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, "Resource": { "Fn::Join": [ "", @@ -497,7 +555,7 @@ "Arn" ] }, - "/prefix/AWSLogs/", + "/prefix-connection-log/AWSLogs/", { "Ref": "AWS::AccountId" }, @@ -505,19 +563,6 @@ ] ] } - }, - { - "Action": "s3:GetBucketAcl", - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::GetAtt": [ - "Bucket83908E77", - "Arn" - ] - } } ], "Version": "2012-10-17" @@ -622,6 +667,20 @@ { "Key": "access_logs.s3.prefix", "Value": "prefix" + }, + { + "Key": "connection_logs.s3.enabled", + "Value": "true" + }, + { + "Key": "connection_logs.s3.bucket", + "Value": { + "Ref": "Bucket83908E77" + } + }, + { + "Key": "connection_logs.s3.prefix", + "Value": "prefix-connection-log" } ], "Scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json index 0cd90bc7f55a6..1fe10a574fc59 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-west-2", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-west-2", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/e8dcef11b871328ec18d29401ebba343dec78affd3ec6055ab6d8be5b9223c97.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-west-2/c4df03d0ac9684e50da08e315219cabc9dd964956b22ef483cb737334b396ac8.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json index 90720258641d3..819371b497c9a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.js.snapshot/tree.json @@ -764,6 +764,64 @@ "Principal": { "Service": "delivery.logs.amazonaws.com" }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix-connection-log/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + }, + "/prefix/AWSLogs/", + { + "Ref": "AWS::AccountId" + }, + "/*" + ] + ] + } + ] + }, + { + "Action": "s3:GetBucketAcl", + "Effect": "Allow", + "Principal": { + "Service": "delivery.logs.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "Bucket83908E77", + "Arn" + ] + } + }, + { + "Action": "s3:PutObject", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::797873946194:root" + }, "Resource": { "Fn::Join": [ "", @@ -774,7 +832,7 @@ "Arn" ] }, - "/prefix/AWSLogs/", + "/prefix-connection-log/AWSLogs/", { "Ref": "AWS::AccountId" }, @@ -782,19 +840,6 @@ ] ] } - }, - { - "Action": "s3:GetBucketAcl", - "Effect": "Allow", - "Principal": { - "Service": "delivery.logs.amazonaws.com" - }, - "Resource": { - "Fn::GetAtt": [ - "Bucket83908E77", - "Arn" - ] - } } ], "Version": "2012-10-17" @@ -898,6 +943,20 @@ { "key": "access_logs.s3.prefix", "value": "prefix" + }, + { + "key": "connection_logs.s3.enabled", + "value": "true" + }, + { + "key": "connection_logs.s3.bucket", + "value": { + "Ref": "Bucket83908E77" + } + }, + { + "key": "connection_logs.s3.prefix", + "value": "prefix-connection-log" } ], "scheme": "internet-facing", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts index cab793d0e6a35..69a96e98340f6 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-elasticloadbalancingv2/test/integ.alb.log.ts @@ -25,6 +25,7 @@ const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { }); lb.logAccessLogs(bucket, 'prefix'); +lb.logConnectionLogs(bucket, 'prefix-connection-log'); const listener = lb.addListener('Listener', { port: 80, diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md index 0f16e99b08917..3fbbce053d021 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/README.md @@ -267,6 +267,22 @@ lb.logAccessLogs(bucket); ``` +### Setting up Connection Log Bucket on Application Load Balancer + +Like access log bucket, the only server-side encryption option that's supported is Amazon S3-managed keys (SSE-S3). For more information +Documentation: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html + +```ts +declare const vpc: ec2.Vpc; + +const bucket = new s3.Bucket(this, 'ALBConnectionLogsBucket',{ + encryption: s3.BucketEncryption.S3_MANAGED, +}); + +const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { vpc }); +lb.logConnectionLogs(bucket); +``` + ## Defining a Network Load Balancer Network Load Balancers are defined in a similar way to Application Load diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts index 0ec173c7b77df..2636e26abbdd5 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts @@ -312,6 +312,68 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic } } + /** + * Enable connection logging for this load balancer. + * + * A region must be specified on the stack containing the load balancer; you cannot enable logging on + * environment-agnostic stacks. + * + * @see https://docs.aws.amazon.com/cdk/latest/guide/environments.html + */ + public logConnectionLogs(bucket: s3.IBucket, prefix?: string) { + /** + * KMS key encryption is not supported on Connection Log bucket for ALB, the bucket must use Amazon S3-managed keys (SSE-S3). + * See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html#bucket-permissions-troubleshooting-connection + */ + if (bucket.encryptionKey) { + throw new Error('Encryption key detected. Bucket encryption using KMS keys is unsupported'); + } + + prefix = prefix || ''; + this.setAttribute('connection_logs.s3.enabled', 'true'); + this.setAttribute('connection_logs.s3.bucket', bucket.bucketName.toString()); + this.setAttribute('connection_logs.s3.prefix', prefix); + + // https://docs.aws.amazon.com/elasticloadbalancing/latest/application/enable-connection-logging.html + const logsDeliveryServicePrincipal = new ServicePrincipal('delivery.logs.amazonaws.com'); + bucket.addToResourcePolicy(new PolicyStatement({ + actions: ['s3:PutObject'], + principals: [this.resourcePolicyPrincipal()], + resources: [ + bucket.arnForObjects(`${prefix ? prefix + '/' : ''}AWSLogs/${Stack.of(this).account}/*`), + ], + })); + // We still need this policy for the bucket using the ACL + bucket.addToResourcePolicy( + new PolicyStatement({ + actions: ['s3:PutObject'], + principals: [logsDeliveryServicePrincipal], + resources: [ + bucket.arnForObjects(`${prefix ? prefix + '/' : ''}AWSLogs/${Stack.of(this).account}/*`), + ], + conditions: { + StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' }, + }, + }), + ); + bucket.addToResourcePolicy( + new PolicyStatement({ + actions: ['s3:GetBucketAcl'], + principals: [logsDeliveryServicePrincipal], + resources: [bucket.bucketArn], + }), + ); + + // make sure the bucket's policy is created before the ALB (see https://github.com/aws/aws-cdk/issues/1633) + // at the L1 level to avoid creating a circular dependency (see https://github.com/aws/aws-cdk/issues/27528 + // and https://github.com/aws/aws-cdk/issues/27928) + const lb = this.node.defaultChild; + const bucketPolicy = bucket.policy?.node.defaultChild; + if (lb && bucketPolicy && CfnResource.isCfnResource(lb) && CfnResource.isCfnResource(bucketPolicy)) { + lb.addDependency(bucketPolicy); + } + } + /** * Add a security group to this load balancer */ diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts index 958a881846fab..6838181872275 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts @@ -645,6 +645,345 @@ describe('tests', () => { }); }); + describe('logConnectionLogs', () => { + + class ExtendedLB extends elbv2.ApplicationLoadBalancer { + constructor(scope: Construct, id: string, vpc: ec2.IVpc) { + super(scope, id, { vpc }); + + const connectionLogsBucket = new s3.Bucket(this, 'ALBConnectionLogsBucket', { + blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, + encryption: s3.BucketEncryption.S3_MANAGED, + versioned: true, + serverAccessLogsPrefix: 'selflog/', + enforceSSL: true, + }); + + this.logConnectionLogs(connectionLogsBucket); + } + } + + function loggingSetup(withEncryption: boolean = false ): { stack: cdk.Stack; bucket: s3.Bucket; lb: elbv2.ApplicationLoadBalancer } { + const app = new cdk.App(); + const stack = new cdk.Stack(app, undefined, { env: { region: 'us-east-1' } }); + const vpc = new ec2.Vpc(stack, 'Stack'); + let bucketProps = {}; + if (withEncryption) { + const kmsKey = new Key(stack, 'TestKMSKey'); + bucketProps = { ...bucketProps, encryption: s3.BucketEncryption.KMS, encyptionKey: kmsKey }; + } + const bucket = new s3.Bucket(stack, 'ConnectionLogBucket', { ...bucketProps }); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + return { stack, bucket, lb }; + } + + test('sets load balancer attributes', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket); + + //THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'connection_logs.s3.enabled', + Value: 'true', + }, + { + Key: 'connection_logs.s3.bucket', + Value: { Ref: 'ConnectionLogBucketFDE8490A' }, + }, + { + Key: 'connection_logs.s3.prefix', + Value: '', + }, + ]), + }); + }); + + test('adds a dependency on the bucket', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket); + + // THEN + // verify the ALB depends on the bucket policy + Template.fromStack(stack).hasResource('AWS::ElasticLoadBalancingV2::LoadBalancer', { + DependsOn: ['ConnectionLogBucketPolicyF17C8635'], + }); + }); + + test('logging bucket permissions', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket); + + // THEN + // verify the bucket policy allows the ALB to put objects in the bucket + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { + PolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { AWS: { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::127311923021:root']] } }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + }, + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + Condition: { StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' } }, + }, + { + Action: 's3:GetBucketAcl', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'], + }, + }, + ], + }, + }); + }); + + test('connection logging with prefix', () => { + // GIVEN + const { stack, bucket, lb } = loggingSetup(); + + // WHEN + lb.logConnectionLogs(bucket, 'prefix-of-connection-logs'); + + // THEN + // verify that the LB attributes reference the bucket + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'connection_logs.s3.enabled', + Value: 'true', + }, + { + Key: 'connection_logs.s3.bucket', + Value: { Ref: 'ConnectionLogBucketFDE8490A' }, + }, + { + Key: 'connection_logs.s3.prefix', + Value: 'prefix-of-connection-logs', + }, + ]), + }); + + // verify the bucket policy allows the ALB to put objects in the bucket + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { + PolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { AWS: { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::127311923021:root']] } }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/prefix-of-connection-logs/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + }, + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': ['', [{ 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'] }, '/prefix-of-connection-logs/AWSLogs/', + { Ref: 'AWS::AccountId' }, '/*']], + }, + Condition: { StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' } }, + }, + { + Action: 's3:GetBucketAcl', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::GetAtt': ['ConnectionLogBucketFDE8490A', 'Arn'], + }, + }, + ], + }, + }); + }); + + test('bucket with KMS throws validation error', () => { + //GIVEN + const { stack, bucket, lb } = loggingSetup(true); + + // WHEN + const logConnectionLogFunctionTest = () => lb.logConnectionLogs(bucket); + + // THEN + // verify failure in case the connection log bucket is encrypted with KMS + expect(logConnectionLogFunctionTest).toThrow('Encryption key detected. Bucket encryption using KMS keys is unsupported'); + + }); + + test('connection logging on imported bucket', () => { + // GIVEN + const { stack, lb } = loggingSetup(); + + const bucket = s3.Bucket.fromBucketName(stack, 'ImportedConnectionLoggingBucket', 'imported-bucket'); + // Imported buckets have `autoCreatePolicy` disabled by default + bucket.policy = new s3.BucketPolicy(stack, 'ImportedConnectionLoggingBucketPolicy', { + bucket, + }); + + // WHEN + lb.logConnectionLogs(bucket); + + // THEN + // verify that the LB attributes reference the bucket + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', { + LoadBalancerAttributes: Match.arrayWith([ + { + Key: 'connection_logs.s3.enabled', + Value: 'true', + }, + { + Key: 'connection_logs.s3.bucket', + Value: 'imported-bucket', + }, + { + Key: 'connection_logs.s3.prefix', + Value: '', + }, + ]), + }); + + // verify the bucket policy allows the ALB to put objects in the bucket + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { + PolicyDocument: { + Version: '2012-10-17', + Statement: [ + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { AWS: { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::127311923021:root']] } }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':s3:::imported-bucket/AWSLogs/', + { Ref: 'AWS::AccountId' }, + '/*', + ], + ], + }, + }, + { + Action: 's3:PutObject', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':s3:::imported-bucket/AWSLogs/', + { Ref: 'AWS::AccountId' }, + '/*', + ], + ], + }, + Condition: { StringEquals: { 's3:x-amz-acl': 'bucket-owner-full-control' } }, + }, + { + Action: 's3:GetBucketAcl', + Effect: 'Allow', + Principal: { Service: 'delivery.logs.amazonaws.com' }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':s3:::imported-bucket', + ], + ], + }, + }, + ], + }, + }); + + // verify the ALB depends on the bucket policy + Template.fromStack(stack).hasResource('AWS::ElasticLoadBalancingV2::LoadBalancer', { + DependsOn: ['ImportedConnectionLoggingBucketPolicy548EEC12'], + }); + }); + + test('does not add circular dependency on bucket with extended load balancer', () => { + // GIVEN + const { stack } = loggingSetup(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + + // WHEN + new ExtendedLB(stack, 'ExtendedLB', vpc); + + // THEN + Template.fromStack(stack).hasResource('AWS::S3::Bucket', { + Type: 'AWS::S3::Bucket', + Properties: { + AccessControl: 'LogDeliveryWrite', + BucketEncryption: { + ServerSideEncryptionConfiguration: [ + { + ServerSideEncryptionByDefault: { + SSEAlgorithm: 'AES256', + }, + }, + ], + }, + LoggingConfiguration: { + LogFilePrefix: 'selflog/', + }, + OwnershipControls: { + Rules: [ + { + ObjectOwnership: 'ObjectWriter', + }, + ], + }, + PublicAccessBlockConfiguration: { + BlockPublicAcls: true, + BlockPublicPolicy: true, + IgnorePublicAcls: true, + RestrictPublicBuckets: true, + }, + VersioningConfiguration: { + Status: 'Enabled', + }, + }, + UpdateReplacePolicy: 'Retain', + DeletionPolicy: 'Retain', + DependsOn: Match.absent(), + }); + }); + }); + test('Exercise metrics', () => { // GIVEN const stack = new cdk.Stack();