01 Define the AWS WAFv2 rule for the web ACL. An AWS WAFv2 rule is a configurable condition that inspects incoming web requests and defines an action to take (allow, block, or count) if the request meets that condition. Save the rule definition to a JSON file named wafv2-custom-rule.json. As an example, the following rule allows country-specific web traffic to protect applications from attacks (geo-based rule):
[
{
"Name":"cc-geo-based-access-rule",
"Priority":0,
"Statement": {
"GeoMatchStatement": {
"CountryCodes": [
"AU",
"US"
]
}
},
"Action":{
"Allow":{
}
},
"VisibilityConfig":{
"SampledRequestsEnabled":true,
"CloudWatchMetricsEnabled":true,
"MetricName":"cc-geo-based-rule-metric"
}
}
]
02 Run wafv2 create-web-acl command (OSX/Linux/UNIX) to create the AWS WAFv2 web ACL that will be attached later to the Cloudfront distribution used as CDN solution for your web application. The web ACL will keep your web application secure from the most common web threats and security vulnerabilities:
aws wafv2 create-web-acl
--name cc-cloudfront-web-acl
--description "Allow country-specific web traffic to protect application from attacks"
--scope CLOUDFRONT
--region=us-east-1
--default-action Allow={}
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName="cc-geo-based-rule-metric"
--rules file://wafv2-custom-rule.json
--query 'Summary.ARN'
03 The command output should return the ARN of the new WAFv2 web ACL:
"arn:aws:wafv2:us-east-1:123456789012:global/webacl/cc-cloudfront-web-acl1/0abcd123-abcd-1234-abcd-1234abcd1234"
04 Now that the AWS WAFv2 web ACL is ready for use, take the required steps to associate it with your Amazon Cloudfront distribution. Run get-distribution-config command (OSX/Linux/UNIX) to collect the configuration information from the CDN distribution that you want to protect with AWS WAFv2. The following command returns the configuration object of a web distribution identified by the ID "ABCABCABCABCAB":
aws cloudfront get-distribution-config
--id ABCABCABCABCAB
05 The command output should return the selected distribution configuration information:
{
"ETag": "123ABC123ABCD",
"DistributionConfig": {
"CallerReference": "abcd1234-abcd-1234-abcd-1234abcd1234",
"Aliases": {
"Quantity": 0
},
"DefaultRootObject": "",
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "trendmicro-website.s3.us-east-1.amazonaws.com-1234abcd1234",
"DomainName": "trendmicro-website.s3.us-east-1.amazonaws.com",
"OriginPath": "",
"CustomHeaders": {
"Quantity": 0
},
"S3OriginConfig": {
"OriginAccessIdentity": "",
"OriginReadTimeout": 30
},
"ConnectionAttempts": 3,
"ConnectionTimeout": 10,
"OriginShield": {
"Enabled": false
},
"OriginAccessControlId": "ABCABCABCABCAB"
}
]
},
"OriginGroups": {
"Quantity": 0
},
"DefaultCacheBehavior": {
"TargetOriginId": "trendmicro-website.s3.us-east-1.amazonaws.com-1234abcd1234",
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"TrustedKeyGroups": {
"Enabled": false,
"Quantity": 0
},
"ViewerProtocolPolicy": "redirect-to-https",
"AllowedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
],
"CachedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
]
}
},
"SmoothStreaming": false,
"Compress": true,
"LambdaFunctionAssociations": {
"Quantity": 0
},
"FunctionAssociations": {
"Quantity": 0
},
"FieldLevelEncryptionId": "",
"CachePolicyId": "abcd1234-abcd-1234-abcd-1234abcd1234",
"GrpcConfig": {
"Enabled": false
}
},
"CacheBehaviors": {
"Quantity": 0
},
"CustomErrorResponses": {
"Quantity": 0
},
"Comment": "",
"Logging": {
"Enabled": false,
"IncludeCookies": false,
"Bucket": "",
"Prefix": ""
},
"PriceClass": "PriceClass_All",
"Enabled": true,
"ViewerCertificate": {
"CloudFrontDefaultCertificate": true,
"SSLSupportMethod": "vip",
"MinimumProtocolVersion": "TLSv1",
"CertificateSource": "cloudfront"
},
"Restrictions": {
"GeoRestriction": {
"RestrictionType": "none",
"Quantity": 0
}
},
"WebACLId": "",
"HttpVersion": "http2",
"IsIPV6Enabled": true,
"ContinuousDeploymentPolicyId": "",
"Staging": false
}
}
06 Modify the distribution configuration returned in the previous step to attach the WAFv2 web ACL created earlier in the Remediation process by setting the web ACL ARN as value for the "WebACLId" attribute, as shown in the example below. Once the "WebACLId" attribute is configured, remove the "ETag" flag and save the new distribution configuration to a JSON document named cloudfront-wafv2-integration.json:
{
"CallerReference": "abcd1234-abcd-1234-abcd-1234abcd1234",
"Aliases": {
"Quantity": 0
},
"DefaultRootObject": "",
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "trendmicro-website.s3.us-east-1.amazonaws.com-1234abcd1234",
"DomainName": "trendmicro-website.s3.us-east-1.amazonaws.com",
"OriginPath": "",
"CustomHeaders": {
"Quantity": 0
},
"S3OriginConfig": {
"OriginAccessIdentity": "",
"OriginReadTimeout": 30
},
"ConnectionAttempts": 3,
"ConnectionTimeout": 10,
"OriginShield": {
"Enabled": false
},
"OriginAccessControlId": "ABCABCABCABCAB"
}
]
},
"OriginGroups": {
"Quantity": 0
},
"DefaultCacheBehavior": {
"TargetOriginId": "trendmicro-website.s3.us-east-1.amazonaws.com-1234abcd1234",
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"TrustedKeyGroups": {
"Enabled": false,
"Quantity": 0
},
"ViewerProtocolPolicy": "redirect-to-https",
"AllowedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
],
"CachedMethods": {
"Quantity": 2,
"Items": [
"HEAD",
"GET"
]
}
},
"SmoothStreaming": false,
"Compress": true,
"LambdaFunctionAssociations": {
"Quantity": 0
},
"FunctionAssociations": {
"Quantity": 0
},
"FieldLevelEncryptionId": "",
"CachePolicyId": "abcd1234-abcd-1234-abcd-1234abcd1234",
"GrpcConfig": {
"Enabled": false
}
},
"CacheBehaviors": {
"Quantity": 0
},
"CustomErrorResponses": {
"Quantity": 0
},
"Comment": "",
"Logging": {
"Enabled": false,
"IncludeCookies": false,
"Bucket": "",
"Prefix": ""
},
"PriceClass": "PriceClass_All",
"Enabled": true,
"ViewerCertificate": {
"CloudFrontDefaultCertificate": true,
"SSLSupportMethod": "vip",
"MinimumProtocolVersion": "TLSv1",
"CertificateSource": "cloudfront"
},
"Restrictions": {
"GeoRestriction": {
"RestrictionType": "none",
"Quantity": 0
}
},
"WebACLId": "arn:aws:wafv2:us-east-1:123456789012:global/webacl/cc-cloudfront-web-acl1/0abcd123-abcd-1234-abcd-1234abcd1234",
"HttpVersion": "http2",
"IsIPV6Enabled": true,
"ContinuousDeploymentPolicyId": "",
"Staging": false
}
07 Run cloudfront update-distribution command (OSX/Linux/UNIX) to update your Amazon Cloudfront distribution in order to integrate it with the AWS WAFv2 service. The following command example updates a CloudFront distribution with the ID "ABCABCABCABCAB" and ETag "123ABC123ABCD" (an ETag is a header ID exposed when a CDN distribution configuration is retrieved), using the distribution configuration modified in the previous step (i.e., cloudfront-wafv2-integration.json):
aws cloudfront update-distribution
--id ABCABCABCABCAB
--distribution-config file://cloudfront-wafv2-integration.json
--if-match 123ABC123ABCD
--query 'Distribution.Status'
08 The command output should return the current status of the modified Cloudfront distribution: