Browse Source

validate grants when setting ownership to `OwnershipBucketOwnerEnforced`

Signed-off-by: changlin.shi <changlin.shi@ly.com>
pull/4090/head
changlin.shi 2 years ago
parent
commit
2227888acc
  1. 10
      weed/s3api/s3acl/acl_helper.go
  2. 17
      weed/s3api/s3acl/acl_helper_test.go
  3. 20
      weed/s3api/s3api_bucket_handlers.go
  4. 6
      weed/s3api/s3err/s3api_errors.go

10
weed/s3api/s3acl/acl_helper.go

@ -503,3 +503,13 @@ func GrantEquals(a, b *s3.Grant) bool {
} }
return true return true
} }
func GrantWithFullControl(accountId string) *s3.Grant {
return &s3.Grant{
Permission: &s3_constants.PermissionFullControl,
Grantee: &s3.Grantee{
Type: &s3_constants.GrantTypeCanonicalUser,
ID: &accountId,
},
}
}

17
weed/s3api/s3acl/acl_helper_test.go

@ -706,3 +706,20 @@ func TestSetAcpGrantsHeader(t *testing.T) {
t.Fatalf("owner unexpect") t.Fatalf("owner unexpect")
} }
} }
func TestGrantWithFullControl(t *testing.T) {
accountId := "Accountaskdfj"
expect := &s3.Grant{
Permission: &s3_constants.PermissionFullControl,
Grantee: &s3.Grantee{
Type: &s3_constants.GrantTypeCanonicalUser,
ID: &accountId,
},
}
result := GrantWithFullControl(accountId)
if !GrantEquals(result, expect) {
t.Fatal("GrantWithFullControl not expect")
}
}

20
weed/s3api/s3api_bucket_handlers.go

@ -6,6 +6,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3account"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3acl"
"github.com/seaweedfs/seaweedfs/weed/util" "github.com/seaweedfs/seaweedfs/weed/util"
"math" "math"
"net/http" "net/http"
@ -400,6 +402,24 @@ func (s3a *S3ApiServer) PutBucketOwnershipControls(w http.ResponseWriter, r *htt
oldOwnership, ok := bucketEntry.Extended[s3_constants.ExtOwnershipKey] oldOwnership, ok := bucketEntry.Extended[s3_constants.ExtOwnershipKey]
if !ok || string(oldOwnership) != ownership { if !ok || string(oldOwnership) != ownership {
// must reset bucket acl to default(bucket owner with full control permission) before setting ownership
// to `OwnershipBucketOwnerEnforced` (bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting)
if ownership == s3_constants.OwnershipBucketOwnerEnforced {
acpGrants := s3acl.GetAcpGrants(bucketEntry.Extended)
if len(acpGrants) != 1 {
s3err.WriteErrorResponse(w, r, s3err.InvalidBucketAclWithObjectOwnership)
return
}
bucketOwner := s3acl.GetAcpOwner(bucketEntry.Extended, s3account.AccountAdmin.Id)
expectGrant := s3acl.GrantWithFullControl(bucketOwner)
if s3acl.GrantEquals(acpGrants[0], expectGrant) {
s3err.WriteErrorResponse(w, r, s3err.InvalidBucketAclWithObjectOwnership)
return
}
}
if bucketEntry.Extended == nil { if bucketEntry.Extended == nil {
bucketEntry.Extended = make(map[string][]byte) bucketEntry.Extended = make(map[string][]byte)
} }

6
weed/s3api/s3err/s3api_errors.go

@ -109,6 +109,7 @@ const (
ErrRequestBytesExceed ErrRequestBytesExceed
OwnershipControlsNotFoundError OwnershipControlsNotFoundError
InvalidBucketAclWithObjectOwnership
) )
// error code to APIError structure, these fields carry respective // error code to APIError structure, these fields carry respective
@ -422,6 +423,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "The bucket ownership controls were not found", Description: "The bucket ownership controls were not found",
HTTPStatusCode: http.StatusNotFound, HTTPStatusCode: http.StatusNotFound,
}, },
InvalidBucketAclWithObjectOwnership: {
Code: "InvalidBucketAclWithObjectOwnership",
Description: "Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting",
HTTPStatusCode: http.StatusNotFound,
},
} }
// GetAPIError provides API Error for input API error code. // GetAPIError provides API Error for input API error code.

Loading…
Cancel
Save