We're trying to distribute out S3 buckets via Cloudfront but for some reason the only response is an AccessDenied XML document like the following:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>89F25EB47DDA64D5</RequestId>
<HostId>Z2xAduhEswbdBqTB/cgCggm/jVG24dPZjy1GScs9ak0w95rF4I0SnDnJrUKHHQC</HostId>
</Error>
Here's the setting's we're using:
And here's the policy for the bucket
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity *********"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::x***-logos/*"
}
]
}
If you're accessing the root of your CloudFront distribution, you need to set a default root object: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html
To specify a default root object using the CloudFront console:
Sign in to the AWS Management Console and open the Amazon CloudFront console at https://console.aws.amazon.com/cloudfront/.
In the list of distributions in the top pane, select the distribution to update.
In the Distribution Details pane, on the General tab, click Edit.
In the Edit Distribution dialog box, in the Default Root Object field, enter the file name of the default root object.
Enter only the object name, for example,
index.html
. Do not add a / before the object name.To save your changes, click Yes, Edit.
I've just had the same issue and while Kousha's answer does solve the problem for index.html in the root path, my problem was also with sub-directories as I used those combined with index.html to get "pretty urls" (example.com/something/ rather than "ugly" example.com/something.html)
Partially it's Amazon's fault as well, because when you set up CloudFront distribution, it will offer you S3 buckets to choose from, but if you do choose one of those it will use the bucket URL rather than static website hosting URL as a backend.
So to fix the issue:
UPDATE Jan '22: you can also fix this by keeping static hosting OFF and adding a CloudFront function to append
index.html
. See this post on SO for more information. This allows you to use an OAI and keep the bucket private.I had the same issue as @Cezz, though the solution would not work in my case.
As soon as static website hosting is enabled for the bucket, it means users can access the content either via the Cloudfront URL, or the S3 URL, which is not always desirable. For example, in my case, the Cloudfront distribution is SSL enabled, and users should not be able to access it over a non-SSL connection.
The solution I found was to:
Note though that in my case, I'm serving a single page javascript application where all paths are resolved by index.html. If you've paths that resolve to different objects in your S3 bucket, this will not work.
In my case I was using multiple origins with "Path Pattern" Behaviors along with an Origin Path in my S3 bucket:
Bad setup:
CloudFront Behavior:
/images/*
->My-S3-origin
My-S3-origin: Origin Path:
/images
S3 files: /images/my-image.jpg
GET Request: /images/my-image.jpg -> 403
What was happening was the entire CloudFront GET request gets sent to the origin:
/image/my-image.jpg
prefixed by Origin Path:/images
, so the request into S3 looks like/images/images/my-image.jpg
which doesn't exist.Solution
remove Origin Path.
This allowed me to access the bucket with an origin access identity and bucket permissions and individual file permissions restricted.
In my case I had configured Route 53 wrongly. I'd created an Alias on my domain but pointed it to the S3 Bucket instead of the CloudFront distribution.
Also I omitted the default root object. The console could really be improved if they add a bit of information to the question mark text about the potential consequences of omitting it.
My issue was that I had turned website hosting off and had to change the origin name from the website path to the normal non-website one. That had removed the origin access identity. I put that back and everything worked fine.
If block public access is On and Hosting disabled, you need to setup Error Pages with appropriate HTTP error code and HTTP response code in CF.