How to enable redirection on a domain for an S3-hosted website with CloudFront in front of it

amazon s3amazon-cloudfrontamazon-route53amazon-web-servicesredirect

I'm trying to get redirects to work within a domain name for an S3-hosted static website. That is, if I point mydomain.com/foo, I want it to redirect to mydomain.com; this should basically mirror mydomain.com.s3-website-us-east-1.amazonaws.com/foo being redirected to mydomain.com.s3-website-us-east-1.amazonaws.com. What's happening right now is mydomain.com/foo gets redirected to mydomain.com.s3-website-us-east-1.amazonaws.com/.

I have an S3 bucket named in line with Amazon docs in order to ensure resources are redirected appropriately. I also have CloudFront configured to point to the S3 website endpoint (mydomain.com.s3-website-us-east-1.amazonaws.com), as well as the domain set up in "Alternate Domain Names (CNAMEs)".

In Route53, I've created an A record to point to the CloudFront's d123456789.cloudfront.net domain name. So, right now going to mydomain.com works just fine; however, trying to go to a resource that would cause a redirect gets me back to the ugly S3 name.

How can I keep CloudFront in the mix but get friendly redirection behavior that keeps my domain name front and center?

Edit: For example purposes, I'm trying to just redirect /upload to /; here's how I've set that up:
S3 Redirect Screenshot

Edit 2: To clarify, redirecting foo.com/update to foo.com/index.html is the minimal case; ideally I'd like to be able to redirect any resource under foo.com/ to foo.com/index.html, which is why I was pursuing the redirect rules solution.

Best Answer

You need to specify the target hostname and protocol in the routing rules. This forces the Location: to have the correct (desired) hostname.

The simplest approach for redirecting almost everything is creating a routing rule that matches 403 Forbidden (since S3 denies everything by default) and points where you want things to go.

<RoutingRules>
 <RoutingRule>
  <Condition>
    <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
  </Condition>
  <Redirect>
   <Protocol>https</Protocol> 
   <HostName>target.example.com</HostName>
   <ReplaceKeyWith></ReplaceKeyWith>
  </Redirect>
 </RoutingRule>
</RoutingRules>

All requests should redirect to https://target.example.com/, unless the requested URL matches an existing object with the public-read ACL, or an index document.

If this doesn't behave as expected, you can also change it to match on 404, but don't do that. If 404 works, this means your bucket policy is too permissive, allowing unauthenticated users to list your bucket contents... so, don't change this -- fix your policy. Use 403 here.

Related Topic