Apply WAF Web ACL to CloudFront
AWS WAF can be applied to the following four types of resources
- ALB
- CloudFront
- API Gateway
- AppSync
In this article, we will check how to apply WAF to CloudFront.
For details on how to apply WAF to ALB, please refer to the following page.
For information on how to apply WAF to API Gateway, please see the following page
For information on how to apply WAF to AppSync, please refer to the following page
Environment
Create a WAF Web ACL.
Restrict geography.
Specifically, create your own rule group and set a rule to block access from Japan (JP) in it.
Apply the created Web ACL to CloudFront.
Create a CloudFront distribution.
Specify an S3 bucket as the origin.
Create an OAI in CloudFront and restrict the S3 bucket policy to allow access only from the OAI.
Create a Lambda function.
Configure this function as a CloudFormation custom resource.
The function’s function is to automatically create and delete objects in the bucket when creating and deleting stacks.
The object to be created is index.html for static website hosting.
The runtime for the function is Python 3.8.
CloudFormation template files
The above configuration is built using CloudFormation.
The CloudFormation templates are located at the following URL
https://github.com/awstut-an-r/awstut-fa/tree/main/051
Explanation of key points of template files
This page focuses on how to apply WAF to CloudFront.
For basic information on WAF, please refer to the following page
For information on how to restrict geography with WAF, please refer to the following page
For information on how to specify an S3 bucket as the origin of CloudFront and use OAI, please refer to the following page
For information on custom resources in CloudFormation, please refer to the following page
Region to create WAF to be applied to CloudFront
When applying WAF to CloudFront, the first point to be considered is the region where the WAF will be created.
For CLOUDFRONT, you must create your WAFv2 resources in the US East (N. Virginia) Region, us-east-1.
AWS::WAFv2::WebACL
Please note that there are region restrictions when applying WAF to CloudFront as described above.
Web ACL
Resources:
RuleGroup:
Type: AWS::WAFv2::RuleGroup
Properties:
Capacity: 10
Name: !Sub "${Prefix}-GeoRestrictionRuleGroup"
Rules:
- Action:
Block: {}
Name: !Sub "${Prefix}-GeoRestrictionRule"
Priority: 0
Statement:
GeoMatchStatement:
CountryCodes:
- JP
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: !Sub "${Prefix}-GeoRestrictionRule"
SampledRequestsEnabled: true
Scope: CLOUDFRONT
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: !Sub "${Prefix}-GeoRestrictionRuleGroup"
SampledRequestsEnabled: true
WebACL:
Type: AWS::WAFv2::WebACL
Properties:
DefaultAction:
Allow: {}
Name: !Sub "${Prefix}-WebACL"
Rules:
- Name: !Sub "${Prefix}-WebACL-GeoRestriction"
OverrideAction:
None: {}
Priority: 0
Statement:
RuleGroupReferenceStatement:
Arn: !GetAtt RuleGroup.Arn
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: !Sub "${Prefix}-WebACL-GeoRestriction"
SampledRequestsEnabled: true
Scope: CLOUDFRONT
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: !Ref Prefix
SampledRequestsEnabled: true
Code language: YAML (yaml)
Define rule groups for Web ACLs and ACLs and set geo-restrictions.
The key point is the Scope property for both resources.
Instructions on how to set this property are provided below.
Specifies whether this is for an Amazon CloudFront distribution or for a regional application. A regional application can be an Application Load Balancer (ALB), an Amazon API Gateway REST API, or an AWS AppSync GraphQL API. Valid Values are CLOUDFRONT and REGIONAL.
AWS::WAFv2::WebACL
This time, WAF will be applied to CloudFront, so set “CLOUDFRONT” to this property.
CloudFront
Resources:
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
Compress: true
ForwardedValues:
Cookies:
Forward: none
QueryString: false
TargetOriginId: !Ref BucketName
ViewerProtocolPolicy: allow-all
DefaultRootObject: index.html
Enabled: true
Origins:
- DomainName: !Ref BucketRegionalDomainName
Id: !Ref BucketName
S3OriginConfig:
OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${OAI}"
PriceClass: PriceClass_All
WebACLId: !Ref WebACLArn
Code language: YAML (yaml)
The key point is the WebACLId property.
Specify the ARN of the WAF mentioned above for this property.
When applying WAF to ALB, we associated it by creating an AWS::WAFv2::WebACLAssociation resource and specifying both ARNs for it.
Please note that this resource is not used for CloudFront, as quoted below.
For Amazon CloudFront, don’t use this resource. Instead, use your CloudFront distribution configuration. To associate a web ACL with a distribution, provide the Amazon Resource Name (ARN) of the AWS::WAFv2::WebACL to your CloudFront distribution configuration.
AWS::WAFv2::WebACLAssociation
Architecting
Use CloudFormation to build this environment and check the actual behavior.
Create CloudFormation stacks and check resources in stacks
Create a CloudFormation stacks.
For information on how to create stacks and check each stack, please refer to the following page
This time, be careful which region you create the stack in.
When creating a stack with the AWS CLI, specify the us-east-1 region in the region option as shown in the command below.
aws cloudformation create-stack \
--stack-name [stack-name]
--template-url https://[bucket-name].s3.[region].amazonaws.com/[folder-name]/fa-051.yaml
--capabilities CAPABILITY_IAM
--region us-east-1
Code language: Bash (bash)
After checking the resources in each stack, the following is the information on the main resources created in this case.
- S3 bucket: fa-051
- CloudFront distribution domain: https://d1pvh6f3ahqkqz.cloudfront.net/
- Name of WAF: fa-051-WebACL
The resources are also checked from the AWS Management Console.
First is CloudFront.
We can see that the CloudFront distribution has been created and AWS WAF has been applied.
Next, check the Web ACL.
The key point is that the Web ACL is created in the “Global (CloudFront)” region.
Note that it is not in us-east-1, where the CloudFormation stack was created.
From the Web ACL side, you can also see that this ACL is applied to CloudFront.
Checking action
Now that everything is ready, access CloudFront from Japan.
Access was denied.
Because you accessed from Japan, the WAF Web ACL filtered the access before it reached CloudFront.
To confirm, change the action of the geo-restriction.
We changed the rule action from blocking to counting, i.e., keeping the rule alive but only counting the number of traffic that corresponds to the rule.
Access CloudFront again.
You can now access CloudFront.
This is because the rule action has been changed from block to count only, and access is now possible.
Summary
We have seen how to apply WAF ACLs to CloudFront.