How to create a security group allowing traffic from CloudFront only?

Andreas Wittig – 07 Mar 2022

It is one of those problems for which there has been no satisfactory solution for years. How do you ensure that only CloudFront is granted access to an Elastic Load Balancer - CLB, ALB, or NLB? Without the ability to restrict incoming traffic, all of CloudFront’s network layer protection does little good. You will learn how to use AWS-managed prefix list for Amazon CloudFront in the following.

How to create a security group allowing traffic from CloudFront only?

Until recently, when using a load balancer or similar endpoint as the origin for a CloudFront distribution, you had to allow incoming HTTPS traffic from anywhere (0.0.0.0/0). At least, there was no simple way to maintain a list with all the IP addresses used by the CloudFront edge locations worldwide. In my opinion, automatically updating a security group by using a Lambda function is nothing I want to run in production.

Therefore, probably many other AWS customers and we ended up with the following situation. The load balancer was accessible not only from CloudFront but from anywhere. This made it possible to bypass CloudFront’s protective measures.

ALB accessible from anywhere

Luckily, AWS announced managed prefix lists for CloudFront on February 7, 2022. The prefix list contains all IP ranges used by CloudFront edge locations. AWS updates the prefix list when needed. You can easily use the prefix list to restrict access when configuring a security group, as shown in the following figure.

This means that CloudFront’s protection measures can no longer be bypassed. It is ensured that all incoming traffic on the load balancer comes from CloudFront.

ALB accessible from CloudFront only

However, keep in mind that anyone can create a CloudFront distribution. This does not guarantee that all the requests arriving at your load balancer originate from your CloudFront distribution. Check out to learn how to restrict access at the application layer.


Looking for a new challenge?

  • tecRacer

    Cloud Consultant

    tecRacer • Premier AWS Consulting Partner • Germany, Austria, Spain, and Switzerland
    AWS only Infrastructure as Code EC2 Containers Serverless
  • tecRacer

    Cloud Migration Specialist

    tecRacer • Premier AWS Consulting Partner • Germany, Austria, Spain, and Switzerland
    Lift&Shift Transformation EC2 RDS VPC

So how do you create a security group that only allows incoming traffic from CloudFront by using an AWS-managed prefix list? We will present the Terraform and CloudFormation code in the following.

The following snippet shows the Terraform code needed to create a security group that allows incoming HTTPS traffic from CloudFront only. The data source aws_ec2_managed_prefix_list fetches the ID of the prefix list by name.

data "aws_ec2_managed_prefix_list" "cloudfront" {
name = "com.amazonaws.global.cloudfront.origin-facing"
}

resource "aws_security_group" "lb" {
name = "loadbalancer"
vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id
}

resource "aws_security_group_rule" "lb_ingress_cloudfront" {
description = "HTTPS from CloudFront"
security_group_id = aws_security_group.lb.id
type = "ingress"
from_port = 443
to_port = 443
protocol = "tcp"
prefix_list_ids = [data.aws_ec2_managed_prefix_list.cloudfront.id]
}

Unfortunately, things are getting a little more complicated when using CloudFormation. The ID of the prefix list aws_ec2_managed_prefix_list varies between the regions. Luckily, it seems to be the same for all AWS accounts. Therefore, I’m using a mapping between the region and the prefix list for CloudFront in the following snippet.

Mappings:
RegionMap:
'af-south-1':
PrefixListCloudFront: 'pl-c0aa4fa9'
'eu-north-1':
PrefixListCloudFront: 'pl-fab65393'
'ap-south-1':
PrefixListCloudFront: 'pl-9aa247f3'
'eu-west-3':
PrefixListCloudFront: 'pl-75b1541c'
'eu-west-2':
PrefixListCloudFront: 'pl-93a247fa'
'eu-south-1':
PrefixListCloudFront: 'pl-1bbc5972'
'eu-west-1':
PrefixListCloudFront: 'pl-4fa04526'
'ap-northeast-2':
PrefixListCloudFront: 'pl-22a6434b'
'me-south-1':
PrefixListCloudFront: 'pl-17b2577e'
'ap-northeast-1':
PrefixListCloudFront: 'pl-58a04531'
'sa-east-1':
PrefixListCloudFront: 'pl-5da64334'
'ca-central-1':
PrefixListCloudFront: 'pl-38a64351'
'ap-east-1':
PrefixListCloudFront: 'pl-14b2577d'
'ap-southeast-1':
PrefixListCloudFront: 'pl-31a34658'
'ap-southeast-2':
PrefixListCloudFront: 'pl-b8a742d1'
'eu-central-1':
PrefixListCloudFront: 'pl-a3a144ca'
'us-east-1':
PrefixListCloudFront: 'pl-3b927c52'
'us-east-2':
PrefixListCloudFront: 'pl-b6a144df'
'us-west-1':
PrefixListCloudFront: 'pl-4ea04527'
'us-west-2':
PrefixListCloudFront: 'pl-82a045eb'
Resources:
LoadBalancerSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: 'loadbalancer'
VpcId: 'vpc-40e43c28'
LoadBalancerSecurityGroupInWorld:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref LoadBalancerSecurityGroup
IpProtocol: tcp
FromPort: 443
ToPort: 443
SourcePrefixListId: !FindInMap ['RegionMap', !Ref 'AWS::Region', 'PrefixListCloudFront']

There is one stumbling block to consider. The prefix list is not available in ap-northeast-3 and ap-southeast-3.

I implemented this for one of our consulting clients and our open source project widdix/aws-cf-templates right away. I highly encourage you to do the same.

Become a cloudonaut supporter

Andreas Wittig

Andreas Wittig ( Email, Twitter, or LinkedIn )

We launched the cloudonaut blog in 2015. Since then, we have published 345 articles, 45 podcast episodes, and 37 videos. It's all free and means a lot of work in our spare time. We enjoy sharing our AWS knowledge with you.

Please support us

Have you learned something new by reading, listening, or watching our content? With your help, we can spend enough time to keep publishing great content in the future. Learn more

$
Amount must be a multriply of 5. E.g, 5, 10, 15.

Thanks to Alan Leech, Alex DeBrie, ANTHONY RAITI, Jaap-Jan Frans, Jason Yorty, Jeff Finley, Jens Gehring, jhoadley, Johannes Grumböck, John Culkin, Jonas Mellquist, Juraj Martinka, Kamil Oboril, Ken Snyder, Ross Mohan, Ross Mohan, sam onaga, Shawn Tolidano, Thorsten Hoeger, Todd Valentine, and all anonymous supporters for your help! We also want to thank all supporters who purchased a cloudonaut t-shirt.