When setting up CloudFront distributions with S3 origins, the dreaded AccessDenied
XML response is one of the most common roadblocks developers face. Let's examine a real-world configuration that's failing:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>89F25EB47DDA64D5</RequestId>
<HostId>Z2xAduhEswbdBqTB/cgCggm/jVG24dPZjy1GScs9ak0w95rF4I0SnDnJrUKHHQC</HostId>
</Error>
The current setup appears correct at first glance:
- CloudFront distribution properly configured with S3 origin
- Origin Access Identity (OAI) created and attached
- S3 bucket policy that references the OAI
Here's the bucket policy being used:
{
"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/*"
}
]
}
After analyzing hundreds of similar cases, I've found the most common culprit is mismatched OAI identifiers. The bucket policy must reference the exact OAI attached to your CloudFront distribution.
Here's how to verify and fix this:
# First, get your distribution's OAI ID
aws cloudfront list-distributions \
--query "DistributionList.Items[].Origins.Items[].S3OriginConfig.OriginAccessIdentity"
# Then cross-check with your bucket policy
aws s3api get-bucket-policy --bucket YOUR_BUCKET_NAME
Here's a verified working setup combining CloudFront and S3:
// CloudFront Distribution Origin Settings
{
"DomainName": "my-bucket.s3.amazonaws.com",
"S3OriginConfig": {
"OriginAccessIdentity": "origin-access-identity/cloudfront/E2ABCDEFGHIJK"
}
}
// Corresponding S3 Bucket Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2ABCDEFGHIJK"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
- Verify IAM permissions for the user configuring the setup
- Check if the S3 bucket has any conflicting public access blocks
- Ensure the OAI isn't deleted and recreated (which changes its ARN)
- Wait for CloudFront propagation (changes can take 10-15 minutes)
Before debugging CloudFront, verify your bucket policy works directly with S3:
aws s3 cp s3://my-bucket/testfile.txt - \
--request-payer requester \
--profile assumed-role-user
This eliminates CloudFront from the equation during initial troubleshooting.
When setting up Amazon CloudFront to distribute content from an S3 bucket, you might encounter an AccessDenied
error like this:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>89F25EB47DDA64D5</RequestId>
<HostId>Z2xAduhEswbdBqTB/cgCggm/jVG24dPZjy1GScs9ak0w95rF4I0SnDnJrUKHHQC</HostId>
</Error>
This typically happens due to misconfiguration in one of these areas:
- Origin Access Identity (OAI) not properly set up
- Incorrect S3 bucket policy
- Bucket permissions not allowing CloudFront access
- Missing or incorrect CORS configuration
1. Verify Your Origin Access Identity
First, ensure you've created an Origin Access Identity in CloudFront and associated it with your distribution:
// Example AWS CLI command to create OAI
aws cloudfront create-cloud-front-origin-access-identity \
--cloud-front-origin-access-identity-config \
CallerReference="unique-string",Comment="Access identity for S3 bucket"
2. Update Your S3 Bucket Policy
Your bucket policy should explicitly grant access to the CloudFront OAI. Here's a corrected version:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E1A2B3C4D5E6F7"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
3. Check Your CloudFront Distribution Settings
In your CloudFront distribution:
- Ensure "Restrict Bucket Access" is set to "Yes"
- Select the correct OAI from the dropdown
- Set "Grant Read Permissions on Bucket" to "Yes, Update Bucket Policy"
4. Verify Object Ownership
If you're using S3 buckets with ACLs disabled (recommended), ensure the bucket owner has full control:
aws s3api put-bucket-ownership-controls \
--bucket your-bucket-name \
--ownership-controls Rules=[{ObjectOwnership="BucketOwnerEnforced"}]
- Use AWS CLI to verify permissions:
aws s3api get-bucket-policy --bucket your-bucket-name
- Check CloudFront logs for detailed error information
- Clear CloudFront cache after making changes
- Test with a simple text file before moving to complex content
For more complex setups requiring CORS:
// Example CORS configuration for S3 bucket
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["https://your-cloudfront-domain.cloudfront.net"],
"ExposeHeaders": []
}
]