S3 hosted website Cloudfront distribution and API Gateway custom domain pointing to the same subdomain
Asked Answered
E

1

4

I have a subdomain for my website named api.example.com and I want to have the following achieved:

  • have 1 CloudFront distribution for an S3 static website mapped to api.example.com

  • have the API Gateway custom domain name mapped to the same subdomain api.example.com

The steps I did to achieve this setup are:

  1. Create an API Gateway custom domain api.example.com and set the base mappings for the APIs I want to expose as v1 (version 1 for now)

  2. In Route 53 I created a CNAME record api.example.com pointing to the Edge optimized Target domain name of the API Gateway from Step 1

Note: at this point I get, as expected, the 200 response from https://api.example.com/v1

  1. I created an S3 bucket and set it up for Static website hosting. All files uploaded successfully and working.

  2. I created a new Cloudfront distribution with the origin in the S3 bucket. At this point, for this Cloudfront distribution, I can not set the CNAME record as api.example.com because it is already used by the first Custom Domain Name set in the API Gateway and AWS gives an CNAMEAlreadyExistsException - so I leave this field empty. Accessing the CloudFront distribution for the S3 bucket works as expected.

  3. Under the CloudFront distribution generated for the S3 bucket I add another origin (the API Gateway custom domain name) and create the Bevahior rule to route the v1/* calls to API Gateway custom domain name.

At this point, things are not falling into place anymore: - when accessing https://api.example.com I get the {"message": "Fobidden" } from the API Gateway distribution. However the URL https://api.example.com/v1 still returns the expected result.

Question: Is there anything which I missed to set so it will work for the URL https://api.example.com to return the content of the S3 static website?

Note: also, the fact that I have an empty CNAME field on the S3 bucket cloudfront distribution while I have a CNAME defined in Route53 using the same cloudfront distribution prompts me an warning message saying that this situation may expose me to a vulnerability.

Epexegesis answered 20/9, 2018 at 23:24 Comment(0)
K
5

For your usecase mentioned, you only need one Cloudfront distribution (which is mapped to api.example.com) where it should be able to forward the traffic to S3 and API Gateway (both added as origins to the same distribution) using different behavior configurations. You can configure the behaviors in a way that /v1/* traffic is routed to the API Gateway and other traffic to S3.

When setting up the origins and behaviors, there are few configurations you need to follow.

  • Make sure both S3 and API Gateway behaviors redirects HTTP to HTTPS.
  • When adding API Gateway origin set only to forward HTTPS traffic.
  • In API Gateway behavior, whitelist the headers for accept-* ones , authorization, origin, referrer and makesure you do not whitelist 'Host' header.
  • In both origins, don't add any paths.
  • For the API Gateway behavior configure the TTLs to 0 and allow all the methods (GET, POST & etc.)
Kragh answered 21/9, 2018 at 2:3 Comment(5)
I did not have 2 distributions - I had only one for S3. The 2nd origin was set for the API Gateway Custom Domain Name. I re-did the configuration, but this time I set the API Gateway custom domain name as abc.example.com as I cannot set it toapi.example.com as the CNAME is taken by the S3 distribution. When accessing the api.example.com the S3 website is returned, however the API URLs are now returning {"message":"Forbidden"}.Epexegesis
The API Gateway deployment needs no custom domain name at all. The CloudFront distribution can have an origin set up to point to the generic execute-api hostname of the API. (Also the API should be regional, not edge-optimized. It would work either way but when used behind your own CloudFront distro, edge-optimized should not be used because it will have somewhat higher latency and some headers may not come through as expected because the request traverses the AWS edge network twice instead of once.)Kessler
Michael's comment works.. so creating another origin which points to the generic execute-api host name of the API Gateway will work - no need to create a custom domain name at all. I needed the custom domain for a different reason (to consolidate multiple APIs under one URL) but this can be done also using CloudFront distribution origins pointing to the API Gateway execute API URLs. Thanks Michael!Epexegesis
Can you enumerate exactly whats headers to forward?Molder
@Tyrsius As I recall, you can forward the headers other than "Host" header.Kragh

© 2022 - 2024 — McMap. All rights reserved.