I'm using the Amazon S3 static website feature but getting an Access Denied error. Why is this happening?

Last updated: 2021-12-22

I'm using an Amazon Simple Storage Service (Amazon S3) bucket to host a static website with the S3 static website endpoint. Why I am getting an Access Denied error?

Short description

If you're trying to host a static website using Amazon S3, but you're getting an Access Denied error, check the following requirements:

  • Objects in the bucket must be publicly accessible.
  • S3 bucket policy must allow access to the s3:GetObject action.
  • The AWS account that owns the bucket must also own the object.
  • Objects can't be encrypted by AWS Key Management Service (AWS KMS).
  • Objects that are requested must exist in the S3 bucket.
  • Amazon S3 Block Public Access must be disabled on the bucket and account level.

Resolution

Objects in the bucket must be publicly accessible

S3 static website endpoint supports only publicly accessible content. To verify whether an object in your S3 bucket is publicly accessible, open the object's URL in a web browser. Or, you can run a cURL command on the URL.

The following is an example URL of an S3 object:

http://doc-example-bucket.s3-website-us-east-1.amazonaws.com/index.html
If an Access Denied error is returned by the web browser or cURL command, then the object isn't publicly accessible. To allow public read access to your S3 object, create a bucket policy that allows public read access for all objects in the bucket.

S3 bucket policy must allow access to the s3:GetObject action

Review your bucket policy, and make sure that there aren't any deny statements that block public read access to the s3:GetObject action. Even if you have an explicit allow statement for s3:GetObject in your bucket policy, confirm that there isn't a conflicting explicit deny statement. An explicit deny statement will always override an explicit allow statement.

To review your bucket policy for s3:GetObject, perform the following steps:

1.    Open the Amazon S3 console.

2.    Choose the Permissions tab.

3.    Choose Bucket Policy.

4.    Review the bucket policy for statements with "Action": "s3:GetObject" or "Action": "s3:*".

5.    (Optional) Modify the bucket policy. For example, you can remove or edit statements that block public read access to s3:GetObject.

The AWS account that owns the bucket must also own the object

To allow public read access to objects, the AWS account that owns the bucket must also own the objects. A bucket or object is owned by the account of the AWS Identity and Access Management (IAM) identity that created the bucket or object.

Note: The object-ownership requirement applies to public read access granted by a bucket policy. It doesn't apply to public read access granted by the object's access control list (ACL).

To check if your Amazon S3 bucket and objects are owned by the same AWS account, perform the following steps:

1.    To retrieve the S3 canonical ID of the bucket owner, use the following command:

aws s3api list-buckets --query Owner.ID

2.    To retrieve the S3 canonical ID of the object owner, use the following command:

aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html

Note: This example shows a single object. To check several objects, use the list command.

3.    Confirm whether the canonical IDs of the bucket owner and object owner match. If they don't match, then the bucket and object have different owners.

Note: You can also use the Amazon S3 console to check the bucket and object owners. The owners are found in the Permissions tab of the respective bucket or object.

4.    If the canonical IDs of the bucket and object owner don't match, change the object's owner to the bucket owner.

From the object owner's account, run the following command to retrieve the ACL permissions assigned to the object:

aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name

If the object doesn't have bucket-owner-full-control ACL permissions, then run the following command from the object owner's account:

aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name --acl bucket-owner-full-control

If the object has bucket-owner-full-control ACL permissions, run the following command from the bucket owner's account. This command changes the owner of the object by copying the object over itself:

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html --storage-class STANDARD

You can also use S3 Object Ownership to grant the bucket owner automatic ownership of any objects uploaded by anonymous users or other AWS accounts.

Objects in the bucket can't be AWS KMS-encrypted

AWS KMS doesn't support anonymous requests. As a result, any Amazon S3 bucket that allows anonymous or public access will not apply to objects that are encrypted with AWS KMS. You must remove KMS encryption from the objects that you want to serve using the Amazon S3 static website endpoint.

Note: Instead of using AWS KMS encryption, use AES-256 to encrypt your objects.

You can check if an object in your bucket is KMS encrypted using the following methods:

  • Use the Amazon S3 console to view the properties of the object. Review the Encryption dialog box. If AWS-KMS is selected, then the object is KMS-encrypted.
  • Run the head-object command using the AWS Command Line Interface (AWS CLI). If the command returns ServerSideEncryption as aws:kms, then the object is KMS-encrypted.

Note: If you receive errors when running AWS CLI commands, make sure that you’re using the most recent version of the AWS CLI.

To change the object's encryption settings using the Amazon S3 console, see Specifying Amazon S3 encryption.

To change the object's encryption settings using the AWS CLI, verify that the object's bucket doesn't have default encryption. If the bucket doesn't have default encryption, then remove the object's encryption by copying the object over itself:

 

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html --storage-class STANDARD
Warning: Copying the object over itself removes settings for storage-class and website-redirect-location. To maintain these settings in the new object, make sure to explicitly specify storage-class or website-redirect-location values in the copy request.

Objects that are requested must exist in the S3 bucket

If a user performing the request doesn’t have s3:ListBucket permissions, then the user gets an Access Denied error for missing objects.

You can run the head-object AWS CLI command to check if an object exists in the bucket.

Note: S3 object names are case-sensitive. If the request doesn't have a valid object name, then Amazon S3 will report that the object is missing.

If the object exists in the bucket, then the Access Denied error isn't masking a 404 Not Found error. Verify other configuration requirements to resolve the Access Denied error.

If the object doesn't exist in the bucket, then the Access Denied error is masking a 404 Not Found error. Resolve the issue related to the missing object.

Note: It's not a security best practice to enable public s3:ListBucket access. Enabling public s3:ListBucket access allows users to see and list all objects in a bucket. This access exposes object metadata details (for example, key and size) to users even if the users don't have permissions for downloading the object.

Amazon S3 Block Public Access must be disabled on the bucket

Amazon S3 Block Public Access settings can apply to individual buckets or AWS accounts. Confirm that there aren't any Amazon S3 Block Public Access settings applied to either your S3 bucket or AWS account. These settings can override permissions that allow public read access.


Did this article help?


Do you need billing or technical support?