Use the Conformity Knowledge Base AI to help improve your Cloud Posture

CloudFront Integrated With WAF

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: Medium (should be achieved)
Rule ID: CF-004

Ensure that all your Amazon CloudFront distributions are integrated with the Amazon Web Application Firewall (WAF) service to protect against application-layer attacks that can compromise the security of your websites/web applications or place unnecessary load on them.

This rule can help you with the following compliance standards:

  • PCI
  • NIST4

For further details on compliance standards supported by Conformity, see here.

This rule can help you work with the AWS Well-Architected Framework.

This rule resolution is part of the Conformity Security & Compliance tool for AWS.

Security

With CloudFront – WAF integration enabled you will be able to block any malicious requests made to your Content Delivery Network (CDN) based on the criteria defined in the web Access Control List (web ACL) associated with the CDN distribution.


Audit

To determine if your CloudFront distributions are integrated with Amazon WAF, perform the following operations:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon CloudFront console at https://console.aws.amazon.com/cloudfront/v3/.

03 In the left navigation panel, under CloudFront, choose Distributions.

04 Click on the name (link) of the CloudFront distribution that you want to examine.

05 Select the General tab to access the general configuration settings available for the selected distribution.

06 In the Settings section, check the AWS WAF web ACL – optional configuration setting to determine if the selected distribution is currently associated with a web ACL. A web access control list (web ACL) gives you fine-grained control over all of the HTTP(S) web requests that your protected resource responds to. If there is no web ACL configured for the AWS WAF web ACL – optional setting, the selected Amazon CloudFront distribution is not associated with a web ACL, therefore the CloudFront distribution is not integrated with Amazon WAF for protection against malicious requests.

07 Repeat steps no. 4 – 6 for each CloudFront distribution available within your AWS cloud account.

Using AWS CLI

01 Run list-distributions command (OSX/Linux/UNIX) with custom query filters to list the ID of each Amazon CloudFront distribution created in your AWS account:

aws cloudfront list-distributions
  --output table
  --query 'DistributionList.Items[*].Id'

02 The command output should return a table with the requested distribution ID(s):

--------------------
|ListDistributions |
+------------------+
|  ABCDABCDABCDAB  |
|  AABBCCDDAABBCC  |
|  AAAABBBBCCCCDD  |
+------------------+

03 Run get-distribution command (OSX/Linux/UNIX) using the ID of the Amazon CloudFront distribution that you want to examine as the identifier parameter and custom filtering to describe the name of the web ACL associated with the selected distribution:

aws cloudfront get-distribution
  --id ABCDABCDABCDAB
  --query 'Distribution.DistributionConfig.WebACLId'

04 The command output should return the requested configuration information:

""

If the get-distribution command output returns an empty string (i.e. ""), there is no web ACL associated with the selected Amazon CloudFront distribution, therefore the CloudFront distribution is not integrated with Amazon WAF for protection against malicious requests.

05 Repeat steps no. 3 and 4 for each CloudFront distribution deployed in your AWS cloud account.

Remediation / Resolution

To integrate CloudFront with Amazon WAF you must create and configure a web ACL and associate it with your CloudFront distributions. To implement CloudFront – WAF integration, perform the following operations:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Resources": {
		"WAFWebACL": {
			"Type": "AWS::WAFv2::WebACL",
			"Properties": {
				"Name": "cc-cloudfront-web-acl",
				"Scope": "CLOUDFRONT",
				"DefaultAction": {
					"Block": {}
				},
				"Rules": [
					{
						"Name": "AWS-AWSManagedRulesBotControlRuleSet",
						"Priority": 0,
						"OverrideAction": {
							"None": {}
						},
						"Statement": {
							"ManagedRuleGroupStatement": {
								"VendorName": "AWS",
								"Name": "AWSManagedRulesBotControlRuleSet",
								"ExcludedRules": []
							}
						},
						"VisibilityConfig": {
							"SampledRequestsEnabled": true,
							"CloudWatchMetricsEnabled": true,
							"MetricName": "AWS-AWSManagedRulesBotControlRuleSet"
						}
					}
				]
			}
		},
		"CloudFrontDistribution": {
			"Type": "AWS::CloudFront::Distribution",
			"Properties": {
				"DistributionConfig": {
					"Enabled": true,
					"Comment": "CloudFront CDN Web Distribution",
					"Origins": [
						{
							"Id": "cc-cdn-origin",
							"DomainName": "domain.com"
						}
					],
					"DefaultRootObject": "index.html",
					"DefaultCacheBehavior": {
						"AllowedMethods": [
							"HEAD",
							"GET"
						],
						"Compress": true,
						"DefaultTTL": 0,
						"ForwardedValues": {
							"Cookies": {
								"Forward": "none"
							},
							"QueryString": false
						},
						"ViewerProtocolPolicy": "redirect-to-https"
					},
					"HttpVersion": "http2",
					"ViewerCertificate": {
						"CloudFrontDefaultCertificate": true
					},
					"PriceClass": "PriceClass_All",
					"WebACLId": {
						"Fn::GetAtt": [
							"WAFWebACL",
							"Arn"
						]
					}
				}
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Resources:
	WAFWebACL:
		Type: AWS::WAFv2::WebACL
		Properties:
		Name: cc-cloudfront-web-acl
		Scope: CLOUDFRONT
		DefaultAction:
			Block: {}
		Rules:
			- Name: AWS-AWSManagedRulesBotControlRuleSet
			Priority: 0
			OverrideAction:
				None: {}
			Statement:
				ManagedRuleGroupStatement:
				VendorName: AWS
				Name: AWSManagedRulesBotControlRuleSet
				ExcludedRules: []
			VisibilityConfig:
				SampledRequestsEnabled: true
				CloudWatchMetricsEnabled: true
				MetricName: AWS-AWSManagedRulesBotControlRuleSet
	CloudFrontDistribution:
		Type: AWS::CloudFront::Distribution
		Properties:
		DistributionConfig:
			Enabled: true
			Comment: CloudFront CDN Web Distribution
			Origins:
			- Id: cc-cdn-origin
				DomainName: domain.com
			DefaultRootObject: index.html
			DefaultCacheBehavior:
			AllowedMethods:
				- HEAD
				- GET
			Compress: true
			DefaultTTL: 0
			ForwardedValues:
				Cookies:
				Forward: none
				QueryString: false
			ViewerProtocolPolicy: redirect-to-https
			HttpVersion: http2
			ViewerCertificate:
			CloudFrontDefaultCertificate: true
			PriceClass: PriceClass_All
			WebACLId: !GetAtt 'WAFWebACL.Arn'

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

terraform {
	required_providers {
		aws = {
			source  = "hashicorp/aws"
			version = "~> 4.0"
		}
	}

	required_version = ">= 0.14.9"
}

provider "aws" {
	profile = "default"
	region  = "us-east-1"
}

resource "aws_wafv2_web_acl" "wafv2-web-acl" {
	name  = "cc-cloudfront-web-acl"
	scope = "CLOUDFRONT"
	default_action {
		block {}
	}
	rule {
		name     = "AWS-AWSManagedRulesBotControlRuleSet"
		priority = 0
		override_action {
			none {}
		}
		statement {
			managed_rule_group_statement {
				vendor_name = "AWS"
				name        = "AWSManagedRulesBotControlRuleSet"
			}
		}
		visibility_config {
			cloudwatch_metrics_enabled = true
			sampled_requests_enabled   = true
			metric_name                = "AWS-AWSManagedRulesBotControlRuleSet"
		}
	}
}

resource "aws_cloudfront_distribution" "cloudfront-distribution" {

	enabled             = true
	default_root_object = "index.html"
	comment             = "CloudFront CDN Web Distribution"

	origin {
		domain_name = "domain.com"
		origin_id   = "cc-cdn-origin"
	}

	default_cache_behavior {
		target_origin_id = "cc-domain-origin"
		allowed_methods  = ["GET", "HEAD"]
		cached_methods   = ["GET", "HEAD"]
		forwarded_values {
			query_string = false
			cookies {
				forward = "none"
			}
		}
		min_ttl                = 0
		default_ttl            = 3600
		max_ttl                = 86400
		compress               = true
		viewer_protocol_policy = "redirect-to-https"
	}

	viewer_certificate {
		cloudfront_default_certificate = true
	}

	price_class = "PriceClass_All"
	web_acl_id  = aws_wafv2_web_acl.wafv2-web-acl.arn

}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon WAF & Shield console at https://console.aws.amazon.com/wafv2/.

03 In the left navigation panel, under AWS WAF, choose Web ACLs.

04 Choose Create web ACL to initiate the web ACL setup process.

05 On the Create web ACL page, perform the following actions:

  1. For Step 1 Describe web ACL and associate it to AWS resources, perform the following:
    • Enter a unique name for the new web ACL in the Name box.
    • (Optional) Provide a short description for the new resource in the Description – optionalbox.
    • Enter a unique name for the new CloudWatch metric in the CloudWatch metric namebox.
    • For Resource type, select CloudFront distributions as the type of the AWS resource that you want to associate with this web ACL.
    • In the Associated AWS resources – optional section, choose Add AWS resources, and select the Amazon CloudFront distribution(s) that you want to associate with the new web ACL. Choose Add to apply the selected distribution(s).
    • Choose Next to continue the setup process.
  2. For Step 2 Add rules and rule groups, perform the following:
    • In the Rules section, choose Add rules to add managed or customer rules. Choose Add managed rule groups and select the rule group that you want to implement for your new web ACL or select Add my own rules and rule groups to define your own rules/rule groups.
    • Once the necessary rules/rule groups are added to your web ACL, choose the default web ACL action for requests that don't match the rules added at the previous step. Choose Deny or Allow under Default action to either block or allow through those requests that pass the rules inspections.
    • (Optional) For Custom request/Custom response, you can configure a custom request or response based on the default action selected at the previous step.
    • Choose Next to continue.

06 For Step 3 Set rule priority, configure the rules/rule groups priority based on your requirements. Amazon WAF evaluates the rules and rule groups in the order shown, starting from the top. Use the Move up/Move down controls to move the rules up or down in order to change the evaluation order. Choose Next to continue.

07 For Step 4 Configure metrics, choose the rules and/or rule groups that you want to deliver metrics to Amazon CloudWatch. For Request sampling options, select Enable sampled requests to enable the feature. Choose Next to continue.

08 For Step 5 Review and create web ACL, review the web ACL configuration, and choose Create web ACL to create your new Amazon WAF web ACL. The new web ACL will be automatically associated with the selected Amazon CloudFront distribution(s).

09 Repeat steps no. 4 and 5 to create new web ACLs for your Amazon CloudFront distributions.

Using AWS CLI

01 Define the rules/rules group for the new web ACL. You can use managed rules/rule groups or you can define your own rules/rule groups. As an example, the following JSON document represents the definition of a managed rule group named AWSManagedRulesBotControlRuleSet. The AWSManagedRulesBotControlRuleSet rule group defines protection against automated bots that can consume excess resources, skew business metrics, cause downtime, or perform malicious activities. The managed rule group provides additional visibility through Amazon CloudWatch and generates labels that you can use to control bot traffic to your applications. Save the following rule group definition to a JSON named rule-definition.json:

[
	{
		"Name": "AWS-AWSManagedRulesBotControlRuleSet",
		"Priority": 0,
		"Statement": {
			"ManagedRuleGroupStatement": {
				"VendorName": "AWS",
				"Name": "AWSManagedRulesBotControlRuleSet"
			}
		},
		"OverrideAction": {
			"None": {}
		},
		"VisibilityConfig": {
			"SampledRequestsEnabled": false,
			"CloudWatchMetricsEnabled": false,
			"MetricName": "AWS-AWSManagedRulesBotControlRuleSet"
		}
	}
]

02 Run create-web-acl command (OSX/Linux/UNIX) to create a new Amazon WAF web ACL for your Amazon CloudFront distribution(s) using the rule group definition listed at the previous step (rule-definition.json):

aws wafv2 create-web-acl
  --name cc-cdn-bot-protection
  --scope CLOUDFRONT
  --default-action Block={}
  --visibility-config "SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=CdnProtectionWebAclMetric"
  --rules file://rule-definition.json
  --query 'Summary.Id'

03 The command output should return the identifier (ID) of the new web ACL:

"abcd1234-abcd-1234-abcd-1234abcd1234"

04 Run get-distribution-config command (OSX/Linux/UNIX) to extract all the configuration information from the Amazon CloudFront distribution that you want to reconfigure:

aws cloudfront get-distribution-config
  --id ABCDABCDABCDAB
  --query 'DistributionConfig'

05 The command output should return the requested configuration information:

{
	"CallerReference": "abcd1234-abcd-1234-abcd-1234abcd1234",
	"Aliases": {
		"Quantity": 0
	},
	"DefaultRootObject": "",
	"Origins": {
		"Quantity": 1,
		"Items": [
			{
				"Id": "cloudconformity.com",
				"DomainName": "cloudconformity.com",
				"OriginPath": "",
				"CustomHeaders": {
					"Quantity": 0
				},
				"CustomOriginConfig": {
					"HTTPPort": 80,
					"HTTPSPort": 443,
					"OriginProtocolPolicy": "http-only",
					"OriginSslProtocols": {
						"Quantity": 2,
						"Items": [
							"TLSv1.1",
							"TLSv1.2"
						]
					},
					"OriginReadTimeout": 30,
					"OriginKeepaliveTimeout": 5
				},
				"ConnectionAttempts": 3,
				"ConnectionTimeout": 10,
				"OriginShield": {
					"Enabled": false
				}
			}
		]
	},
	"OriginGroups": {
		"Quantity": 0
	},
	"DefaultCacheBehavior": {
		"TargetOriginId": "cloudconformity.com",
		"TrustedSigners": {
			"Enabled": false,
			"Quantity": 0
		},
		"TrustedKeyGroups": {
			"Enabled": false,
			"Quantity": 0
		},
		"ViewerProtocolPolicy": "allow-all",
		"AllowedMethods": {
			"Quantity": 2,
			"Items": [
				"HEAD",
				"GET"
			],
			"CachedMethods": {
				"Quantity": 2,
				"Items": [
					"HEAD",
					"GET"
				]
			}
		},
		"SmoothStreaming": false,
		"Compress": true,
		"LambdaFunctionAssociations": {
			"Quantity": 0
		},
		"FunctionAssociations": {
			"Quantity": 0
		},
		"FieldLevelEncryptionId": "",
		"ForwardedValues": {
			"QueryString": false,
			"Cookies": {
				"Forward": "none"
			},
			"Headers": {
				"Quantity": 0
			},
			"QueryStringCacheKeys": {
				"Quantity": 0
			}
		},
		"MinTTL": 0,
		"DefaultTTL": 86400,
		"MaxTTL": 31536000
	},
	"CacheBehaviors": {
		"Quantity": 1,
		"Items": [
			{
				"PathPattern": "/images",
				"TargetOriginId": "cloudconformity.com",
				"TrustedSigners": {
					"Enabled": false,
					"Quantity": 0
				},
				"TrustedKeyGroups": {
					"Enabled": false,
					"Quantity": 0
				},
				"ViewerProtocolPolicy": "allow-all",
				"AllowedMethods": {
					"Quantity": 2,
					"Items": [
						"HEAD",
						"GET"
					],
					"CachedMethods": {
						"Quantity": 2,
						"Items": [
							"HEAD",
							"GET"
						]
					}
				},
				"SmoothStreaming": false,
				"Compress": true,
				"LambdaFunctionAssociations": {
					"Quantity": 0
				},
				"FunctionAssociations": {
					"Quantity": 0
				},
				"FieldLevelEncryptionId": "",
				"ForwardedValues": {
					"QueryString": false,
					"Cookies": {
						"Forward": "none"
					},
					"Headers": {
						"Quantity": 0
					},
					"QueryStringCacheKeys": {
						"Quantity": 0
					}
				},
				"MinTTL": 0,
				"DefaultTTL": 86400,
				"MaxTTL": 31536000
			}
		]
	},
	"CustomErrorResponses": {
		"Quantity": 0
	},
	"Comment": "",
	"Logging": {
		"Enabled": false,
		"IncludeCookies": false,
		"Bucket": "",
		"Prefix": ""
	},
	"PriceClass": "PriceClass_100",
	"Enabled": true,
	"ViewerCertificate": {
		"CloudFrontDefaultCertificate": true,
		"MinimumProtocolVersion": "TLSv1",
		"CertificateSource": "cloudfront"
	},
	"Restrictions": {
		"GeoRestriction": {
			"RestrictionType": "none",
			"Quantity": 0
		}
	},
	"WebACLId": "",
	"HttpVersion": "http1.1",
	"IsIPV6Enabled": false
}

06 Run get-distribution-config command (OSX/Linux/UNIX) to describe the current version of the configuration available for the selected distribution (i.e. eTag):

aws cloudfront get-distribution-config
  --id ABCDABCDABCDAB
  --query 'ETag'

07 The command output should return the requested information:

"AAAABBBBCCCCD"

08 Modify the configuration document returned at step no. 5 to associate the newly created web ACL with the selected CloudFront distribution. Use the web ACL ID returned at step no. 3 as the value for the "WebACLId" configuration property. Save the document with the modified distribution configuration (highlighted) to a JSON file named enable-cloudfront-waf-integration.json:

{
	"CallerReference": "abcd1234-abcd-1234-abcd-1234abcd1234",
	"Aliases": {
		"Quantity": 0
	},
	"DefaultRootObject": "",
	"Origins": {
		"Quantity": 1,
		"Items": [
			{
				"Id": "cloudconformity.com",
				"DomainName": "cloudconformity.com",
				"OriginPath": "",
				"CustomHeaders": {
					"Quantity": 0
				},
				"CustomOriginConfig": {
					"HTTPPort": 80,
					"HTTPSPort": 443,
					"OriginProtocolPolicy": "http-only",
					"OriginSslProtocols": {
						"Quantity": 2,
						"Items": [
							"TLSv1.1",
							"TLSv1.2"
						]
					},
					"OriginReadTimeout": 30,
					"OriginKeepaliveTimeout": 5
				},
				"ConnectionAttempts": 3,
				"ConnectionTimeout": 10,
				"OriginShield": {
					"Enabled": false
				}
			}
		]
	},
	"OriginGroups": {
		"Quantity": 0
	},
	"DefaultCacheBehavior": {
		"TargetOriginId": "cloudconformity.com",
		"TrustedSigners": {
			"Enabled": false,
			"Quantity": 0
		},
		"TrustedKeyGroups": {
			"Enabled": false,
			"Quantity": 0
		},
		"ViewerProtocolPolicy": "allow-all",
		"AllowedMethods": {
			"Quantity": 2,
			"Items": [
				"HEAD",
				"GET"
			],
			"CachedMethods": {
				"Quantity": 2,
				"Items": [
					"HEAD",
					"GET"
				]
			}
		},
		"SmoothStreaming": false,
		"Compress": true,
		"LambdaFunctionAssociations": {
			"Quantity": 0
		},
		"FunctionAssociations": {
			"Quantity": 0
		},
		"FieldLevelEncryptionId": "",
		"ForwardedValues": {
			"QueryString": false,
			"Cookies": {
				"Forward": "none"
			},
			"Headers": {
				"Quantity": 0
			},
			"QueryStringCacheKeys": {
				"Quantity": 0
			}
		},
		"MinTTL": 0,
		"DefaultTTL": 86400,
		"MaxTTL": 31536000
	},
	"CacheBehaviors": {
		"Quantity": 1,
		"Items": [
			{
				"PathPattern": "/images",
				"TargetOriginId": "cloudconformity.com",
				"TrustedSigners": {
					"Enabled": false,
					"Quantity": 0
				},
				"TrustedKeyGroups": {
					"Enabled": false,
					"Quantity": 0
				},
				"ViewerProtocolPolicy": "allow-all",
				"AllowedMethods": {
					"Quantity": 2,
					"Items": [
						"HEAD",
						"GET"
					],
					"CachedMethods": {
						"Quantity": 2,
						"Items": [
							"HEAD",
							"GET"
						]
					}
				},
				"SmoothStreaming": false,
				"Compress": true,
				"LambdaFunctionAssociations": {
					"Quantity": 0
				},
				"FunctionAssociations": {
					"Quantity": 0
				},
				"FieldLevelEncryptionId": "",
				"ForwardedValues": {
					"QueryString": false,
					"Cookies": {
						"Forward": "none"
					},
					"Headers": {
						"Quantity": 0
					},
					"QueryStringCacheKeys": {
						"Quantity": 0
					}
				},
				"MinTTL": 0,
				"DefaultTTL": 86400,
				"MaxTTL": 31536000
			}
		]
	},
	"CustomErrorResponses": {
		"Quantity": 0
	},
	"Comment": "",
	"Logging": {
		"Enabled": false,
		"IncludeCookies": false,
		"Bucket": "",
		"Prefix": ""
	},
	"PriceClass": "PriceClass_100",
	"Enabled": true,
	"ViewerCertificate": {
		"CloudFrontDefaultCertificate": true,
		"MinimumProtocolVersion": "TLSv1",
		"CertificateSource": "cloudfront"
	},
	"Restrictions": {
		"GeoRestriction": {
			"RestrictionType": "none",
			"Quantity": 0
		}
	},
	"WebACLId": "abcd1234-abcd-1234-abcd-1234abcd1234",
	"HttpVersion": "http1.1",
	"IsIPV6Enabled": false
}

09 Run update-distribution command (OSX/Linux/UNIX) using the document modified at the previous step (i.e. enable-cloudfront-waf-integration.json) as the distribution configuration document, to reconfigure the selected Amazon CloudFront distribution in order to implement CloudFront – WAF integration for the selected distribution. --if-match parameter represents the current version of the configuration, returned at step no. 7:

aws cloudfront update-distribution
  --id ABCDABCDABCDAB
  --if-match AAAABBBBCCCCD
  --distribution-config file://enable-cloudfront-waf-integration.json
  --query 'Distribution.Status'

10 The command output should return the status of the modified CloudFront distribution:

"InProgress"

11 Repeat steps no. 1 – 10 to enable CloudFront – WAF integration for each Amazon CloudFront distribution deployed in your AWS cloud account.

References

Publication date Aug 30, 2016