From 090014808b4bec0e23fcac3fc3907dffa9600954 Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Mon, 17 Jun 2024 19:03:10 +0900 Subject: [PATCH 1/7] feat(cloudfront): add attachWebAclId method for Distribution --- ...aws-cdk-cloudfront-with-webacl.assets.json | 19 ++ ...s-cdk-cloudfront-with-webacl.template.json | 83 ++++++++ .../cdk.out | 1 + .../integ.json | 12 ++ ...efaultTestDeployAssert166CAFCF.assets.json | 19 ++ ...aultTestDeployAssert166CAFCF.template.json | 36 ++++ .../manifest.json | 119 ++++++++++++ .../tree.json | 181 ++++++++++++++++++ .../test/integ.cloudfront-with-webacl.ts | 36 ++++ packages/aws-cdk-lib/aws-cloudfront/README.md | 46 ++++- .../aws-cloudfront/lib/distribution.ts | 16 +- .../aws-cloudfront/test/distribution.test.ts | 31 +++ .../rosetta/aws_cloudfront/default.ts-fixture | 1 + 13 files changed, 591 insertions(+), 9 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json new file mode 100644 index 0000000000000..9cbbbfe967006 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186": { + "source": { + "path": "aws-cdk-cloudfront-with-webacl.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json new file mode 100644 index 0000000000000..bfaa179b7fa34 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json @@ -0,0 +1,83 @@ +{ + "Resources": { + "WebAcl": { + "Type": "AWS::WAFv2::WebACL", + "Properties": { + "DefaultAction": { + "Allow": {} + }, + "Scope": "CLOUDFRONT", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": false, + "MetricName": "webAclMetric", + "SampledRequestsEnabled": false + } + } + }, + "Distribution830FAC52": { + "Type": "AWS::CloudFront::Distribution", + "Properties": { + "DistributionConfig": { + "DefaultCacheBehavior": { + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", + "Compress": true, + "TargetOriginId": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", + "ViewerProtocolPolicy": "allow-all" + }, + "Enabled": true, + "HttpVersion": "http2", + "IPV6Enabled": true, + "Origins": [ + { + "CustomOriginConfig": { + "OriginProtocolPolicy": "https-only" + }, + "DomainName": "www.example.com", + "Id": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663" + } + ], + "WebACLId": { + "Fn::GetAtt": [ + "WebAcl", + "Arn" + ] + } + } + } + } + }, + "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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json new file mode 100644 index 0000000000000..b94d99be5517f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "integ-cloudfront-with-webacl/DefaultTest": { + "stacks": [ + "aws-cdk-cloudfront-with-webacl" + ], + "assertionStack": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert", + "assertionStackName": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json new file mode 100644 index 0000000000000..51c22564b38bc --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json new file mode 100644 index 0000000000000..5b42d422302a5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json @@ -0,0 +1,119 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-cloudfront-with-webacl.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-cloudfront-with-webacl.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-cloudfront-with-webacl": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-cloudfront-with-webacl.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}/376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-cloudfront-with-webacl.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-cloudfront-with-webacl.assets" + ], + "metadata": { + "/aws-cdk-cloudfront-with-webacl/WebAcl": [ + { + "type": "aws:cdk:logicalId", + "data": "WebAcl" + } + ], + "/aws-cdk-cloudfront-with-webacl/Distribution/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Distribution830FAC52" + } + ], + "/aws-cdk-cloudfront-with-webacl/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-cloudfront-with-webacl/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-cloudfront-with-webacl" + }, + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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": [ + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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": [ + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets" + ], + "metadata": { + "/integ-cloudfront-with-webacl/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-cloudfront-with-webacl/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-cloudfront-with-webacl/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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json new file mode 100644 index 0000000000000..9ce07a8dc2fb2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json @@ -0,0 +1,181 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-cloudfront-with-webacl": { + "id": "aws-cdk-cloudfront-with-webacl", + "path": "aws-cdk-cloudfront-with-webacl", + "children": { + "WebAcl": { + "id": "WebAcl", + "path": "aws-cdk-cloudfront-with-webacl/WebAcl", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::WAFv2::WebACL", + "aws:cdk:cloudformation:props": { + "defaultAction": { + "allow": {} + }, + "scope": "CLOUDFRONT", + "visibilityConfig": { + "cloudWatchMetricsEnabled": false, + "metricName": "webAclMetric", + "sampledRequestsEnabled": false + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Distribution": { + "id": "Distribution", + "path": "aws-cdk-cloudfront-with-webacl/Distribution", + "children": { + "Origin1": { + "id": "Origin1", + "path": "aws-cdk-cloudfront-with-webacl/Distribution/Origin1", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-cloudfront-with-webacl/Distribution/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFront::Distribution", + "aws:cdk:cloudformation:props": { + "distributionConfig": { + "enabled": true, + "origins": [ + { + "domainName": "www.example.com", + "id": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", + "customOriginConfig": { + "originProtocolPolicy": "https-only" + } + } + ], + "defaultCacheBehavior": { + "pathPattern": "*", + "targetOriginId": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", + "cachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", + "compress": true, + "viewerProtocolPolicy": "allow-all" + }, + "httpVersion": "http2", + "ipv6Enabled": true, + "webAclId": { + "Fn::GetAtt": [ + "WebAcl", + "Arn" + ] + } + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-cloudfront-with-webacl/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-cloudfront-with-webacl/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "integ-cloudfront-with-webacl": { + "id": "integ-cloudfront-with-webacl", + "path": "integ-cloudfront-with-webacl", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-cloudfront-with-webacl/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-cloudfront-with-webacl/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.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": "constructs.Construct", + "version": "10.3.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts new file mode 100644 index 0000000000000..a862e751c566d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts @@ -0,0 +1,36 @@ + +import * as cdk from 'aws-cdk-lib'; +import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { TestOrigin } from './test-origin'; +import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-cloudfront-with-webacl', { + env: { + region: 'us-east-1', + }, +}); + +const webAcl = new CfnWebACL(stack, 'WebAcl', { + defaultAction: { + allow: {}, + }, + scope: 'CLOUDFRONT', + visibilityConfig: { + cloudWatchMetricsEnabled: false, + metricName: 'webAclMetric', + sampledRequestsEnabled: false, + }, +}); + +const distribution = new cloudfront.Distribution(stack, 'Distribution', { + defaultBehavior: { origin: new TestOrigin('www.example.com') }, +}); + +distribution.attachWebAclId(webAcl.attrArn); + +new IntegTest(app, 'integ-cloudfront-with-webacl', { + testCases: [stack], +}); diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index 965e3cbac7f69..ffcd70ca0a6be 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -1,6 +1,5 @@ # Amazon CloudFront Construct Library - Amazon CloudFront is a web service that speeds up distribution of your static and dynamic web content, such as .html, .css, .js, and image files, to your users. CloudFront delivers your content through a worldwide network of data centers called edge locations. When a user requests content that you're serving with CloudFront, the user is routed to the edge location that provides the lowest latency, so that content is delivered with the best @@ -211,13 +210,44 @@ new cloudfront.Distribution(this, 'myDist', { }); ``` +### Attaching WAF Web Acls + +You can attach the AWS WAF web ACL to a CloudFront distribution. + +To specify a web ACL created using the latest version of AWS WAF, use the ACL ARN, for example +`arn:aws:wafv2:us-east-1:123456789012:global/webacl/ExampleWebACL/473e64fd-f30b-4765-81a0-62ad96dd167a`. +The web ACL must be in the `us-east-1` region. + +To specify a web ACL created using AWS WAF Classic, use the ACL ID, for example `473e64fd-f30b-4765-81a0-62ad96dd167a`. + +```ts +declare const bucketOrigin: origins.S3Origin; +declare const webAcl: wafv2.CfnWebACL; +const distribution = new cloudfront.Distribution(stack, 'Distribution', { + defaultBehavior: { origin: bucketOrigin }, + webAclId: webAcl.attrArn, +}); +``` + +You can also attach a web ACL to a distribution after creation. + +```ts +declare const bucketOrigin: origins.S3Origin; +declare const webAcl: wafv2.CfnWebACL; +const distribution = new cloudfront.Distribution(stack, 'Distribution', { + defaultBehavior: { origin: bucketOrigin }, +}); + +distribution.attachWebAclId(webAcl.attrArn); +``` + ### Customizing Cache Keys and TTLs with Cache Policies You can use a cache policy to improve your cache hit ratio by controlling the values (URL query strings, HTTP headers, and cookies) that are included in the cache key, and/or adjusting how long items remain in the cache via the time-to-live (TTL) settings. CloudFront provides some predefined cache policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own cache policy that’s specific to your needs. -See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html for more details. +See for more details. ```ts // Using an existing cache policy for a Distribution @@ -260,7 +290,7 @@ Other information from the viewer request, such as URL query strings, HTTP heade You can use an origin request policy to control the information that’s included in an origin request. CloudFront provides some predefined origin request policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own origin request policy that’s specific to your needs. -See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.html for more details. +See for more details. ```ts // Using an existing origin request policy for a Distribution @@ -296,7 +326,7 @@ new cloudfront.Distribution(this, 'myDistCustomPolicy', { You can configure CloudFront to add one or more HTTP headers to the responses that it sends to viewers (web browsers or other clients), without making any changes to the origin or writing any code. To specify the headers that CloudFront adds to HTTP responses, you use a response headers policy. CloudFront adds the headers regardless of whether it serves the object from the cache or has to retrieve the object from the origin. If the origin response includes one or more of the headers that’s in a response headers policy, the policy can specify whether CloudFront uses the header it received from the origin or overwrites it with the one in the policy. -See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-response-headers.html +See ```ts // Using an existing managed response headers policy @@ -418,7 +448,7 @@ new cloudfront.Distribution(this, 'myDist', { > The `EdgeFunction` construct will automatically request a function in `us-east-1`, regardless of the region of the current stack. > `EdgeFunction` has the same interface as `Function` and can be created and used interchangeably. > Please note that using `EdgeFunction` requires that the `us-east-1` region has been bootstrapped. -> See https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html for more about bootstrapping regions. +> See for more about bootstrapping regions. If the stack is in `us-east-1`, a "normal" `lambda.Function` can be used instead of an `EdgeFunction`. @@ -558,7 +588,7 @@ To create an empty Key Value Store: const store = new cloudfront.KeyValueStore(this, 'KeyValueStore'); ``` -To also include an initial set of values, the `source` property can be specified, either from a +To also include an initial set of values, the `source` property can be specified, either from a local file or an inline string. For the structure of this file, see [Creating a file of key value pairs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/kvs-with-functions-create-s3-kvp.html). ```ts @@ -1177,5 +1207,5 @@ new cloudfront.KeyGroup(this, 'MyKeyGroup', { See: -* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html -* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html +- +- diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts index 336affec8b862..226886a3c3e50 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts @@ -309,6 +309,7 @@ export class Distribution extends Resource implements IDistribution { private readonly errorResponses: ErrorResponse[]; private readonly certificate?: acm.ICertificate; private readonly publishAdditionalMetrics?: boolean; + private webAclId?: string; constructor(scope: Construct, id: string, props: DistributionProps) { super(scope, id); @@ -335,6 +336,7 @@ export class Distribution extends Resource implements IDistribution { this.certificate = props.certificate; this.errorResponses = props.errorResponses ?? []; this.publishAdditionalMetrics = props.publishAdditionalMetrics; + this.webAclId = props.webAclId; // Comments have an undocumented limit of 128 characters const trimmedComment = @@ -360,7 +362,7 @@ export class Distribution extends Resource implements IDistribution { restrictions: this.renderRestrictions(props.geoRestriction), viewerCertificate: this.certificate ? this.renderViewerCertificate(this.certificate, props.minimumProtocolVersion, props.sslSupportMethod) : undefined, - webAclId: props.webAclId, + webAclId: Lazy.string({ produce: () => this.webAclId }), }, }); @@ -598,6 +600,18 @@ export class Distribution extends Resource implements IDistribution { return this.grant(identity, 'cloudfront:CreateInvalidation'); } + /** + * Attach WAF WebACL to this CloudFront distribution + * + * @param webAclId The WAF WebACL to associate with this distribution + */ + public attachWebAclId(webAclId: string) { + if (this.webAclId) { + throw new Error('A WebACL has already been attached to this distribution'); + } + this.webAclId = webAclId; + } + private addOrigin(origin: IOrigin, isFailoverOrigin: boolean = false): string { const ORIGIN_ID_MAX_LENGTH = 128; diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts index abd135a418632..24a61cd5eff42 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts @@ -1334,3 +1334,34 @@ describe('Distribution metrics tests', () => { }).toThrow(new RegExp(`${metric.errorMetricName} metric is only available if 'publishAdditionalMetrics' is set 'true'`)); }); }); + +describe('attachWebAclId', () => { + test('can attach WebAcl to the distribution by the method', () => { + const origin = defaultOrigin(); + + const distribution = new Distribution(stack, 'MyDist', { + defaultBehavior: { origin }, + }); + + distribution.attachWebAclId('473e64fd-f30b-4765-81a0-62ad96dd167a'); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', { + DistributionConfig: { + WebACLId: '473e64fd-f30b-4765-81a0-62ad96dd167a', + }, + }); + }); + + test('throws if a WebAcl is already attached to the distribution', () => { + const origin = defaultOrigin(); + + const distribution = new Distribution(stack, 'MyDist', { + defaultBehavior: { origin }, + webAclId: '473e64fd-f30b-4765-81a0-62ad96dd167a', + }); + + expect(() => { + distribution.attachWebAclId('473e64fd-f30b-4765-81a0-62ad96dd167b'); + }).toThrow(/A WebACL has already been attached to this distribution/); + }); +}); diff --git a/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture b/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture index d8c849ae21977..38de5258fdd15 100644 --- a/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture +++ b/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture @@ -6,6 +6,7 @@ import * as s3 from 'aws-cdk-lib/aws-s3'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as wafv2 from 'aws-cdk-lib/aws-wafv2'; import * as path from 'path'; class Context extends Stack { From 19b246bb66534fd42aa84ba779bca2faeaee5433 Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Mon, 17 Jun 2024 20:50:56 +0900 Subject: [PATCH 2/7] Revert "feat(cloudfront): add attachWebAclId method for Distribution" This reverts commit 090014808b4bec0e23fcac3fc3907dffa9600954. --- ...aws-cdk-cloudfront-with-webacl.assets.json | 19 -- ...s-cdk-cloudfront-with-webacl.template.json | 83 -------- .../cdk.out | 1 - .../integ.json | 12 -- ...efaultTestDeployAssert166CAFCF.assets.json | 19 -- ...aultTestDeployAssert166CAFCF.template.json | 36 ---- .../manifest.json | 119 ------------ .../tree.json | 181 ------------------ .../test/integ.cloudfront-with-webacl.ts | 36 ---- packages/aws-cdk-lib/aws-cloudfront/README.md | 46 +---- .../aws-cloudfront/lib/distribution.ts | 16 +- .../aws-cloudfront/test/distribution.test.ts | 31 --- .../rosetta/aws_cloudfront/default.ts-fixture | 1 - 13 files changed, 9 insertions(+), 591 deletions(-) delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json delete mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json deleted file mode 100644 index 9cbbbfe967006..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "36.0.0", - "files": { - "376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186": { - "source": { - "path": "aws-cdk-cloudfront-with-webacl.template.json", - "packaging": "file" - }, - "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json deleted file mode 100644 index bfaa179b7fa34..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "Resources": { - "WebAcl": { - "Type": "AWS::WAFv2::WebACL", - "Properties": { - "DefaultAction": { - "Allow": {} - }, - "Scope": "CLOUDFRONT", - "VisibilityConfig": { - "CloudWatchMetricsEnabled": false, - "MetricName": "webAclMetric", - "SampledRequestsEnabled": false - } - } - }, - "Distribution830FAC52": { - "Type": "AWS::CloudFront::Distribution", - "Properties": { - "DistributionConfig": { - "DefaultCacheBehavior": { - "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", - "Compress": true, - "TargetOriginId": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", - "ViewerProtocolPolicy": "allow-all" - }, - "Enabled": true, - "HttpVersion": "http2", - "IPV6Enabled": true, - "Origins": [ - { - "CustomOriginConfig": { - "OriginProtocolPolicy": "https-only" - }, - "DomainName": "www.example.com", - "Id": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663" - } - ], - "WebACLId": { - "Fn::GetAtt": [ - "WebAcl", - "Arn" - ] - } - } - } - } - }, - "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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out deleted file mode 100644 index 1f0068d32659a..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out +++ /dev/null @@ -1 +0,0 @@ -{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json deleted file mode 100644 index b94d99be5517f..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": "36.0.0", - "testCases": { - "integ-cloudfront-with-webacl/DefaultTest": { - "stacks": [ - "aws-cdk-cloudfront-with-webacl" - ], - "assertionStack": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert", - "assertionStackName": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json deleted file mode 100644 index 51c22564b38bc..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "36.0.0", - "files": { - "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { - "source": { - "path": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json deleted file mode 100644 index ad9d0fb73d1dd..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json deleted file mode 100644 index 5b42d422302a5..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "version": "36.0.0", - "artifacts": { - "aws-cdk-cloudfront-with-webacl.assets": { - "type": "cdk:asset-manifest", - "properties": { - "file": "aws-cdk-cloudfront-with-webacl.assets.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "aws-cdk-cloudfront-with-webacl": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", - "properties": { - "templateFile": "aws-cdk-cloudfront-with-webacl.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}/376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", - "additionalDependencies": [ - "aws-cdk-cloudfront-with-webacl.assets" - ], - "lookupRole": { - "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", - "requiresBootstrapStackVersion": 8, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "dependencies": [ - "aws-cdk-cloudfront-with-webacl.assets" - ], - "metadata": { - "/aws-cdk-cloudfront-with-webacl/WebAcl": [ - { - "type": "aws:cdk:logicalId", - "data": "WebAcl" - } - ], - "/aws-cdk-cloudfront-with-webacl/Distribution/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "Distribution830FAC52" - } - ], - "/aws-cdk-cloudfront-with-webacl/BootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "BootstrapVersion" - } - ], - "/aws-cdk-cloudfront-with-webacl/CheckBootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "CheckBootstrapVersion" - } - ] - }, - "displayName": "aws-cdk-cloudfront-with-webacl" - }, - "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets": { - "type": "cdk:asset-manifest", - "properties": { - "file": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json", - "requiresBootstrapStackVersion": 6, - "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" - } - }, - "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", - "properties": { - "templateFile": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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": [ - "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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": [ - "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets" - ], - "metadata": { - "/integ-cloudfront-with-webacl/DefaultTest/DeployAssert/BootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "BootstrapVersion" - } - ], - "/integ-cloudfront-with-webacl/DefaultTest/DeployAssert/CheckBootstrapVersion": [ - { - "type": "aws:cdk:logicalId", - "data": "CheckBootstrapVersion" - } - ] - }, - "displayName": "integ-cloudfront-with-webacl/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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json deleted file mode 100644 index 9ce07a8dc2fb2..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json +++ /dev/null @@ -1,181 +0,0 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "aws-cdk-cloudfront-with-webacl": { - "id": "aws-cdk-cloudfront-with-webacl", - "path": "aws-cdk-cloudfront-with-webacl", - "children": { - "WebAcl": { - "id": "WebAcl", - "path": "aws-cdk-cloudfront-with-webacl/WebAcl", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::WAFv2::WebACL", - "aws:cdk:cloudformation:props": { - "defaultAction": { - "allow": {} - }, - "scope": "CLOUDFRONT", - "visibilityConfig": { - "cloudWatchMetricsEnabled": false, - "metricName": "webAclMetric", - "sampledRequestsEnabled": false - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "Distribution": { - "id": "Distribution", - "path": "aws-cdk-cloudfront-with-webacl/Distribution", - "children": { - "Origin1": { - "id": "Origin1", - "path": "aws-cdk-cloudfront-with-webacl/Distribution/Origin1", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "Resource": { - "id": "Resource", - "path": "aws-cdk-cloudfront-with-webacl/Distribution/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudFront::Distribution", - "aws:cdk:cloudformation:props": { - "distributionConfig": { - "enabled": true, - "origins": [ - { - "domainName": "www.example.com", - "id": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", - "customOriginConfig": { - "originProtocolPolicy": "https-only" - } - } - ], - "defaultCacheBehavior": { - "pathPattern": "*", - "targetOriginId": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", - "cachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", - "compress": true, - "viewerProtocolPolicy": "allow-all" - }, - "httpVersion": "http2", - "ipv6Enabled": true, - "webAclId": { - "Fn::GetAtt": [ - "WebAcl", - "Arn" - ] - } - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "aws-cdk-cloudfront-with-webacl/BootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "aws-cdk-cloudfront-with-webacl/CheckBootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "integ-cloudfront-with-webacl": { - "id": "integ-cloudfront-with-webacl", - "path": "integ-cloudfront-with-webacl", - "children": { - "DefaultTest": { - "id": "DefaultTest", - "path": "integ-cloudfront-with-webacl/DefaultTest", - "children": { - "Default": { - "id": "Default", - "path": "integ-cloudfront-with-webacl/DefaultTest/Default", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "DeployAssert": { - "id": "DeployAssert", - "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert", - "children": { - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert/CheckBootstrapVersion", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.0" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.3.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": "constructs.Construct", - "version": "10.3.0" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts deleted file mode 100644 index a862e751c566d..0000000000000 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts +++ /dev/null @@ -1,36 +0,0 @@ - -import * as cdk from 'aws-cdk-lib'; -import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'; -import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -import { TestOrigin } from './test-origin'; -import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2'; - -const app = new cdk.App(); - -const stack = new cdk.Stack(app, 'aws-cdk-cloudfront-with-webacl', { - env: { - region: 'us-east-1', - }, -}); - -const webAcl = new CfnWebACL(stack, 'WebAcl', { - defaultAction: { - allow: {}, - }, - scope: 'CLOUDFRONT', - visibilityConfig: { - cloudWatchMetricsEnabled: false, - metricName: 'webAclMetric', - sampledRequestsEnabled: false, - }, -}); - -const distribution = new cloudfront.Distribution(stack, 'Distribution', { - defaultBehavior: { origin: new TestOrigin('www.example.com') }, -}); - -distribution.attachWebAclId(webAcl.attrArn); - -new IntegTest(app, 'integ-cloudfront-with-webacl', { - testCases: [stack], -}); diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index ffcd70ca0a6be..965e3cbac7f69 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -1,5 +1,6 @@ # Amazon CloudFront Construct Library + Amazon CloudFront is a web service that speeds up distribution of your static and dynamic web content, such as .html, .css, .js, and image files, to your users. CloudFront delivers your content through a worldwide network of data centers called edge locations. When a user requests content that you're serving with CloudFront, the user is routed to the edge location that provides the lowest latency, so that content is delivered with the best @@ -210,44 +211,13 @@ new cloudfront.Distribution(this, 'myDist', { }); ``` -### Attaching WAF Web Acls - -You can attach the AWS WAF web ACL to a CloudFront distribution. - -To specify a web ACL created using the latest version of AWS WAF, use the ACL ARN, for example -`arn:aws:wafv2:us-east-1:123456789012:global/webacl/ExampleWebACL/473e64fd-f30b-4765-81a0-62ad96dd167a`. -The web ACL must be in the `us-east-1` region. - -To specify a web ACL created using AWS WAF Classic, use the ACL ID, for example `473e64fd-f30b-4765-81a0-62ad96dd167a`. - -```ts -declare const bucketOrigin: origins.S3Origin; -declare const webAcl: wafv2.CfnWebACL; -const distribution = new cloudfront.Distribution(stack, 'Distribution', { - defaultBehavior: { origin: bucketOrigin }, - webAclId: webAcl.attrArn, -}); -``` - -You can also attach a web ACL to a distribution after creation. - -```ts -declare const bucketOrigin: origins.S3Origin; -declare const webAcl: wafv2.CfnWebACL; -const distribution = new cloudfront.Distribution(stack, 'Distribution', { - defaultBehavior: { origin: bucketOrigin }, -}); - -distribution.attachWebAclId(webAcl.attrArn); -``` - ### Customizing Cache Keys and TTLs with Cache Policies You can use a cache policy to improve your cache hit ratio by controlling the values (URL query strings, HTTP headers, and cookies) that are included in the cache key, and/or adjusting how long items remain in the cache via the time-to-live (TTL) settings. CloudFront provides some predefined cache policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own cache policy that’s specific to your needs. -See for more details. +See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html for more details. ```ts // Using an existing cache policy for a Distribution @@ -290,7 +260,7 @@ Other information from the viewer request, such as URL query strings, HTTP heade You can use an origin request policy to control the information that’s included in an origin request. CloudFront provides some predefined origin request policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own origin request policy that’s specific to your needs. -See for more details. +See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.html for more details. ```ts // Using an existing origin request policy for a Distribution @@ -326,7 +296,7 @@ new cloudfront.Distribution(this, 'myDistCustomPolicy', { You can configure CloudFront to add one or more HTTP headers to the responses that it sends to viewers (web browsers or other clients), without making any changes to the origin or writing any code. To specify the headers that CloudFront adds to HTTP responses, you use a response headers policy. CloudFront adds the headers regardless of whether it serves the object from the cache or has to retrieve the object from the origin. If the origin response includes one or more of the headers that’s in a response headers policy, the policy can specify whether CloudFront uses the header it received from the origin or overwrites it with the one in the policy. -See +See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-response-headers.html ```ts // Using an existing managed response headers policy @@ -448,7 +418,7 @@ new cloudfront.Distribution(this, 'myDist', { > The `EdgeFunction` construct will automatically request a function in `us-east-1`, regardless of the region of the current stack. > `EdgeFunction` has the same interface as `Function` and can be created and used interchangeably. > Please note that using `EdgeFunction` requires that the `us-east-1` region has been bootstrapped. -> See for more about bootstrapping regions. +> See https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html for more about bootstrapping regions. If the stack is in `us-east-1`, a "normal" `lambda.Function` can be used instead of an `EdgeFunction`. @@ -588,7 +558,7 @@ To create an empty Key Value Store: const store = new cloudfront.KeyValueStore(this, 'KeyValueStore'); ``` -To also include an initial set of values, the `source` property can be specified, either from a +To also include an initial set of values, the `source` property can be specified, either from a local file or an inline string. For the structure of this file, see [Creating a file of key value pairs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/kvs-with-functions-create-s3-kvp.html). ```ts @@ -1207,5 +1177,5 @@ new cloudfront.KeyGroup(this, 'MyKeyGroup', { See: -- -- +* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html +* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts index 226886a3c3e50..336affec8b862 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts @@ -309,7 +309,6 @@ export class Distribution extends Resource implements IDistribution { private readonly errorResponses: ErrorResponse[]; private readonly certificate?: acm.ICertificate; private readonly publishAdditionalMetrics?: boolean; - private webAclId?: string; constructor(scope: Construct, id: string, props: DistributionProps) { super(scope, id); @@ -336,7 +335,6 @@ export class Distribution extends Resource implements IDistribution { this.certificate = props.certificate; this.errorResponses = props.errorResponses ?? []; this.publishAdditionalMetrics = props.publishAdditionalMetrics; - this.webAclId = props.webAclId; // Comments have an undocumented limit of 128 characters const trimmedComment = @@ -362,7 +360,7 @@ export class Distribution extends Resource implements IDistribution { restrictions: this.renderRestrictions(props.geoRestriction), viewerCertificate: this.certificate ? this.renderViewerCertificate(this.certificate, props.minimumProtocolVersion, props.sslSupportMethod) : undefined, - webAclId: Lazy.string({ produce: () => this.webAclId }), + webAclId: props.webAclId, }, }); @@ -600,18 +598,6 @@ export class Distribution extends Resource implements IDistribution { return this.grant(identity, 'cloudfront:CreateInvalidation'); } - /** - * Attach WAF WebACL to this CloudFront distribution - * - * @param webAclId The WAF WebACL to associate with this distribution - */ - public attachWebAclId(webAclId: string) { - if (this.webAclId) { - throw new Error('A WebACL has already been attached to this distribution'); - } - this.webAclId = webAclId; - } - private addOrigin(origin: IOrigin, isFailoverOrigin: boolean = false): string { const ORIGIN_ID_MAX_LENGTH = 128; diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts index 24a61cd5eff42..abd135a418632 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts @@ -1334,34 +1334,3 @@ describe('Distribution metrics tests', () => { }).toThrow(new RegExp(`${metric.errorMetricName} metric is only available if 'publishAdditionalMetrics' is set 'true'`)); }); }); - -describe('attachWebAclId', () => { - test('can attach WebAcl to the distribution by the method', () => { - const origin = defaultOrigin(); - - const distribution = new Distribution(stack, 'MyDist', { - defaultBehavior: { origin }, - }); - - distribution.attachWebAclId('473e64fd-f30b-4765-81a0-62ad96dd167a'); - - Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', { - DistributionConfig: { - WebACLId: '473e64fd-f30b-4765-81a0-62ad96dd167a', - }, - }); - }); - - test('throws if a WebAcl is already attached to the distribution', () => { - const origin = defaultOrigin(); - - const distribution = new Distribution(stack, 'MyDist', { - defaultBehavior: { origin }, - webAclId: '473e64fd-f30b-4765-81a0-62ad96dd167a', - }); - - expect(() => { - distribution.attachWebAclId('473e64fd-f30b-4765-81a0-62ad96dd167b'); - }).toThrow(/A WebACL has already been attached to this distribution/); - }); -}); diff --git a/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture b/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture index 38de5258fdd15..d8c849ae21977 100644 --- a/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture +++ b/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture @@ -6,7 +6,6 @@ import * as s3 from 'aws-cdk-lib/aws-s3'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import * as lambda from 'aws-cdk-lib/aws-lambda'; -import * as wafv2 from 'aws-cdk-lib/aws-wafv2'; import * as path from 'path'; class Context extends Stack { From a57683d94f6e0b205be31dc8e7600048be13076e Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Mon, 17 Jun 2024 20:53:51 +0900 Subject: [PATCH 3/7] Revert "Revert "feat(cloudfront): add attachWebAclId method for Distribution"" This reverts commit 19b246bb66534fd42aa84ba779bca2faeaee5433. --- ...aws-cdk-cloudfront-with-webacl.assets.json | 19 ++ ...s-cdk-cloudfront-with-webacl.template.json | 83 ++++++++ .../cdk.out | 1 + .../integ.json | 12 ++ ...efaultTestDeployAssert166CAFCF.assets.json | 19 ++ ...aultTestDeployAssert166CAFCF.template.json | 36 ++++ .../manifest.json | 119 ++++++++++++ .../tree.json | 181 ++++++++++++++++++ .../test/integ.cloudfront-with-webacl.ts | 36 ++++ packages/aws-cdk-lib/aws-cloudfront/README.md | 46 ++++- .../aws-cloudfront/lib/distribution.ts | 16 +- .../aws-cloudfront/test/distribution.test.ts | 31 +++ .../rosetta/aws_cloudfront/default.ts-fixture | 1 + 13 files changed, 591 insertions(+), 9 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json new file mode 100644 index 0000000000000..9cbbbfe967006 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186": { + "source": { + "path": "aws-cdk-cloudfront-with-webacl.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json new file mode 100644 index 0000000000000..bfaa179b7fa34 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/aws-cdk-cloudfront-with-webacl.template.json @@ -0,0 +1,83 @@ +{ + "Resources": { + "WebAcl": { + "Type": "AWS::WAFv2::WebACL", + "Properties": { + "DefaultAction": { + "Allow": {} + }, + "Scope": "CLOUDFRONT", + "VisibilityConfig": { + "CloudWatchMetricsEnabled": false, + "MetricName": "webAclMetric", + "SampledRequestsEnabled": false + } + } + }, + "Distribution830FAC52": { + "Type": "AWS::CloudFront::Distribution", + "Properties": { + "DistributionConfig": { + "DefaultCacheBehavior": { + "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", + "Compress": true, + "TargetOriginId": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", + "ViewerProtocolPolicy": "allow-all" + }, + "Enabled": true, + "HttpVersion": "http2", + "IPV6Enabled": true, + "Origins": [ + { + "CustomOriginConfig": { + "OriginProtocolPolicy": "https-only" + }, + "DomainName": "www.example.com", + "Id": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663" + } + ], + "WebACLId": { + "Fn::GetAtt": [ + "WebAcl", + "Arn" + ] + } + } + } + } + }, + "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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json new file mode 100644 index 0000000000000..b94d99be5517f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "integ-cloudfront-with-webacl/DefaultTest": { + "stacks": [ + "aws-cdk-cloudfront-with-webacl" + ], + "assertionStack": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert", + "assertionStackName": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json new file mode 100644 index 0000000000000..51c22564b38bc --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json new file mode 100644 index 0000000000000..5b42d422302a5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/manifest.json @@ -0,0 +1,119 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-cloudfront-with-webacl.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-cloudfront-with-webacl.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-cloudfront-with-webacl": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-cloudfront-with-webacl.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}/376696827a9cd2af7e143b2f3b06e066e69cc46212bced3a6690eebde614b186.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-cloudfront-with-webacl.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-cloudfront-with-webacl.assets" + ], + "metadata": { + "/aws-cdk-cloudfront-with-webacl/WebAcl": [ + { + "type": "aws:cdk:logicalId", + "data": "WebAcl" + } + ], + "/aws-cdk-cloudfront-with-webacl/Distribution/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Distribution830FAC52" + } + ], + "/aws-cdk-cloudfront-with-webacl/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-cloudfront-with-webacl/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-cloudfront-with-webacl" + }, + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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": [ + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.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": [ + "integcloudfrontwithwebaclDefaultTestDeployAssert166CAFCF.assets" + ], + "metadata": { + "/integ-cloudfront-with-webacl/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-cloudfront-with-webacl/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-cloudfront-with-webacl/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-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json new file mode 100644 index 0000000000000..9ce07a8dc2fb2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.js.snapshot/tree.json @@ -0,0 +1,181 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-cloudfront-with-webacl": { + "id": "aws-cdk-cloudfront-with-webacl", + "path": "aws-cdk-cloudfront-with-webacl", + "children": { + "WebAcl": { + "id": "WebAcl", + "path": "aws-cdk-cloudfront-with-webacl/WebAcl", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::WAFv2::WebACL", + "aws:cdk:cloudformation:props": { + "defaultAction": { + "allow": {} + }, + "scope": "CLOUDFRONT", + "visibilityConfig": { + "cloudWatchMetricsEnabled": false, + "metricName": "webAclMetric", + "sampledRequestsEnabled": false + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Distribution": { + "id": "Distribution", + "path": "aws-cdk-cloudfront-with-webacl/Distribution", + "children": { + "Origin1": { + "id": "Origin1", + "path": "aws-cdk-cloudfront-with-webacl/Distribution/Origin1", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-cloudfront-with-webacl/Distribution/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::CloudFront::Distribution", + "aws:cdk:cloudformation:props": { + "distributionConfig": { + "enabled": true, + "origins": [ + { + "domainName": "www.example.com", + "id": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", + "customOriginConfig": { + "originProtocolPolicy": "https-only" + } + } + ], + "defaultCacheBehavior": { + "pathPattern": "*", + "targetOriginId": "awscdkcloudfrontwithwebaclDistributionOrigin11CAC3663", + "cachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6", + "compress": true, + "viewerProtocolPolicy": "allow-all" + }, + "httpVersion": "http2", + "ipv6Enabled": true, + "webAclId": { + "Fn::GetAtt": [ + "WebAcl", + "Arn" + ] + } + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-cloudfront-with-webacl/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-cloudfront-with-webacl/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "integ-cloudfront-with-webacl": { + "id": "integ-cloudfront-with-webacl", + "path": "integ-cloudfront-with-webacl", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-cloudfront-with-webacl/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-cloudfront-with-webacl/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-cloudfront-with-webacl/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.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": "constructs.Construct", + "version": "10.3.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts new file mode 100644 index 0000000000000..a862e751c566d --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts @@ -0,0 +1,36 @@ + +import * as cdk from 'aws-cdk-lib'; +import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { TestOrigin } from './test-origin'; +import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-cloudfront-with-webacl', { + env: { + region: 'us-east-1', + }, +}); + +const webAcl = new CfnWebACL(stack, 'WebAcl', { + defaultAction: { + allow: {}, + }, + scope: 'CLOUDFRONT', + visibilityConfig: { + cloudWatchMetricsEnabled: false, + metricName: 'webAclMetric', + sampledRequestsEnabled: false, + }, +}); + +const distribution = new cloudfront.Distribution(stack, 'Distribution', { + defaultBehavior: { origin: new TestOrigin('www.example.com') }, +}); + +distribution.attachWebAclId(webAcl.attrArn); + +new IntegTest(app, 'integ-cloudfront-with-webacl', { + testCases: [stack], +}); diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index 965e3cbac7f69..ffcd70ca0a6be 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -1,6 +1,5 @@ # Amazon CloudFront Construct Library - Amazon CloudFront is a web service that speeds up distribution of your static and dynamic web content, such as .html, .css, .js, and image files, to your users. CloudFront delivers your content through a worldwide network of data centers called edge locations. When a user requests content that you're serving with CloudFront, the user is routed to the edge location that provides the lowest latency, so that content is delivered with the best @@ -211,13 +210,44 @@ new cloudfront.Distribution(this, 'myDist', { }); ``` +### Attaching WAF Web Acls + +You can attach the AWS WAF web ACL to a CloudFront distribution. + +To specify a web ACL created using the latest version of AWS WAF, use the ACL ARN, for example +`arn:aws:wafv2:us-east-1:123456789012:global/webacl/ExampleWebACL/473e64fd-f30b-4765-81a0-62ad96dd167a`. +The web ACL must be in the `us-east-1` region. + +To specify a web ACL created using AWS WAF Classic, use the ACL ID, for example `473e64fd-f30b-4765-81a0-62ad96dd167a`. + +```ts +declare const bucketOrigin: origins.S3Origin; +declare const webAcl: wafv2.CfnWebACL; +const distribution = new cloudfront.Distribution(stack, 'Distribution', { + defaultBehavior: { origin: bucketOrigin }, + webAclId: webAcl.attrArn, +}); +``` + +You can also attach a web ACL to a distribution after creation. + +```ts +declare const bucketOrigin: origins.S3Origin; +declare const webAcl: wafv2.CfnWebACL; +const distribution = new cloudfront.Distribution(stack, 'Distribution', { + defaultBehavior: { origin: bucketOrigin }, +}); + +distribution.attachWebAclId(webAcl.attrArn); +``` + ### Customizing Cache Keys and TTLs with Cache Policies You can use a cache policy to improve your cache hit ratio by controlling the values (URL query strings, HTTP headers, and cookies) that are included in the cache key, and/or adjusting how long items remain in the cache via the time-to-live (TTL) settings. CloudFront provides some predefined cache policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own cache policy that’s specific to your needs. -See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html for more details. +See for more details. ```ts // Using an existing cache policy for a Distribution @@ -260,7 +290,7 @@ Other information from the viewer request, such as URL query strings, HTTP heade You can use an origin request policy to control the information that’s included in an origin request. CloudFront provides some predefined origin request policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own origin request policy that’s specific to your needs. -See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.html for more details. +See for more details. ```ts // Using an existing origin request policy for a Distribution @@ -296,7 +326,7 @@ new cloudfront.Distribution(this, 'myDistCustomPolicy', { You can configure CloudFront to add one or more HTTP headers to the responses that it sends to viewers (web browsers or other clients), without making any changes to the origin or writing any code. To specify the headers that CloudFront adds to HTTP responses, you use a response headers policy. CloudFront adds the headers regardless of whether it serves the object from the cache or has to retrieve the object from the origin. If the origin response includes one or more of the headers that’s in a response headers policy, the policy can specify whether CloudFront uses the header it received from the origin or overwrites it with the one in the policy. -See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-response-headers.html +See ```ts // Using an existing managed response headers policy @@ -418,7 +448,7 @@ new cloudfront.Distribution(this, 'myDist', { > The `EdgeFunction` construct will automatically request a function in `us-east-1`, regardless of the region of the current stack. > `EdgeFunction` has the same interface as `Function` and can be created and used interchangeably. > Please note that using `EdgeFunction` requires that the `us-east-1` region has been bootstrapped. -> See https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html for more about bootstrapping regions. +> See for more about bootstrapping regions. If the stack is in `us-east-1`, a "normal" `lambda.Function` can be used instead of an `EdgeFunction`. @@ -558,7 +588,7 @@ To create an empty Key Value Store: const store = new cloudfront.KeyValueStore(this, 'KeyValueStore'); ``` -To also include an initial set of values, the `source` property can be specified, either from a +To also include an initial set of values, the `source` property can be specified, either from a local file or an inline string. For the structure of this file, see [Creating a file of key value pairs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/kvs-with-functions-create-s3-kvp.html). ```ts @@ -1177,5 +1207,5 @@ new cloudfront.KeyGroup(this, 'MyKeyGroup', { See: -* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html -* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html +- +- diff --git a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts index 336affec8b862..226886a3c3e50 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/lib/distribution.ts @@ -309,6 +309,7 @@ export class Distribution extends Resource implements IDistribution { private readonly errorResponses: ErrorResponse[]; private readonly certificate?: acm.ICertificate; private readonly publishAdditionalMetrics?: boolean; + private webAclId?: string; constructor(scope: Construct, id: string, props: DistributionProps) { super(scope, id); @@ -335,6 +336,7 @@ export class Distribution extends Resource implements IDistribution { this.certificate = props.certificate; this.errorResponses = props.errorResponses ?? []; this.publishAdditionalMetrics = props.publishAdditionalMetrics; + this.webAclId = props.webAclId; // Comments have an undocumented limit of 128 characters const trimmedComment = @@ -360,7 +362,7 @@ export class Distribution extends Resource implements IDistribution { restrictions: this.renderRestrictions(props.geoRestriction), viewerCertificate: this.certificate ? this.renderViewerCertificate(this.certificate, props.minimumProtocolVersion, props.sslSupportMethod) : undefined, - webAclId: props.webAclId, + webAclId: Lazy.string({ produce: () => this.webAclId }), }, }); @@ -598,6 +600,18 @@ export class Distribution extends Resource implements IDistribution { return this.grant(identity, 'cloudfront:CreateInvalidation'); } + /** + * Attach WAF WebACL to this CloudFront distribution + * + * @param webAclId The WAF WebACL to associate with this distribution + */ + public attachWebAclId(webAclId: string) { + if (this.webAclId) { + throw new Error('A WebACL has already been attached to this distribution'); + } + this.webAclId = webAclId; + } + private addOrigin(origin: IOrigin, isFailoverOrigin: boolean = false): string { const ORIGIN_ID_MAX_LENGTH = 128; diff --git a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts index abd135a418632..24a61cd5eff42 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront/test/distribution.test.ts @@ -1334,3 +1334,34 @@ describe('Distribution metrics tests', () => { }).toThrow(new RegExp(`${metric.errorMetricName} metric is only available if 'publishAdditionalMetrics' is set 'true'`)); }); }); + +describe('attachWebAclId', () => { + test('can attach WebAcl to the distribution by the method', () => { + const origin = defaultOrigin(); + + const distribution = new Distribution(stack, 'MyDist', { + defaultBehavior: { origin }, + }); + + distribution.attachWebAclId('473e64fd-f30b-4765-81a0-62ad96dd167a'); + + Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', { + DistributionConfig: { + WebACLId: '473e64fd-f30b-4765-81a0-62ad96dd167a', + }, + }); + }); + + test('throws if a WebAcl is already attached to the distribution', () => { + const origin = defaultOrigin(); + + const distribution = new Distribution(stack, 'MyDist', { + defaultBehavior: { origin }, + webAclId: '473e64fd-f30b-4765-81a0-62ad96dd167a', + }); + + expect(() => { + distribution.attachWebAclId('473e64fd-f30b-4765-81a0-62ad96dd167b'); + }).toThrow(/A WebACL has already been attached to this distribution/); + }); +}); diff --git a/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture b/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture index d8c849ae21977..38de5258fdd15 100644 --- a/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture +++ b/packages/aws-cdk-lib/rosetta/aws_cloudfront/default.ts-fixture @@ -6,6 +6,7 @@ import * as s3 from 'aws-cdk-lib/aws-s3'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as wafv2 from 'aws-cdk-lib/aws-wafv2'; import * as path from 'path'; class Context extends Stack { From c9ff0fdeea161781ba45f6710af367a44b901b5f Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Mon, 17 Jun 2024 21:25:24 +0900 Subject: [PATCH 4/7] fix README for rosetta --- packages/aws-cdk-lib/aws-cloudfront/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index ffcd70ca0a6be..f3d0386124603 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -223,7 +223,7 @@ To specify a web ACL created using AWS WAF Classic, use the ACL ID, for example ```ts declare const bucketOrigin: origins.S3Origin; declare const webAcl: wafv2.CfnWebACL; -const distribution = new cloudfront.Distribution(stack, 'Distribution', { +const distribution = new cloudfront.Distribution(this, 'Distribution', { defaultBehavior: { origin: bucketOrigin }, webAclId: webAcl.attrArn, }); @@ -234,7 +234,7 @@ You can also attach a web ACL to a distribution after creation. ```ts declare const bucketOrigin: origins.S3Origin; declare const webAcl: wafv2.CfnWebACL; -const distribution = new cloudfront.Distribution(stack, 'Distribution', { +const distribution = new cloudfront.Distribution(this, 'Distribution', { defaultBehavior: { origin: bucketOrigin }, }); From c8750c4dacd184178dc58807a2bd2ee9c7df639d Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Mon, 17 Jun 2024 21:36:09 +0900 Subject: [PATCH 5/7] formatter off --- packages/aws-cdk-lib/aws-cloudfront/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index f3d0386124603..0ed4083683743 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -247,7 +247,7 @@ You can use a cache policy to improve your cache hit ratio by controlling the va that are included in the cache key, and/or adjusting how long items remain in the cache via the time-to-live (TTL) settings. CloudFront provides some predefined cache policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own cache policy that’s specific to your needs. -See for more details. +See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html for more details. ```ts // Using an existing cache policy for a Distribution @@ -290,7 +290,7 @@ Other information from the viewer request, such as URL query strings, HTTP heade You can use an origin request policy to control the information that’s included in an origin request. CloudFront provides some predefined origin request policies, known as managed policies, for common use cases. You can use these managed policies, or you can create your own origin request policy that’s specific to your needs. -See for more details. +See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.html for more details. ```ts // Using an existing origin request policy for a Distribution @@ -326,7 +326,7 @@ new cloudfront.Distribution(this, 'myDistCustomPolicy', { You can configure CloudFront to add one or more HTTP headers to the responses that it sends to viewers (web browsers or other clients), without making any changes to the origin or writing any code. To specify the headers that CloudFront adds to HTTP responses, you use a response headers policy. CloudFront adds the headers regardless of whether it serves the object from the cache or has to retrieve the object from the origin. If the origin response includes one or more of the headers that’s in a response headers policy, the policy can specify whether CloudFront uses the header it received from the origin or overwrites it with the one in the policy. -See +See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-response-headers.html ```ts // Using an existing managed response headers policy @@ -448,7 +448,7 @@ new cloudfront.Distribution(this, 'myDist', { > The `EdgeFunction` construct will automatically request a function in `us-east-1`, regardless of the region of the current stack. > `EdgeFunction` has the same interface as `Function` and can be created and used interchangeably. > Please note that using `EdgeFunction` requires that the `us-east-1` region has been bootstrapped. -> See for more about bootstrapping regions. +> See https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html for more about bootstrapping regions. If the stack is in `us-east-1`, a "normal" `lambda.Function` can be used instead of an `EdgeFunction`. @@ -1207,5 +1207,5 @@ new cloudfront.KeyGroup(this, 'MyKeyGroup', { See: -- -- +* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html +* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html From 43b40a2678b2444570171762637643457f0de095 Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Mon, 17 Jun 2024 21:36:48 +0900 Subject: [PATCH 6/7] style for an integ test style for README Revert "style for README" This reverts commit 7cb05fac02eed4b1910d2bafa0c77ee5fc5aa3fa. --- .../test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts index a862e751c566d..b2bdff67feca9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudfront/test/integ.cloudfront-with-webacl.ts @@ -1,4 +1,3 @@ - import * as cdk from 'aws-cdk-lib'; import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'; import { IntegTest } from '@aws-cdk/integ-tests-alpha'; From 25cd65520c5461d9b6affd14e70eabc2c6f5931e Mon Sep 17 00:00:00 2001 From: go-to-k <24818752+go-to-k@users.noreply.github.com> Date: Mon, 17 Jun 2024 22:19:57 +0900 Subject: [PATCH 7/7] style for README --- packages/aws-cdk-lib/aws-cloudfront/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk-lib/aws-cloudfront/README.md b/packages/aws-cdk-lib/aws-cloudfront/README.md index 0ed4083683743..9bdd344ac47f8 100644 --- a/packages/aws-cdk-lib/aws-cloudfront/README.md +++ b/packages/aws-cdk-lib/aws-cloudfront/README.md @@ -1207,5 +1207,5 @@ new cloudfront.KeyGroup(this, 'MyKeyGroup', { See: -* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html -* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html +- https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html +- https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html