fix: drop the owner's FULL_CONTROL grant when grant headers set the bucket ACL

CreateBucket and PutBucketAcl with x-amz-grant-* headers stored the
requested grants plus a FULL_CONTROL grant for the bucket owner, so
GetBucketAcl returned a grant AWS doesn't. On AWS the headers replace the
whole ACL and the owner gets FULL_CONTROL only when a header names it.

UpdateACL now keeps just the header grants when there are any. A canned
ACL and a bucket created without grants still get the owner's FULL_CONTROL
grant. The owner keeps full access either way, since aclAllows lets the
bucket owner perform any action regardless of grants.

Fixes #1407
This commit is contained in:
dualfroz committed 2026-10-14 19:40:59 +02:00
1 parent 3fee7f49c9
commit 0e3045b87f
5 files changed
+142 -41

No files matched your search

-7
View File
@@ -212,13 +212,6 @@ func CreateBucket_non_default_acl(s *S3Conf) error {
}
grants := []types.Grant{
{
Grantee: &types.Grantee{
ID: &s.awsID,
Type: types.TypeCanonicalUser,
},
Permission: types.PermissionFullControl,
},
{
Grantee: &types.Grantee{
ID: &testuser1.access,
+10 -27
View File
@@ -328,38 +328,21 @@ func IAM_CreateBucket_success(s *S3Conf) error {
return err
}
if len(acl.Grants) != 2 {
return fmt.Errorf("expected the length of acl grants to be 2, instead got %v", len(acl.Grants))
if getString(acl.Owner.ID) != testUser1.access {
return fmt.Errorf("expected the bucket owner to be %v, instead got %v", testUser1.access, getString(acl.Owner.ID))
}
var granteeChecked bool
var ownerChecked bool
for _, grant := range acl.Grants {
// owner
if getString(grant.Grantee.ID) == testUser1.access {
ownerChecked = true
if grant.Permission != types.PermissionFullControl {
return fmt.Errorf("expected the owner '%s' to have %s permission, instead got %s", testUser1.access, types.PermissionFullControl, grant.Permission)
}
continue
}
if getString(grant.Grantee.ID) != testUser2.access {
return fmt.Errorf("expected the grantee ID to be %v, instaed got %v", testUser2.access, getString(grant.Grantee.ID))
}
if grant.Permission != types.PermissionRead {
return fmt.Errorf("expected the %v user permission to be %s, instead got %s", testUser2.access, types.PermissionRead, grant.Permission)
}
granteeChecked = true
// the grant header replaces the acl, so the owner gets no FULL_CONTROL grant
if len(acl.Grants) != 1 {
return fmt.Errorf("expected the length of acl grants to be 1, instead got %v", len(acl.Grants))
}
if !ownerChecked {
return fmt.Errorf("missing the owner '%s' full control acl", testUser1.access)
grant := acl.Grants[0]
if getString(grant.Grantee.ID) != testUser2.access {
return fmt.Errorf("expected the grantee ID to be %v, instaed got %v", testUser2.access, getString(grant.Grantee.ID))
}
if !granteeChecked {
return fmt.Errorf("missing the user %s in read grantees acl", testUser2.access)
if grant.Permission != types.PermissionRead {
return fmt.Errorf("expected the %v user permission to be %s, instead got %s", testUser2.access, types.PermissionRead, grant.Permission)
}
return teardown(s, bucket)