Question

AWS S3: Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting)

On my website, all of a sudden I cannot upload photos. I get the following error:

##### RightAws::S3Interface returned an error: 400 Bad Request
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidBucketAclWithObjectOwnership</Code><Message>Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting</Message><RequestId>REQUEST</RequestId><HostId>ID$
##### RightAws::S3Interface request: https://bucket.s3.amazonaws.com:443/ ####

RightAws::AwsError (InvalidBucketAclWithObjectOwnership: Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting):

What's odd, is nothing has been changed on my end, when this used to work. AWS did send out this email, which seems related but was only supposed to apply to new buckets:

Hello,

We are reaching out to inform you that starting in April 2023 Amazon S3 will change the default security configuration for all new S3 buckets. For new buckets created after this date, S3 Block Public Access will be enabled, and S3 access control lists (ACLs) will be disabled.

The majority of S3 use cases do not need public access or ACLs. For most customers, no action is required. If you have use cases for public bucket access or the use of ACLs, you can disable Block Public Access or enable ACLs after you create an S3 bucket. In these cases, you may need to update automation scripts, CloudFormation templates, or other infrastructure configuration tools to configure these settings. To learn more, read the AWS News blog [1] and What's New announcement [2] on this change or visit our user guide for S3 Block Public Access [3] and S3 Object Ownership to disable ACLs [4]. Also, see our user guide for AWS CloudFormation on these settings [5][6].

I have seen similar issues, where people fixed it by using Edit Object Ownership to set Object Ownership to ACLs disabled (recommended). When I try this I get this error:

Bucket owner enforced cannot be applied because you have existing bucket ACLs If you want to apply the bucket owner enforced setting, you must remove access granted to other AWS accounts or groups from your bucket ACL and migrate these permissions to a bucket policy

I'm not sure how to get past this. I've seen people update the Bucket Policy, but mine is currently blank. I'm fairly new to AWS so I'm being careful not to mess with too much I don't understand.

This bucket should be public. This is the current ACL settings:
acls

I attempted to move over to using a Bucket Policy. I set my bucket policy as follows:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1380877761162",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/*"
        }
    ]
}

I removed the Bucket ACLs to put them back to the defaults.
removed

And I edited Object Ownership:
objectownership

And still I get the same error, which is particularly confusing because if I understand correctly, it now should not be using ACLs at all.

 46  53603  46
1 Jan 1970

Solution

 39

TLDR To create a bucket nowadays (alternative to acl public-read option):

#!/bin/bash

bucket_name="my-unique-name"
aws s3api create-bucket --bucket "${bucket_name}" > /dev/null # 1
aws s3api put-public-access-block --bucket "${bucket_name}" --public-access-block-configuration "BlockPublicPolicy=false" # 2
aws s3api put-bucket-policy --bucket "${bucket_name}" --policy '{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::'"${bucket_name}"'/*"
 
            ]
        }
    ]
}' # 3

What changed?

1 - Since 25.04.2023 Amazon changed default settings for newly created buckets. The ACL on buckets was considered as wrong practice (here is some nice post about that). To discourage using them the option BucketOwnerEnforced started to be the default one.

BucketOwnerEnforced - Access control lists (ACLs) are disabled and no longer affect permissions. The bucket owner automatically owns and has full control over every object in the bucket. The bucket only accepts PUT requests that don't specify an ACL or bucket owner full control ACLs, such as the bucket-owner-full-control canned ACL or an equivalent form of this ACL expressed in the XML format.

$ aws s3api get-bucket-ownership-controls --bucket "${bucket_name}"

{
    "OwnershipControls": {
        "Rules": [
            {
                "ObjectOwnership": "BucketOwnerEnforced"
            }
        ]
    }
}

2 - Without BlockPublicPolicy we won't be able to set public access to the bucket. In case of acl authenticated-read (not 100% sure thought) make sure RestrictPublicBuckets is set to false as well.

3 - For public or write acl, policy needs to be changed accordingly (PutObject)

Of course nothing stops you for using ACL, what you need to do is set BucketOwnerPreferred or ObjectWriter for your bucket.

$ aws s3api put-bucket-ownership-controls --bucket "${bucket_name}" --ownership-controls="Rules=[{ObjectOwnership=BucketOwnerPreferred}]"
$ aws s3api put-bucket-acl --bucket "${bucket_name}" --acl public-read
2023-04-25

Solution

 39

TLDR To create a bucket nowadays (alternative to acl public-read option):

#!/bin/bash

bucket_name="my-unique-name"
aws s3api create-bucket --bucket "${bucket_name}" > /dev/null # 1
aws s3api put-public-access-block --bucket "${bucket_name}" --public-access-block-configuration "BlockPublicPolicy=false" # 2
aws s3api put-bucket-policy --bucket "${bucket_name}" --policy '{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::'"${bucket_name}"'/*"
 
            ]
        }
    ]
}' # 3

What changed?

1 - Since 25.04.2023 Amazon changed default settings for newly created buckets. The ACL on buckets was considered as wrong practice (here is some nice post about that). To discourage using them the option BucketOwnerEnforced started to be the default one.

BucketOwnerEnforced - Access control lists (ACLs) are disabled and no longer affect permissions. The bucket owner automatically owns and has full control over every object in the bucket. The bucket only accepts PUT requests that don't specify an ACL or bucket owner full control ACLs, such as the bucket-owner-full-control canned ACL or an equivalent form of this ACL expressed in the XML format.

$ aws s3api get-bucket-ownership-controls --bucket "${bucket_name}"

{
    "OwnershipControls": {
        "Rules": [
            {
                "ObjectOwnership": "BucketOwnerEnforced"
            }
        ]
    }
}

2 - Without BlockPublicPolicy we won't be able to set public access to the bucket. In case of acl authenticated-read (not 100% sure thought) make sure RestrictPublicBuckets is set to false as well.

3 - For public or write acl, policy needs to be changed accordingly (PutObject)

Of course nothing stops you for using ACL, what you need to do is set BucketOwnerPreferred or ObjectWriter for your bucket.

$ aws s3api put-bucket-ownership-controls --bucket "${bucket_name}" --ownership-controls="Rules=[{ObjectOwnership=BucketOwnerPreferred}]"
$ aws s3api put-bucket-acl --bucket "${bucket_name}" --acl public-read
2023-04-25

Solution

 29

I have a similar issue. Based on previous answers on that question I did these changes :

resources:
  Resources:
    TasksAPIBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.bucketName}
        ### No more AccessControl
        # AccessControl: PublicRead
        ###  replace it with...
        PublicAccessBlockConfiguration:
          BlockPublicAcls: false
        OwnershipControls:
          Rules:
            - ObjectOwnership: ObjectWriter
        ###
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html

See the AWS::S3::Bucket PublicAccessBlockConfiguration and OwnershipControls for more details.

2023-04-27

Solution

 29

I have a similar issue. Based on previous answers on that question I did these changes :

resources:
  Resources:
    TasksAPIBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.bucketName}
        ### No more AccessControl
        # AccessControl: PublicRead
        ###  replace it with...
        PublicAccessBlockConfiguration:
          BlockPublicAcls: false
        OwnershipControls:
          Rules:
            - ObjectOwnership: ObjectWriter
        ###
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html

See the AWS::S3::Bucket PublicAccessBlockConfiguration and OwnershipControls for more details.

2023-04-27