Search code examples
amazon-web-serviceshttp-redirectamazon-s3amazon-cloudfront

AWS S3 static website hosting redirects not activated for requests via CloudFront distribution


We have a S3 bucket serving a static website, and it's located 'behind' a CloudFront distribution (for SSL access). It uses the www subdomain, and something like https://www.our-domain.com/ works fine.

Now we also want the 'apex' or 'naked' domain to work correctly by redirecting (via a 301 redirect) all requests to that website above. Unfortunately, that does not seem to work.

For the setup, we created another S3 bucket, something like redirect-our-domain-website, and in the properties we enabled static website hosting, selecting to redirect all requests to the target www.our-domain.com.

When we retrieve this latter bucket via the S3 bucket endpoint for static websites, http://redirect-our-domain-website.s3-website-eu-west-1.amazonaws.com we are being redirected correctly to the intended target www.our-domain.com.

Unfortunately, when creating a CloudFront distribution to also front that 'static website redirector' (again, for SSL), the redirection does not seem to get activated.

The browser result for request on the 'naked' domain https://our-domain.com/ shows that AWS S3 XML document:

<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Name>redirect-our-domain-website</Name>
  <Prefix/>
  <Marker/>
  <MaxKeys>1000</MaxKeys>
  <IsTruncated>false</IsTruncated>
</ListBucketResult>

So, instead of redirecting to the intended target, it shows a ListBucketResult of the S3 bucket of the static website redirector.

I had expected that the S3 static website redirection would redirect the request to the other S3 static website (actually containing the website).


Solution

  • I also did run into this issue and found the solution here on Stackoverflow. The reason is how CloudFont accesses the S3 bucket. There are basically two ways: Directly aka using an "S3 origin" in Cloudfront (which does not trigger the redirect) or via the S3 bucket endpoint.

    In short: Instead of selecting the bucket from the drop-down in AWS Console for CloudFront, you need the bucket endpoint. Use this hostname, instead of selecting the bucket from the drop-down list. The Origin Protocol Policy, which specifies the protocol used between CloudFront and S3, must be set to "HTTP Only".

    If you use terraform for CloudFront, this would be wrong:

    resource "aws_cloudfront_distribution" "cdn_website_redirect" {
    
      origin {
        origin_id   = "origin-bucket-${aws_s3_bucket.website_redirect_de.id}"
        domain_name = aws_s3_bucket.website_redirect_de.bucket_domain_name
    
        s3_origin_config {
          origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path
        }
      }
    }
    

    And this would be the correct approach:

    resource "aws_cloudfront_distribution" "cdn_website_redirect" {
    
      origin {
        origin_id   = "origin-bucket-${aws_s3_bucket.website_redirect_de.id}"
        domain_name = aws_s3_bucket.website_redirect_de.website_endpoint
    
        custom_origin_config {
          http_port              = 80
          https_port             = 443
          origin_protocol_policy = "http-only"
          origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
        }
      }
    }