Pointing many domains to cloudfront sub directory - amazon-web-services

I have a single page application which is hosted on s3 and have cloudfront pointing to it. The app is multi-tenant, so the "tenants" need to be able to point their domain to a subdirectory.
Example: sometenant.com should point to app.domain.com/sometenant
Is this possible? Fairly hard to test with deployment/propagation/etc...
Also wondering if I could keep pushstate working, if it's possible that is...

This can be done, but not with a single CloudFront distribution -- a single CloudFront distribution can accept and handle requests for multiple subdomains, but unless the origin web server behind CloudFront can vary the response based on the hostname (and this won't work with S3 as the origin server), the basic assumption is that all of the domains pointing to a distribution result in the same behavior.
You'll need a CloudFront distribution for each domain. Not a problem, because the default limit of 200 distributions per account can be increased on request... and distributions are easily created in automation... and you don't pay a fee for each distribution -- just the bandwidth and requests, which will essentially the same.
Each CloudFront distribution can then be configured with a default root object -- this is the page fetched from the back-end when the root / page is requested. Set this to sometenant and, for this distribution, the root page will be requested from the bucket as GET /sometenant. Any other page/object request (images, css, etc.) is forwarded straight through to the bucket.
Each tenant site needs its domain added as an alternate name for its distribution, then you configure the tenant's site to point to the distribution's assigned dxxxexample.cloudfront.net endpoint, in DNS.

Related

Combining an external site with services behind subdirectories served by Cloudfront

Objective
I have the following I wish to host under a single subdomain https://sub.example.com:
An external Wix site, which should be accessible at the root subdomain https://sub.example.com
An API accessible through AWS API Gateway, which should be accessible at https://sub.example.com/api
A flat static site in a restricted AWS S3 bucket, which should be accessible at https://sub.example.com/docs/
Attempted solution
I'm having trouble combining all this in AWS Cloudfront and Route 53. So far, I've tried setting up a Cloudfront distribution with the following default origins and behaviours:
Origin: https://username.wix.com/website (root domain as Origin domain and /website as Origin Path). Behaviour: Path as Default (*)
Origin: API Gateway Invoke URL (stage is Origin Path). Behaviour: Path as /api*.
Origin: S3 bucket domain. Behaviour: Path as /docs*.
In Route 53 I have the sub.example.com A and AAAA records pointing at the Cloudfront distribution domain.
Problems
I'm running into a few issues here:
Redirection of the Wix site is imperfect. Cloudfront hides the Wix domain at the root, but then redirects to the Wix domain for any subdirectories (e.g. https://sub.example.com/about. Also, when specifying index.html as Default root object (this is needed for the S3 static site), the Wix site 404s.
API calls work perfectly fine at https://sub.example.com/api/, but for some reason, the S3 static site is inaccessible (Access Denied) at https://sub.example.com/docs/, even when the Default root object is set as index.html.
Regarding Problem 1, I acknowledge that Cloudfront is not really meant for proxying external sites, but I'm not really sure how to otherwise keep this site at the root subdomain, especially since a Default (*) behaviour is mandatory.
Regarding Problem 2, I'm left a bit flummoxed. I tested all policies and OAIs using a separate distribution to the S3 bucket and confirmed that this is all correct. The Behaviour precedence is also correctly set (0: /docs*, 1: /api*, 2: *).
Regarding both these problems, I wonder if there may be some Route 53 wizardry that can partly solve them. Perhaps solutions can be found in Cloudfront Functions or Lambda#Edge. However, I'm not very experienced at these.
Any advice would be very welcome.

AWS CloudFront and ELB: requests doesn't reach backend

Get into quite strange trouble. Have an Cloudfront distribution with two origins: S3 and ELB.
I've set behaviors for Default () and the Custom (/test-request).
On ELB side there is a rule to forward request from my domain to certain backend. Domain also added as an alias for cloudfront distribution.
But anytime I try to reach https://my.domain/test-request I've got... nothing. Looks like all request go to S3 content and never reach the backend I need.
I've already play with options on behavior side, read a lot of tutorials, but still no luck.
I'm not searching for clear answers, but at least I need direction of my research.
I'm assuming your Cloudfront distribution configuration is
/test-request to your ELB as first priority
Default (*) to your S3 as the catch-all
my.domain is mapped to your Cloudfront's CNAME correctly
When you try to access my.domain/test-request, Cloudfront will match your cache behavior and forwards to your ELB, together with the path /test-request.
Please note that it does NOT strip the /test-request path from your original request.
Your ELB then forwards the original request to your application server, using the path /test-request.
Therefore, it's likely that your application does not expose any resource or API under the path /test-request, and the request fails as a result.
Also, since you are in this topic, please note that by default, Cloudfront does not forward query parameters or browser cookie to your custom origin which is ELB in your case. If you want to capture them, you need to configure the cache behavior properly.
Refs:
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesPathPattern
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesQueryString

Updating AWS Cloudfront to use static website hosting

I'm currently using AWS Cloudfront to serve assets for a companies website under the subdomain content.companyname.com. The current distribution points to companyname.s3.amazonaws.com.
With this setup we lack some of the static website hosting features such as a custom index.html page and a error page. I understand from this answer that I need to point instead to http://companyname.s3-website-eu-west-1.amazonaws.com to get this to work.
My question is, can I just update the Origin without having to create a new Cloudfront distribution? Or is it better to create a new Cloudfront distribution then change the DNS and associate our custom CNAME with it?
We are ideally looking to have zero downtime if possible.
Create a second Origin on the CloudFront distribution, pointing to the new endpoint.
Then you can update each Cache Behavior and select the new origin from the drop-down, and save changes.
If your bucket is correctly configured, this change will take effect over the course of a few minutes, without any downtime.

How to serve static web content from S3 backed by multiple buckets from different regions

I'm trying to serve static web content (HTML, CSS, and JS files) from S3 buckets. I know I can go to the bucket's properties tab and choose the item Use this bucket to host a website from the Static website hosting box. And I'm sure this step will still be part of the solution I'm looking for but it won't be all.
Here's what I'm trying to accomplish:
Deploying the same content to multiple regions and based on availability and/or latency, provide the service to the client.
As for the API Gateway, I know how to do this. I should create the same API Gateway (alongside underlying lambda functions) and Custom Domain Names in all the regions. And then creating the same domain on Route 53 (of type CNAME) and choose Latency as Routing Policy. One can also set up a Health Check for the Record Set so availability of the API Gateway and lambda functions are checked periodically.
Now I want to do the same for the S3 bucket and my static content. i.e. I want to deploy the same content to different regions and somehow make Route 53 to route the request to the closest available bucket. Previously, I was using CloudFront but it seems to me in this setup, I can only introduce one bucket.
Does anyone know how can I serve my static content from multiple buckets? If you are going to suggest CouldFront, please tell me how you plan to use multiple buckets.
You can generate a certificate, setup a CloudFront distribution to grab the content from your bucket and then point your domain to your distribution using Route53. You get free https and you can also add several S3 buckets as origins for your distribution.
From AWS Docs:
After you configure CloudFront to deliver your content, here's what happens when users request your objects:
1. A user accesses your website or application and requests one or more objects, such as an image file and an HTML file.
2. DNS routes the request to the CloudFront edge location that can best serve the request—typically the nearest CloudFront edge location in terms of latency—and routes the request to that edge location.
3. In the edge location, CloudFront checks its cache for the requested files. If the files are in the cache, CloudFront returns them to the user. If the files are not in the cache, it does the following:
3a. CloudFront compares the request with the specifications in your distribution and forwards the request for the files to the applicable origin server for the corresponding file type—for example, to your Amazon S3 bucket for image files and to your HTTP server for the HTML files.
3b. The origin servers send the files back to the CloudFront edge location.
3c. As soon as the first byte arrives from the origin, CloudFront begins to forward the files to the user. CloudFront also adds the files to the cache in the edge location for the next time someone requests those files.
P.D. Keep in mind this is for static content only!
This is possible with CloudFront using Lambda#Edge to change origin based on answer from Route 53.
Please refer this blog for a sample Lambda#Edge code to do this -
https://aws.amazon.com/blogs/apn/using-amazon-cloudfront-with-multi-region-amazon-s3-origins/

AWS CloudFront - Use path path based routing to pull in content from external server

I'm having difficulty mapping a path-based route defined in CloudFront to custom domain. Any ideas what I need to change?
Background:
I've got a Vue app that I host on AWS in this way. This all works fine.
I build and push files to an s3 bucket (www.example.com).
CloudFront distribution that has an origin set up with that bucket (www.example.com.s3-website-us-west-1.amazonaws.com).
A CNAME record from www to the Cloudfront domain name (d111111abcdef8.cloudfront.net)
Now I want content from a separate domain on a separate server to show up as a path on the domain rather than a subdomain like it is now. I have a blog at blog.example.com that I would like to see as www.example.com/blog.
I went through these steps:
Add new custom origin to the Cloudfront distribution (blog.example.com)
Add a new behavior to Cloudfront distribution with path pattern="blog" and Origin set to the one above ("Custom-blog.example.com")
Set the new behavior as priority 0 and the default (*) to priority 1
https://d111111abcdef8.cloudfront.net/blog does a redirect to https://blog.example.com
but https://www.example.com/blog does not
Any ideas?
Here the config images:
Origin:
Behavior:
Set "Origin Protocol Policy" to "HTTPS Only". Otherwise, Cloudfront is talking plain HTTP with the origin, which may produces unwanted redirects.
After that, invalidate the desired path fragments, since redirects can be cached as well.