AWS CloudFront and ELB: requests doesn't reach backend - amazon-web-services

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

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 Route 53 https://example.com goes to blank page

I have set up an S3 bucket to reroute all traffic to example.com to www.example.com with https according to this very poor AWS guide. It works for example.com and http://example.com.
But when I access https://example.com it hangs for a little while and then routes to a blank page. Why is it so difficult to redirect a URL I own to another one in AWS and how do I fix this?
Edit:
I am now configuring CloudFront distributions and trying to find one decent tutorial explaining how to perform this seemingly simple task.
Did you miss this line in the link you provided:
Note: The sites must use HTTP, because the redirect can't connect to Amazon S3 over HTTPS.
You are trying to do something that is expliciting called out as not being possible in the docs.
BTW: If you want to use https to service static s3 websites, using cloudfront if often the easiest and quickest way to do that.
https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-https-requests-s3/
So I finally figured this out and I am going to describe here what worked for me. E.J.'s answer above was a helpful pointer but wasn't specific enough to make this the absolutely trivial task I would hope this to be, even for a first-timer.
Here are the exact steps required, with some prior notes.
Two notes:
You HAVE to setup an SSL certificate with AWS to re-route after https. As an organisation AWS has not yet reached the place where automatic certificate management is... well... automatic. You have to use what I might call AWS "Extremely Manual" ACM.
You need an AWS S3 bucket (make it have the name of the domain your are routing FROM).
Steps:
Follow this guide to setup a S3 bucket that will route (without HTTPs) from example.com to www.example.com (or vice versa I guess)
Navigate to the absolute eye-sore that is Amazon CloudFront
Click everywhere until you find a button to "create distribution"
Set "Origin Domain Name" to the link for the bucket created in step 1. DO NOT use the one AWS recommends, you have to go to the bucket and copy the end-point manually, the one AWS fills-in automatically will not work. It should look like this: example.com.s3-website-eu-west-1.amazonaws.com but location and stuff will be different obviously. Not sure why AWS recommends the wrong end-point but that is the least of my concerns about this process.
This guide works for the rest of the CloudFront distribution creation but is not super specific and points to this mess at one important part. The other steps are okay but when creating an SSL certificate just click that "Request or Import a Certificate with ACM" button (you will have to refresh after creating a certificate because Ajax didn't exist when the AWS console was made 200 years ago)
And the most important step, take the link or whatever it is to your CloudFront distribution (which will look like this: d328r8fyg.cloudfront.net, this one is fake because apparently you're not supposed to share them), and make the A record for example.com created in step 1 point to that CF distro instead of pointing directly to your bucket.
And voila, only took about 3 hours to get a URL to redirect somewhere securely. Not sure why people expect us to make it to Mars when the largest company in the world can't point one url to another and Microsoft Image Editor still can't crop to a specific pixel dimension.
Anyway. I'm glad this is over.

AWS unable to enforce https for S3 bucket

I have tried several tutorials on how to set up https via CloudFront, but nothing is working. I am hosting from an S3 bucket and the app works fine via the http protocol, but I need it to be https.
Does anyone have a very thorough tutorial on how to make this work?
Some tutorials explain how to go about setting up a certificate, some explain how to use CloudFront to handle its distribution and I even found a CloudFront tutorial that explains how not using a link from the CloudFront setup forces the wrong region to be created for a certificate, so I even tried that.
I have not found anything that explains exactly what needs to be done for this very common setup, so I am hoping that someone here has some helpful resources.
I think the main issue I had when setting up a CloudFront distribution for an S3 static webhosting bucket was in the Orign Domain Name.
When you create a new distribution, under Origin Settings, the Origin Domain Name field works as a drop-down menu and lists your buckets. Except that picking a bucket from that list doesn't work for static webhosting. You need to specifically put the endpoint for the bucket there, for example:
mywebhostingbucket.com.s3-website-sa-east-1.amazonaws.com
And for custom domains, you must set up the CNAMEs under Distribution Settings, Alternate Domain Names (CNAMEs), and then make sure you have your custom SSL certificate in the us-east-1 region.
Then you can configure the alias record set for the CloudFront distribution.
Here is a complete answer for setting up a site with https.
I had everything in this document completed:
https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html
And it worked to get the site live via http, but in order to add https, I needed to do the following:
I had requested a certificate for whatever.com, and tried several suggestions after that. But there were a couple of things missing.
To route traffic for the domain (whatever.com) to CloudFront distribution, you will need to clear the current value of the A record and fill in distribution domain name.
Several documents that I viewed said to point the whatever.com S3 bucket to the www.whatever.com S3 bucket, and use the second one to drive the site. Since CloudFront can serve multiple domain name, you may set CNAME of distribution with both, but you will need to set A record for both to distribution AND request an ACM certificate with both domain names (with and without the www). Also, I did ask this, so if you already have a certificate, you can't edit it to do this, which means you'll need to request a new one that has both whatever.com and www.whatever.com
After all of this, I still got "Access Denied" when I went to my site, so to fix this issue, I had to create a new origin in CloudFront with 'Origin Domain Name' set to the full address of the S3 bucket (without the http), and then set the Default (*) Behavior to the S3-Website-.....whatever.com bucket.
After all of this, my site was accessible via http AND https. I hope this helps anyone who experienced this challenge.

Pointing many domains to cloudfront sub directory

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.

Amazon CloudFront custom origin configuration

I'd like CloudFront to first search S3 for a file, defaulting to my custom server if the image is not found. Is this possible?
Unfortunately CloudFront does not have a flexible fallback mechanism.
Depending on your specific use case, you could use an alternate approach where you configure CloudFront to pass all traffic trough your custom server and configure the server to proxy the request to S3 by default and, if that fails, to serve a local copy of the file.
It's also possible that, instead of actually proxying the content from S3, you just configure your server to redirect to the S3 object if it exists, to reduce the traffic that goes trough your server.
Another approach, that could possibly apply if you have a CloudFront distribution dedicated to serving images, is to set your S3 bucket as the distribution's origin and configure a custom error page for 404 errors to serve a default image that's also hosted on S3. For this approach, see:
http://aws.typepad.com/aws/2013/09/custom-error-pages-and-responses-for-amazon-cloudfront.html
You could to try and set it up as a reverse proxy. I haven't tested it, but it falls back to your domain if the asset is missing. Who knows what the 'break' would be that you would need a fallback. But this would help in a number of cases, such as a new admin accidentally deleting your cloudfront bucket.