Custom CloudFront distributions and regional API endpoints: a tutorial

title.png

Configuring a custom CloudFront distribution for regional API Gateway endpoints has many benefits. But the documentation is scant, and leaves out several key settings that must to be tweaked for it all to work. Ater many hours piecing together information from the forums, and my own experimentation, I’ve put together this tutorial in the hope that it will provide you with all the information you need, to set up your own CloudFront distributions for regional API endpoints!

Context: in AWS API Gateway you can associate custom domain names with paths to your REST API. These domain mappings are either

  • edge-optimised, meaning your custom domain name will map to an auto-generated CloudFront distribution, providing some caching benefits, or

  • regional, meaning your custom domain name will map directly to an API Gateway endpoint in the same region as the API itself

“Normal” CloudFront distributions are under your control. But the ones that AWS generates in the edge-optimised scenario are service-controlled: AWS jargon meaning that you don’t have any access to their configuration or ability to invalidate their cache.

Then a few years ago, AWS made it possible to associate custom CloudFront distributions with regional endpoints. In theory this setup provides the best of both worlds: you have complete control over the caching strategy for your API, can invalidate caches and so on, while retaining the nice simple mapping between your custom domain name on one side, and your serverless REST API on the other.

The Problem: the documentation on setting up regional endpoints with custom CloudFront distributions is very limited, and there are several undocumented settings that need to be tweaked for it all to work.

Let’s get started! The objective of this tutorial will be to associate a custom subdomain, api.communitybox.co, with a CloudFront distribution that in turn maps to a REST API inside API Gateway.

1. Configure global and regional SSL certificates

If your API resides in the North Virginia (us-east-1) region you only need to generate one SSL certificate. If your API resides in a different region, you will need to generate two certificates: one in the North Virginia region, and one for the region that your API resides in. The SSL certificates can either contain wildcards (*.communitybox.co in our example) or be tied down to the specific subdomain (api.communitybox.co in our example). The certificates can be easily generated by using the AWS Certificate Manager.

2. Set up a custom domain mapping

Following the steps from the documentation, we go to the API Gateway console, click on Custom Domain Names:

img1.png

We then add a new domain by clicking Create Custom Domain Name and specify api.communitybox.co as the custom domain, selection the Regional distribution (not edge-optimised) and providing the region-specific certificate we created in step 1 (I’ve omitted the base path mappings from the image, as they aren’t relevant for this tutorial):

img2.png

Make a note of the Target Domain Name: this is the URL that you will specify in the Origin field in step

3. Provision a CloudFront distribution

Create a new CloudFront distribution, paying special attention to the following settings:

  • Origin Domain Name: this should be the Target Domain Name from step 2

  • Alternate Domain Name: this should be your custom domain name (in our example, api.communitybox.co)

  • SSL Certificate: select Custom SSL Certificate and specify the North Virginia region certificate we created in step 1

Wait for the distribution to be created. Next we will make two tweaks to the distribution Behaviour and Origin.

4. Make the Origin Protocol Policy HTTPS-only

New CloudFront distributions default to a HTTP-only protocol for communicating with the origin domain, which in our case is an API Gateway endpoint. However API Gateway is HTTPS-only, so we need to tell CloudFront to use HTTPS for communicating with API Gateway. To do so, select the new distribution in the CloudFront console, go to the Origins and Origin Groups tab, select the Origin (there should only be one) and click Edit, then set the policy to HTTPS only. If you get a 502 error when you try your distribution, it is likely because you missed this step!

img3.png

5. Whitelist the Host header field

We’re nearly there! However there is one last step that we need to take before it all will work. Credit for discovering and disseminating this critical step goes to Alex Clifford in this forum thread. Remember in step 2 we set up a domain mapping between a domain (api.communitybox.co) and an API. The API Gateway will reject any incoming requests that are not associated with the custom domain. So we need to tell CloudFront to pass the Host field of the incoming request, straight through to API Gateway without modification.

In the CloudFront console, select the distribution and go to the Behaviours tab and select the only Behaviour available. Next, change the Cache Based on Selected Headers field to “Whitelist” and add the Host field to the Whitelist Headers:

img4.png

6. Map your DNS record to the CloudFront distribution

The final step is to create a mapping between the DNS records for our custom domain, and the CloudFront distribution. The steps here will vary based on your DNS provider though typically you will end up creating a CNAME record that points your domain to the CloudFront distribution’s Domain Name (if you’re using Route 53 then you could also use AWS-specific A Alias records).

Conclusion

…and we’re done! When a client request is made to api.communitybox.co, this will now hit the CloudFront distribution thanks to the DNS mapping from step 6. CloudFront in turn will forward the request on to the regional endpoint we created in step 2. We now get the benefits of CloudFront edge optimisation, while retaining full control over the distribution itself, for example if we need to invalidate the distribution cache or wish to make any other changes to the caching behaviour.

Roland Hougs is currently working on Community Box, among other things, at Fraction 7 - if you have any questions you can find him on Twitter @ominouswater!

rolandbh