CloudFront can cache objects and serve them to your users directly from edge nodes, by doing this reduces the load on your entire backend architecture, this way lowering the latency and even absorbing some DDoS traffic, all covered in a boxed solution.

If you need to run some simple but public web app in AWS Cloud, you will likely be using ElasticBeanstalk as the k8-&-friends ceremony is not worthy, and for whatever reason, your instances are not deployed in a private subnet, then ElasticBeanstalk DNS is reachable over the internet.

This configuration is quite popular, at least when you're just getting started. (see VPC with a single public subnet)

You make use of CloudFront because

  • It's super powerful with 300+ points of presence around the globe
  • Offers caching at the edge, this way you can serve your users much faster
  • Significantly reduces the load on your backend infrastructure
  • You can actually run code/logic via utilizing Lambda@edge and CloudFront Functions
  • Can attach the powerful Shield to your distribution
  • Many more reasons outside the scope of this topic that make this super service so appealing to use

But, the idea that ElasticBeanstalk DNS or EC2 IP is publicly accessible, defeats many of the strong points of CloudFront. Well, not anymore :). Since Feb 2022 Amazon VPC now supports an AWS-managed prefix list for Amazon CloudFront, meaning that now we can make use of this list to any service that supports a managed prefix list. To see this in action, I'll set up a sample Elastic Beanstalk environment and then make use of the managed list to secure its access.

asdf

Instance setup

Head over to the ElasticBeanstalk menu using the console, create a new environment, choose "Web server environment" for the service tier, and hit next. Complete the next page's required info and create your sample environment. If you didn't open the advanced configurations, this might create a load-balanced instance. For this purpose that's not needed. You can edit instance configurations and change from load balanced to a single instance.

Wait a few minutes so it runs, and make sure you can directly access this environment

curl -I http://ebtest-cf.us-east-1.elasticbeanstalk.com/
HTTP/1.1 200 OK
Date: Sun, 23 Oct 2022 13:50:29 GMT
Content-Type: text/html
Content-Length: 2308
Connection: keep-alive
Server: nginx/1.20.0
Last-Modified: Tue, 01 Sep 2020 21:21:33 GMT
Accept-Ranges: bytes
ETag: "1d680a5dd9ca584"

CloudFront setup

Head over CloudFront menu and create a distribution. Place the Elastic Beanstalk application URL as the origin.

After the CloudFront distribution is live, make sure you can access the Beanstalk sample app by using the provided distribution domain name. Here's mine (left elastic beanstalk, right CloudFront)

Left: Elastic Beanstalk, Right:CloudFront

Update Security Group

Visit the VPC page, on the left side you have the "Managed Lists" menu. Open it up and notice the result, AWS is managing IP lists for

  • S3
  • DynamoDB
  • GroundStation
  • CloudFront

Make a note of the prefix list id for CloudFront, looks something like "pl-abc123".

Head over to the Elastic Beanstalk menu, select your environment, and open the configuration page. When this instance was created, a new security group is designed just for it. Make note of your security group name, we're going to modify it.

Open the EC2 page, Click the "Security Groups" menu under the "Network and Security" group.

Select the desired Security Group and modify inbound rules.

  • Delete the default HTTP inbound rule that allows anything
  • Add a new HTTP inbound rule that allows traffic from the prefix list id marked out in the previous step.
  • Voila! That's it :), Now your Elastic Beanstalk Instance can only be accessed from CloudFront IPs. The security group will block any other route access

Left: Blocked Access, Right: Allow from CloudFront

So, congratulations, with these basic steps you've now whitelisted CloudFront access and blocked everything else. Head over AWS documentation for in-depth details

Aws anouncement doc | Working with prefix lists