Fixing "AccessDenied" Errors for Static Websites in Cloudfront
Photo by Rod Long
TLDR
To fix “AccessDenied” errors on static website pages, such as those generated by Hugo, when deployed to S3 and served with Cloudfront, change the
Origin Domain Name
property to the S3 bucket endpoint found in theStatic Website Hosting
property.
Our Problem
If we deploy our static site to Amazon’s S3 Static Website Hosting, and serve the content with AWS Cloudfront, we may find that pages other than the homepage give an “AccessDenied” error message.
Generated Path
When building our static site with a generator such as Hugo, we create content pages such as the About page. However, instead of generating example.com/about.html
, the site page generated is typically something like example.com/about/index.html
. But we would like to reach the About page by navigating to its directory example.com/about/
without explicitly specifying /index.html
in the path.
Normally, if no file extension is specified in the URL, a web server will assume that is a directory path and look for an index.html
file to serve to the user. Hosting our site directly from S3 without Cloudfront, does exactly this. Adding Cloudfront changes this functionality, and only looks for this file from the root directory example.com/
Default Root Object
In this case the index.html
page is our “Default Root Object”. Note that in both S3 and Cloudfront we need to specify the name of the “Default Root Object”. Again, S3 will look for index.html
file after any path if we use it without Cloudfront. However, if we serve our site with Cloudfront, it will only look for this file in the root directory.
Origin Domain Name
To resolve this, we can replace the path made available in the Origin Domain Name dropdown (example.com.s3.amazonaws.com
), with the Endpoint shown in the Static website hosting in the S3 Properties (example.com.s3-website-us-east-1.amazonaws.com
). This effectively bypasses Cloudfront’s behavior in favor of S3’s.
Additional Information
While this solution works, it affects the ability to restrict direct access to the S3 endpoint by a client. AWS offers another solution, which is to modify the incoming URLs with Lambda@Edge See this StackOverflow post for additional discussion of this topic.
COMMENTS