feat: Implement bucket ownership controls

Bucket ACLs are now disabled by default the same as AWS.
By default the object ownership is BucketOwnerEnforced
which means that bucket ACLs are disabled. If one attempts
to set bucket ACL the following error is returned both in
the gateway and on AWS:
	ErrAclNotSupported: {
		Code:           "AccessControlListNotSupported",
		Description:    "The bucket does not allow ACLs",
		HTTPStatusCode: http.StatusBadRequest,
	},

ACls can be enabled with PutBucketOwnershipControls

Changed bucket canned ACL translation

New backend interface methods:
PutBucketOwnershipControls
GetBucketOwnershipControls
DeleteBucketOwnershipControls

Added these to metrics
This commit is contained in:
jonaustin09
2024-06-28 13:11:46 -04:00
committed by Ben McClelland
parent 2db2481f04
commit 7545e6236c
19 changed files with 1356 additions and 202 deletions
+52 -52
View File
@@ -28,7 +28,6 @@ import (
) )
type ACL struct { type ACL struct {
ACL types.BucketCannedACL
Owner string Owner string
Grantees []Grantee Grantees []Grantee
} }
@@ -94,12 +93,34 @@ func UpdateACL(input *s3.PutBucketAclInput, acl ACL, iam IAMService) ([]byte, er
return nil, s3err.GetAPIError(s3err.ErrAccessDenied) return nil, s3err.GetAPIError(s3err.ErrAccessDenied)
} }
defaultGrantees := []Grantee{
{
Permission: types.PermissionFullControl,
Access: acl.Owner,
},
}
// if the ACL is specified, set the ACL, else replace the grantees // if the ACL is specified, set the ACL, else replace the grantees
if input.ACL != "" { if input.ACL != "" {
acl.ACL = input.ACL switch input.ACL {
acl.Grantees = []Grantee{} case types.BucketCannedACLPublicRead:
defaultGrantees = append(defaultGrantees, Grantee{
Permission: types.PermissionRead,
Access: "all-users",
})
case types.BucketCannedACLPublicReadWrite:
defaultGrantees = append(defaultGrantees, []Grantee{
{
Permission: types.PermissionRead,
Access: "all-users",
},
{
Permission: types.PermissionWrite,
Access: "all-users",
},
}...)
}
} else { } else {
grantees := []Grantee{}
accs := []string{} accs := []string{}
if input.GrantRead != nil || input.GrantReadACP != nil || input.GrantFullControl != nil || input.GrantWrite != nil || input.GrantWriteACP != nil { if input.GrantRead != nil || input.GrantReadACP != nil || input.GrantFullControl != nil || input.GrantWrite != nil || input.GrantWriteACP != nil {
@@ -108,31 +129,31 @@ func UpdateACL(input *s3.PutBucketAclInput, acl ACL, iam IAMService) ([]byte, er
if input.GrantFullControl != nil && *input.GrantFullControl != "" { if input.GrantFullControl != nil && *input.GrantFullControl != "" {
fullControlList = splitUnique(*input.GrantFullControl, ",") fullControlList = splitUnique(*input.GrantFullControl, ",")
for _, str := range fullControlList { for _, str := range fullControlList {
grantees = append(grantees, Grantee{Access: str, Permission: "FULL_CONTROL"}) defaultGrantees = append(defaultGrantees, Grantee{Access: str, Permission: "FULL_CONTROL"})
} }
} }
if input.GrantRead != nil && *input.GrantRead != "" { if input.GrantRead != nil && *input.GrantRead != "" {
readList = splitUnique(*input.GrantRead, ",") readList = splitUnique(*input.GrantRead, ",")
for _, str := range readList { for _, str := range readList {
grantees = append(grantees, Grantee{Access: str, Permission: "READ"}) defaultGrantees = append(defaultGrantees, Grantee{Access: str, Permission: "READ"})
} }
} }
if input.GrantReadACP != nil && *input.GrantReadACP != "" { if input.GrantReadACP != nil && *input.GrantReadACP != "" {
readACPList = splitUnique(*input.GrantReadACP, ",") readACPList = splitUnique(*input.GrantReadACP, ",")
for _, str := range readACPList { for _, str := range readACPList {
grantees = append(grantees, Grantee{Access: str, Permission: "READ_ACP"}) defaultGrantees = append(defaultGrantees, Grantee{Access: str, Permission: "READ_ACP"})
} }
} }
if input.GrantWrite != nil && *input.GrantWrite != "" { if input.GrantWrite != nil && *input.GrantWrite != "" {
writeList = splitUnique(*input.GrantWrite, ",") writeList = splitUnique(*input.GrantWrite, ",")
for _, str := range writeList { for _, str := range writeList {
grantees = append(grantees, Grantee{Access: str, Permission: "WRITE"}) defaultGrantees = append(defaultGrantees, Grantee{Access: str, Permission: "WRITE"})
} }
} }
if input.GrantWriteACP != nil && *input.GrantWriteACP != "" { if input.GrantWriteACP != nil && *input.GrantWriteACP != "" {
writeACPList = splitUnique(*input.GrantWriteACP, ",") writeACPList = splitUnique(*input.GrantWriteACP, ",")
for _, str := range writeACPList { for _, str := range writeACPList {
grantees = append(grantees, Grantee{Access: str, Permission: "WRITE_ACP"}) defaultGrantees = append(defaultGrantees, Grantee{Access: str, Permission: "WRITE_ACP"})
} }
} }
@@ -143,7 +164,7 @@ func UpdateACL(input *s3.PutBucketAclInput, acl ACL, iam IAMService) ([]byte, er
if grt.Grantee == nil || grt.Grantee.ID == nil || grt.Permission == "" { if grt.Grantee == nil || grt.Grantee.ID == nil || grt.Permission == "" {
return nil, s3err.GetAPIError(s3err.ErrInvalidRequest) return nil, s3err.GetAPIError(s3err.ErrInvalidRequest)
} }
grantees = append(grantees, Grantee{Access: *grt.Grantee.ID, Permission: grt.Permission}) defaultGrantees = append(defaultGrantees, Grantee{Access: *grt.Grantee.ID, Permission: grt.Permission})
if _, ok := cache[*grt.Grantee.ID]; !ok { if _, ok := cache[*grt.Grantee.ID]; !ok {
cache[*grt.Grantee.ID] = true cache[*grt.Grantee.ID] = true
accs = append(accs, *grt.Grantee.ID) accs = append(accs, *grt.Grantee.ID)
@@ -159,11 +180,10 @@ func UpdateACL(input *s3.PutBucketAclInput, acl ACL, iam IAMService) ([]byte, er
if len(accList) > 0 { if len(accList) > 0 {
return nil, fmt.Errorf("accounts does not exist: %s", strings.Join(accList, ", ")) return nil, fmt.Errorf("accounts does not exist: %s", strings.Join(accList, ", "))
} }
acl.Grantees = grantees
acl.ACL = ""
} }
acl.Grantees = defaultGrantees
result, err := json.Marshal(acl) result, err := json.Marshal(acl)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -207,34 +227,21 @@ func splitUnique(s, divider string) []string {
} }
func verifyACL(acl ACL, access string, permission types.Permission) error { func verifyACL(acl ACL, access string, permission types.Permission) error {
if acl.ACL != "" { grantee := Grantee{Access: access, Permission: permission}
if (permission == "READ" || permission == "READ_ACP") && (acl.ACL != "public-read" && acl.ACL != "public-read-write") { granteeFullCtrl := Grantee{Access: access, Permission: "FULL_CONTROL"}
return s3err.GetAPIError(s3err.ErrAccessDenied) granteeAllUsers := Grantee{Access: "all-users", Permission: permission}
}
if (permission == "WRITE" || permission == "WRITE_ACP") && acl.ACL != "public-read-write" {
return s3err.GetAPIError(s3err.ErrAccessDenied)
}
isFound := false
for _, grt := range acl.Grantees {
if grt == grantee || grt == granteeFullCtrl || grt == granteeAllUsers {
isFound = true
break
}
}
if isFound {
return nil return nil
} else {
if len(acl.Grantees) == 0 {
return nil
}
grantee := Grantee{Access: access, Permission: permission}
granteeFullCtrl := Grantee{Access: access, Permission: "FULL_CONTROL"}
isFound := false
for _, grt := range acl.Grantees {
if grt == grantee || grt == granteeFullCtrl {
isFound = true
break
}
}
if isFound {
return nil
}
} }
return s3err.GetAPIError(s3err.ErrAccessDenied) return s3err.GetAPIError(s3err.ErrAccessDenied)
@@ -295,23 +302,16 @@ func VerifyAccess(ctx context.Context, be backend.Backend, opts AccessOptions) e
if opts.Acc.Role == RoleAdmin { if opts.Acc.Role == RoleAdmin {
return nil return nil
} }
if opts.Acc.Access == opts.Acl.Owner {
return nil
}
policy, policyErr := be.GetBucketPolicy(ctx, opts.Bucket) policy, policyErr := be.GetBucketPolicy(ctx, opts.Bucket)
if policyErr != nil && !errors.Is(policyErr, s3err.GetAPIError(s3err.ErrNoSuchBucketPolicy)) { if policyErr != nil {
return policyErr if !errors.Is(policyErr, s3err.GetAPIError(s3err.ErrNoSuchBucketPolicy)) {
return policyErr
}
} else {
return VerifyBucketPolicy(policy, opts.Acc.Access, opts.Bucket, opts.Object, opts.Action)
} }
// If bucket policy is not set and the ACL is default, only the owner has access
if errors.Is(policyErr, s3err.GetAPIError(s3err.ErrNoSuchBucketPolicy)) && opts.Acl.ACL == "" && len(opts.Acl.Grantees) == 0 {
return s3err.GetAPIError(s3err.ErrAccessDenied)
}
if err := VerifyBucketPolicy(policy, opts.Acc.Access, opts.Bucket, opts.Object, opts.Action); err != nil {
return err
}
if err := verifyACL(opts.Acl, opts.Acc.Access, opts.AclPermission); err != nil { if err := verifyACL(opts.Acl, opts.Acc.Access, opts.AclPermission); err != nil {
return err return err
} }
-5
View File
@@ -134,11 +134,6 @@ func ValidatePolicyDocument(policyBin []byte, bucket string, iam IAMService) err
} }
func VerifyBucketPolicy(policy []byte, access, bucket, object string, action Action) error { func VerifyBucketPolicy(policy []byte, access, bucket, object string, action Action) error {
// If bucket policy is not set
if policy == nil {
return nil
}
var bucketPolicy BucketPolicy var bucketPolicy BucketPolicy
if err := json.Unmarshal(policy, &bucketPolicy); err != nil { if err := json.Unmarshal(policy, &bucketPolicy); err != nil {
return err return err
+4
View File
@@ -55,6 +55,8 @@ const (
GetObjectRetentionAction Action = "s3:GetObjectRetention" GetObjectRetentionAction Action = "s3:GetObjectRetention"
PutObjectRetentionAction Action = "s3:PutObjectRetention" PutObjectRetentionAction Action = "s3:PutObjectRetention"
BypassGovernanceRetentionAction Action = "s3:BypassGovernanceRetention" BypassGovernanceRetentionAction Action = "s3:BypassGovernanceRetention"
PutBucketOwnershipControlsAction Action = "s3:PutBucketOwnershipControls"
GetBucketOwnershipControlsAction Action = "s3:GetBucketOwnershipControls"
AllActions Action = "s3:*" AllActions Action = "s3:*"
) )
@@ -91,6 +93,8 @@ var supportedActionList = map[Action]struct{}{
GetObjectRetentionAction: {}, GetObjectRetentionAction: {},
PutObjectRetentionAction: {}, PutObjectRetentionAction: {},
BypassGovernanceRetentionAction: {}, BypassGovernanceRetentionAction: {},
PutBucketOwnershipControlsAction: {},
GetBucketOwnershipControlsAction: {},
AllActions: {}, AllActions: {},
} }
+63
View File
@@ -53,6 +53,7 @@ type key string
const ( const (
keyAclCapital key = "Acl" keyAclCapital key = "Acl"
keyAclLower key = "acl" keyAclLower key = "acl"
keyOwnership key = "Ownership"
keyTags key = "Tags" keyTags key = "Tags"
keyPolicy key = "Policy" keyPolicy key = "Policy"
keyBucketLock key = "Bucket-Lock" keyBucketLock key = "Bucket-Lock"
@@ -127,6 +128,7 @@ func (az *Azure) String() string {
func (az *Azure) CreateBucket(ctx context.Context, input *s3.CreateBucketInput, acl []byte) error { func (az *Azure) CreateBucket(ctx context.Context, input *s3.CreateBucketInput, acl []byte) error {
meta := map[string]*string{ meta := map[string]*string{
string(keyAclCapital): backend.GetStringPtr(string(acl)), string(keyAclCapital): backend.GetStringPtr(string(acl)),
string(keyOwnership): backend.GetStringPtr(string(input.ObjectOwnership)),
} }
acct, ok := ctx.Value("account").(auth.Account) acct, ok := ctx.Value("account").(auth.Account)
@@ -251,6 +253,67 @@ func (az *Azure) DeleteBucket(ctx context.Context, input *s3.DeleteBucketInput)
return azureErrToS3Err(err) return azureErrToS3Err(err)
} }
func (az *Azure) PutBucketOwnershipControls(ctx context.Context, bucket string, ownership types.ObjectOwnership) error {
client, err := az.getContainerClient(bucket)
if err != nil {
return err
}
resp, err := client.GetProperties(ctx, &container.GetPropertiesOptions{})
if err != nil {
return azureErrToS3Err(err)
}
resp.Metadata[string(keyOwnership)] = backend.GetStringPtr(string(ownership))
_, err = client.SetMetadata(ctx, &container.SetMetadataOptions{Metadata: resp.Metadata})
if err != nil {
return azureErrToS3Err(err)
}
return nil
}
func (az *Azure) GetBucketOwnershipControls(ctx context.Context, bucket string) (types.ObjectOwnership, error) {
var ownship types.ObjectOwnership
client, err := az.getContainerClient(bucket)
if err != nil {
return ownship, err
}
resp, err := client.GetProperties(ctx, &container.GetPropertiesOptions{})
if err != nil {
return ownship, azureErrToS3Err(err)
}
ownership, ok := resp.Metadata[string(keyOwnership)]
if !ok {
return ownship, s3err.GetAPIError(s3err.ErrOwnershipControlsNotFound)
}
return types.ObjectOwnership(*ownership), nil
}
func (az *Azure) DeleteBucketOwnershipControls(ctx context.Context, bucket string) error {
client, err := az.getContainerClient(bucket)
if err != nil {
return err
}
resp, err := client.GetProperties(ctx, &container.GetPropertiesOptions{})
if err != nil {
return azureErrToS3Err(err)
}
delete(resp.Metadata, string(keyOwnership))
_, err = client.SetMetadata(ctx, &container.SetMetadataOptions{Metadata: resp.Metadata})
if err != nil {
return azureErrToS3Err(err)
}
return nil
}
func (az *Azure) PutObject(ctx context.Context, po *s3.PutObjectInput) (string, error) { func (az *Azure) PutObject(ctx context.Context, po *s3.PutObjectInput) (string, error) {
tags, err := parseTags(po.Tagging) tags, err := parseTags(po.Tagging)
if err != nil { if err != nil {
+13
View File
@@ -21,6 +21,7 @@ import (
"io" "io"
"github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/versity/versitygw/s3err" "github.com/versity/versitygw/s3err"
"github.com/versity/versitygw/s3response" "github.com/versity/versitygw/s3response"
"github.com/versity/versitygw/s3select" "github.com/versity/versitygw/s3select"
@@ -43,6 +44,9 @@ type Backend interface {
PutBucketPolicy(_ context.Context, bucket string, policy []byte) error PutBucketPolicy(_ context.Context, bucket string, policy []byte) error
GetBucketPolicy(_ context.Context, bucket string) ([]byte, error) GetBucketPolicy(_ context.Context, bucket string) ([]byte, error)
DeleteBucketPolicy(_ context.Context, bucket string) error DeleteBucketPolicy(_ context.Context, bucket string) error
PutBucketOwnershipControls(_ context.Context, bucket string, ownership types.ObjectOwnership) error
GetBucketOwnershipControls(_ context.Context, bucket string) (types.ObjectOwnership, error)
DeleteBucketOwnershipControls(_ context.Context, bucket string) error
// multipart operations // multipart operations
CreateMultipartUpload(context.Context, *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error) CreateMultipartUpload(context.Context, *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error)
@@ -138,6 +142,15 @@ func (BackendUnsupported) GetBucketPolicy(_ context.Context, bucket string) ([]b
func (BackendUnsupported) DeleteBucketPolicy(_ context.Context, bucket string) error { func (BackendUnsupported) DeleteBucketPolicy(_ context.Context, bucket string) error {
return s3err.GetAPIError(s3err.ErrNotImplemented) return s3err.GetAPIError(s3err.ErrNotImplemented)
} }
func (BackendUnsupported) PutBucketOwnershipControls(_ context.Context, bucket string, ownership types.ObjectOwnership) error {
return s3err.GetAPIError(s3err.ErrNotImplemented)
}
func (BackendUnsupported) GetBucketOwnershipControls(_ context.Context, bucket string) (types.ObjectOwnership, error) {
return types.ObjectOwnershipBucketOwnerEnforced, s3err.GetAPIError(s3err.ErrNotImplemented)
}
func (BackendUnsupported) DeleteBucketOwnershipControls(_ context.Context, bucket string) error {
return s3err.GetAPIError(s3err.ErrNotImplemented)
}
func (BackendUnsupported) CreateMultipartUpload(context.Context, *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error) { func (BackendUnsupported) CreateMultipartUpload(context.Context, *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error) {
return nil, s3err.GetAPIError(s3err.ErrNotImplemented) return nil, s3err.GetAPIError(s3err.ErrNotImplemented)
+59
View File
@@ -75,6 +75,7 @@ const (
contentEncHdr = "content-encoding" contentEncHdr = "content-encoding"
emptyMD5 = "d41d8cd98f00b204e9800998ecf8427e" emptyMD5 = "d41d8cd98f00b204e9800998ecf8427e"
aclkey = "acl" aclkey = "acl"
ownershipkey = "ownership"
etagkey = "etag" etagkey = "etag"
policykey = "policy" policykey = "policy"
bucketLockKey = "bucket-lock" bucketLockKey = "bucket-lock"
@@ -245,6 +246,9 @@ func (p *Posix) CreateBucket(ctx context.Context, input *s3.CreateBucketInput, a
if err := p.meta.StoreAttribute(bucket, "", aclkey, acl); err != nil { if err := p.meta.StoreAttribute(bucket, "", aclkey, acl); err != nil {
return fmt.Errorf("set acl: %w", err) return fmt.Errorf("set acl: %w", err)
} }
if err := p.meta.StoreAttribute(bucket, "", ownershipkey, []byte(input.ObjectOwnership)); err != nil {
return fmt.Errorf("set ownership: %w", err)
}
if input.ObjectLockEnabledForBucket != nil && *input.ObjectLockEnabledForBucket { if input.ObjectLockEnabledForBucket != nil && *input.ObjectLockEnabledForBucket {
now := time.Now() now := time.Now()
@@ -304,6 +308,61 @@ func (p *Posix) DeleteBucket(_ context.Context, input *s3.DeleteBucketInput) err
return nil return nil
} }
func (p *Posix) PutBucketOwnershipControls(_ context.Context, bucket string, ownership types.ObjectOwnership) error {
_, err := os.Stat(bucket)
if errors.Is(err, fs.ErrNotExist) {
return s3err.GetAPIError(s3err.ErrNoSuchBucket)
}
if err != nil {
return fmt.Errorf("stat bucket: %w", err)
}
if err := p.meta.StoreAttribute(bucket, "", ownershipkey, []byte(ownership)); err != nil {
return fmt.Errorf("set ownership: %w", err)
}
return nil
}
func (p *Posix) GetBucketOwnershipControls(_ context.Context, bucket string) (types.ObjectOwnership, error) {
var ownship types.ObjectOwnership
_, err := os.Stat(bucket)
if errors.Is(err, fs.ErrNotExist) {
return ownship, s3err.GetAPIError(s3err.ErrNoSuchBucket)
}
if err != nil {
return ownship, fmt.Errorf("stat bucket: %w", err)
}
ownership, err := p.meta.RetrieveAttribute(bucket, "", ownershipkey)
if errors.Is(err, meta.ErrNoSuchKey) {
return ownship, s3err.GetAPIError(s3err.ErrOwnershipControlsNotFound)
}
if err != nil {
return ownship, fmt.Errorf("get bucket ownership status: %w", err)
}
return types.ObjectOwnership(ownership), nil
}
func (p *Posix) DeleteBucketOwnershipControls(_ context.Context, bucket string) error {
_, err := os.Stat(bucket)
if errors.Is(err, fs.ErrNotExist) {
return s3err.GetAPIError(s3err.ErrNoSuchBucket)
}
if err != nil {
return fmt.Errorf("stat bucket: %w", err)
}
if err := p.meta.DeleteAttribute(bucket, "", ownershipkey); err != nil {
if errors.Is(err, meta.ErrNoSuchKey) {
return nil
}
return fmt.Errorf("delete ownership: %w", err)
}
return nil
}
func (p *Posix) CreateMultipartUpload(ctx context.Context, mpu *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error) { func (p *Posix) CreateMultipartUpload(ctx context.Context, mpu *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error) {
if mpu.Bucket == nil { if mpu.Bucket == nil {
return nil, s3err.GetAPIError(s3err.ErrInvalidBucketName) return nil, s3err.GetAPIError(s3err.ErrInvalidBucketName)
+33
View File
@@ -55,6 +55,8 @@ type S3Proxy struct {
debug bool debug bool
} }
var _ backend.Backend = &S3Proxy{}
func New(access, secret, endpoint, region string, disableChecksum, sslSkipVerify, debug bool) (*S3Proxy, error) { func New(access, secret, endpoint, region string, disableChecksum, sslSkipVerify, debug bool) (*S3Proxy, error) {
s := &S3Proxy{ s := &S3Proxy{
access: access, access: access,
@@ -128,6 +130,37 @@ func (s *S3Proxy) DeleteBucket(ctx context.Context, input *s3.DeleteBucketInput)
return handleError(err) return handleError(err)
} }
func (s *S3Proxy) PutBucketOwnershipControls(ctx context.Context, bucket string, ownership types.ObjectOwnership) error {
_, err := s.client.PutBucketOwnershipControls(ctx, &s3.PutBucketOwnershipControlsInput{
Bucket: &bucket,
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: ownership,
},
},
},
})
return handleError(err)
}
func (s *S3Proxy) GetBucketOwnershipControls(ctx context.Context, bucket string) (types.ObjectOwnership, error) {
var ownship types.ObjectOwnership
resp, err := s.client.GetBucketOwnershipControls(ctx, &s3.GetBucketOwnershipControlsInput{
Bucket: &bucket,
})
if err != nil {
return ownship, handleError(err)
}
return resp.OwnershipControls.Rules[0].ObjectOwnership, nil
}
func (s *S3Proxy) DeleteBucketOwnershipControls(ctx context.Context, bucket string) error {
_, err := s.client.DeleteBucketOwnershipControls(ctx, &s3.DeleteBucketOwnershipControlsInput{
Bucket: &bucket,
})
return handleError(err)
}
func (s *S3Proxy) CreateMultipartUpload(ctx context.Context, input *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error) { func (s *S3Proxy) CreateMultipartUpload(ctx context.Context, input *s3.CreateMultipartUploadInput) (*s3.CreateMultipartUploadOutput, error) {
out, err := s.client.CreateMultipartUpload(ctx, input) out, err := s.client.CreateMultipartUpload(ctx, input)
return out, handleError(err) return out, handleError(err)
+48 -45
View File
@@ -24,51 +24,54 @@ var (
) )
var ( var (
ActionUndetected = "ActionUnDetected" ActionUndetected = "ActionUnDetected"
ActionAbortMultipartUpload = "s3_AbortMultipartUpload" ActionAbortMultipartUpload = "s3_AbortMultipartUpload"
ActionCompleteMultipartUpload = "s3_CompleteMultipartUpload" ActionCompleteMultipartUpload = "s3_CompleteMultipartUpload"
ActionCopyObject = "s3_CopyObject" ActionCopyObject = "s3_CopyObject"
ActionCreateBucket = "s3_CreateBucket" ActionCreateBucket = "s3_CreateBucket"
ActionCreateMultipartUpload = "s3_CreateMultipartUpload" ActionCreateMultipartUpload = "s3_CreateMultipartUpload"
ActionDeleteBucket = "s3_DeleteBucket" ActionDeleteBucket = "s3_DeleteBucket"
ActionDeleteBucketPolicy = "s3_DeleteBucketPolicy" ActionDeleteBucketPolicy = "s3_DeleteBucketPolicy"
ActionDeleteBucketTagging = "s3_DeleteBucketTagging" ActionDeleteBucketTagging = "s3_DeleteBucketTagging"
ActionDeleteObject = "s3_DeleteObject" ActionDeleteObject = "s3_DeleteObject"
ActionDeleteObjectTagging = "s3_DeleteObjectTagging" ActionDeleteObjectTagging = "s3_DeleteObjectTagging"
ActionDeleteObjects = "s3_DeleteObjects" ActionDeleteObjects = "s3_DeleteObjects"
ActionGetBucketAcl = "s3_GetBucketAcl" ActionGetBucketAcl = "s3_GetBucketAcl"
ActionGetBucketPolicy = "s3_GetBucketPolicy" ActionGetBucketPolicy = "s3_GetBucketPolicy"
ActionGetBucketTagging = "s3_GetBucketTagging" ActionGetBucketTagging = "s3_GetBucketTagging"
ActionGetBucketVersioning = "s3_GetBucketVersioning" ActionGetBucketVersioning = "s3_GetBucketVersioning"
ActionGetObject = "s3_GetObject" ActionGetObject = "s3_GetObject"
ActionGetObjectAcl = "s3_GetObjectAcl" ActionGetObjectAcl = "s3_GetObjectAcl"
ActionGetObjectAttributes = "s3_GetObjectAttributes" ActionGetObjectAttributes = "s3_GetObjectAttributes"
ActionGetObjectLegalHold = "s3_GetObjectLegalHold" ActionGetObjectLegalHold = "s3_GetObjectLegalHold"
ActionGetObjectLockConfiguration = "s3_GetObjectLockConfiguration" ActionGetObjectLockConfiguration = "s3_GetObjectLockConfiguration"
ActionGetObjectRetention = "s3_GetObjectRetention" ActionGetObjectRetention = "s3_GetObjectRetention"
ActionGetObjectTagging = "s3_GetObjectTagging" ActionGetObjectTagging = "s3_GetObjectTagging"
ActionHeadBucket = "s3_HeadBucket" ActionHeadBucket = "s3_HeadBucket"
ActionHeadObject = "s3_HeadObject" ActionHeadObject = "s3_HeadObject"
ActionListAllMyBuckets = "s3_ListAllMyBuckets" ActionListAllMyBuckets = "s3_ListAllMyBuckets"
ActionListMultipartUploads = "s3_ListMultipartUploads" ActionListMultipartUploads = "s3_ListMultipartUploads"
ActionListObjectVersions = "s3_ListObjectVersions" ActionListObjectVersions = "s3_ListObjectVersions"
ActionListObjects = "s3_ListObjects" ActionListObjects = "s3_ListObjects"
ActionListObjectsV2 = "s3_ListObjectsV2" ActionListObjectsV2 = "s3_ListObjectsV2"
ActionListParts = "s3_ListParts" ActionListParts = "s3_ListParts"
ActionPutBucketAcl = "s3_PutBucketAcl" ActionPutBucketAcl = "s3_PutBucketAcl"
ActionPutBucketPolicy = "s3_PutBucketPolicy" ActionPutBucketPolicy = "s3_PutBucketPolicy"
ActionPutBucketTagging = "s3_PutBucketTagging" ActionPutBucketTagging = "s3_PutBucketTagging"
ActionPutBucketVersioning = "s3_PutBucketVersioning" ActionPutBucketVersioning = "s3_PutBucketVersioning"
ActionPutObject = "s3_PutObject" ActionPutObject = "s3_PutObject"
ActionPutObjectAcl = "s3_PutObjectAcl" ActionPutObjectAcl = "s3_PutObjectAcl"
ActionPutObjectLegalHold = "s3_PutObjectLegalHold" ActionPutObjectLegalHold = "s3_PutObjectLegalHold"
ActionPutObjectLockConfiguration = "s3_PutObjectLockConfiguration" ActionPutObjectLockConfiguration = "s3_PutObjectLockConfiguration"
ActionPutObjectRetention = "s3_PutObjectRetention" ActionPutObjectRetention = "s3_PutObjectRetention"
ActionPutObjectTagging = "s3_PutObjectTagging" ActionPutObjectTagging = "s3_PutObjectTagging"
ActionRestoreObject = "s3_RestoreObject" ActionRestoreObject = "s3_RestoreObject"
ActionSelectObjectContent = "s3_SelectObjectContent" ActionSelectObjectContent = "s3_SelectObjectContent"
ActionUploadPart = "s3_UploadPart" ActionUploadPart = "s3_UploadPart"
ActionUploadPartCopy = "s3_UploadPartCopy" ActionUploadPartCopy = "s3_UploadPartCopy"
ActionPutBucketOwnershipControls = "s3_PutBucketOwnershipControls"
ActionGetBucketOwnershipControls = "s3_GetBucketOwnershipControls"
ActionDeleteBucketOwnershipControls = "s3_DeleteBucketOwnershipControls"
) )
func init() { func init() {
+205 -48
View File
@@ -7,6 +7,7 @@ import (
"bufio" "bufio"
"context" "context"
"github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/versity/versitygw/backend" "github.com/versity/versitygw/backend"
"github.com/versity/versitygw/s3response" "github.com/versity/versitygw/s3response"
"io" "io"
@@ -44,6 +45,9 @@ var _ backend.Backend = &BackendMock{}
// DeleteBucketFunc: func(contextMoqParam context.Context, deleteBucketInput *s3.DeleteBucketInput) error { // DeleteBucketFunc: func(contextMoqParam context.Context, deleteBucketInput *s3.DeleteBucketInput) error {
// panic("mock out the DeleteBucket method") // panic("mock out the DeleteBucket method")
// }, // },
// DeleteBucketOwnershipControlsFunc: func(contextMoqParam context.Context, bucket string) error {
// panic("mock out the DeleteBucketOwnershipControls method")
// },
// DeleteBucketPolicyFunc: func(contextMoqParam context.Context, bucket string) error { // DeleteBucketPolicyFunc: func(contextMoqParam context.Context, bucket string) error {
// panic("mock out the DeleteBucketPolicy method") // panic("mock out the DeleteBucketPolicy method")
// }, // },
@@ -62,6 +66,9 @@ var _ backend.Backend = &BackendMock{}
// GetBucketAclFunc: func(contextMoqParam context.Context, getBucketAclInput *s3.GetBucketAclInput) ([]byte, error) { // GetBucketAclFunc: func(contextMoqParam context.Context, getBucketAclInput *s3.GetBucketAclInput) ([]byte, error) {
// panic("mock out the GetBucketAcl method") // panic("mock out the GetBucketAcl method")
// }, // },
// GetBucketOwnershipControlsFunc: func(contextMoqParam context.Context, bucket string) (types.ObjectOwnership, error) {
// panic("mock out the GetBucketOwnershipControls method")
// },
// GetBucketPolicyFunc: func(contextMoqParam context.Context, bucket string) ([]byte, error) { // GetBucketPolicyFunc: func(contextMoqParam context.Context, bucket string) ([]byte, error) {
// panic("mock out the GetBucketPolicy method") // panic("mock out the GetBucketPolicy method")
// }, // },
@@ -122,6 +129,9 @@ var _ backend.Backend = &BackendMock{}
// PutBucketAclFunc: func(contextMoqParam context.Context, bucket string, data []byte) error { // PutBucketAclFunc: func(contextMoqParam context.Context, bucket string, data []byte) error {
// panic("mock out the PutBucketAcl method") // panic("mock out the PutBucketAcl method")
// }, // },
// PutBucketOwnershipControlsFunc: func(contextMoqParam context.Context, bucket string, ownership types.ObjectOwnership) error {
// panic("mock out the PutBucketOwnershipControls method")
// },
// PutBucketPolicyFunc: func(contextMoqParam context.Context, bucket string, policy []byte) error { // PutBucketPolicyFunc: func(contextMoqParam context.Context, bucket string, policy []byte) error {
// panic("mock out the PutBucketPolicy method") // panic("mock out the PutBucketPolicy method")
// }, // },
@@ -195,6 +205,9 @@ type BackendMock struct {
// DeleteBucketFunc mocks the DeleteBucket method. // DeleteBucketFunc mocks the DeleteBucket method.
DeleteBucketFunc func(contextMoqParam context.Context, deleteBucketInput *s3.DeleteBucketInput) error DeleteBucketFunc func(contextMoqParam context.Context, deleteBucketInput *s3.DeleteBucketInput) error
// DeleteBucketOwnershipControlsFunc mocks the DeleteBucketOwnershipControls method.
DeleteBucketOwnershipControlsFunc func(contextMoqParam context.Context, bucket string) error
// DeleteBucketPolicyFunc mocks the DeleteBucketPolicy method. // DeleteBucketPolicyFunc mocks the DeleteBucketPolicy method.
DeleteBucketPolicyFunc func(contextMoqParam context.Context, bucket string) error DeleteBucketPolicyFunc func(contextMoqParam context.Context, bucket string) error
@@ -213,6 +226,9 @@ type BackendMock struct {
// GetBucketAclFunc mocks the GetBucketAcl method. // GetBucketAclFunc mocks the GetBucketAcl method.
GetBucketAclFunc func(contextMoqParam context.Context, getBucketAclInput *s3.GetBucketAclInput) ([]byte, error) GetBucketAclFunc func(contextMoqParam context.Context, getBucketAclInput *s3.GetBucketAclInput) ([]byte, error)
// GetBucketOwnershipControlsFunc mocks the GetBucketOwnershipControls method.
GetBucketOwnershipControlsFunc func(contextMoqParam context.Context, bucket string) (types.ObjectOwnership, error)
// GetBucketPolicyFunc mocks the GetBucketPolicy method. // GetBucketPolicyFunc mocks the GetBucketPolicy method.
GetBucketPolicyFunc func(contextMoqParam context.Context, bucket string) ([]byte, error) GetBucketPolicyFunc func(contextMoqParam context.Context, bucket string) ([]byte, error)
@@ -273,6 +289,9 @@ type BackendMock struct {
// PutBucketAclFunc mocks the PutBucketAcl method. // PutBucketAclFunc mocks the PutBucketAcl method.
PutBucketAclFunc func(contextMoqParam context.Context, bucket string, data []byte) error PutBucketAclFunc func(contextMoqParam context.Context, bucket string, data []byte) error
// PutBucketOwnershipControlsFunc mocks the PutBucketOwnershipControls method.
PutBucketOwnershipControlsFunc func(contextMoqParam context.Context, bucket string, ownership types.ObjectOwnership) error
// PutBucketPolicyFunc mocks the PutBucketPolicy method. // PutBucketPolicyFunc mocks the PutBucketPolicy method.
PutBucketPolicyFunc func(contextMoqParam context.Context, bucket string, policy []byte) error PutBucketPolicyFunc func(contextMoqParam context.Context, bucket string, policy []byte) error
@@ -373,6 +392,13 @@ type BackendMock struct {
// DeleteBucketInput is the deleteBucketInput argument value. // DeleteBucketInput is the deleteBucketInput argument value.
DeleteBucketInput *s3.DeleteBucketInput DeleteBucketInput *s3.DeleteBucketInput
} }
// DeleteBucketOwnershipControls holds details about calls to the DeleteBucketOwnershipControls method.
DeleteBucketOwnershipControls []struct {
// ContextMoqParam is the contextMoqParam argument value.
ContextMoqParam context.Context
// Bucket is the bucket argument value.
Bucket string
}
// DeleteBucketPolicy holds details about calls to the DeleteBucketPolicy method. // DeleteBucketPolicy holds details about calls to the DeleteBucketPolicy method.
DeleteBucketPolicy []struct { DeleteBucketPolicy []struct {
// ContextMoqParam is the contextMoqParam argument value. // ContextMoqParam is the contextMoqParam argument value.
@@ -417,6 +443,13 @@ type BackendMock struct {
// GetBucketAclInput is the getBucketAclInput argument value. // GetBucketAclInput is the getBucketAclInput argument value.
GetBucketAclInput *s3.GetBucketAclInput GetBucketAclInput *s3.GetBucketAclInput
} }
// GetBucketOwnershipControls holds details about calls to the GetBucketOwnershipControls method.
GetBucketOwnershipControls []struct {
// ContextMoqParam is the contextMoqParam argument value.
ContextMoqParam context.Context
// Bucket is the bucket argument value.
Bucket string
}
// GetBucketPolicy holds details about calls to the GetBucketPolicy method. // GetBucketPolicy holds details about calls to the GetBucketPolicy method.
GetBucketPolicy []struct { GetBucketPolicy []struct {
// ContextMoqParam is the contextMoqParam argument value. // ContextMoqParam is the contextMoqParam argument value.
@@ -571,6 +604,15 @@ type BackendMock struct {
// Data is the data argument value. // Data is the data argument value.
Data []byte Data []byte
} }
// PutBucketOwnershipControls holds details about calls to the PutBucketOwnershipControls method.
PutBucketOwnershipControls []struct {
// ContextMoqParam is the contextMoqParam argument value.
ContextMoqParam context.Context
// Bucket is the bucket argument value.
Bucket string
// Ownership is the ownership argument value.
Ownership types.ObjectOwnership
}
// PutBucketPolicy holds details about calls to the PutBucketPolicy method. // PutBucketPolicy holds details about calls to the PutBucketPolicy method.
PutBucketPolicy []struct { PutBucketPolicy []struct {
// ContextMoqParam is the contextMoqParam argument value. // ContextMoqParam is the contextMoqParam argument value.
@@ -693,54 +735,57 @@ type BackendMock struct {
UploadPartCopyInput *s3.UploadPartCopyInput UploadPartCopyInput *s3.UploadPartCopyInput
} }
} }
lockAbortMultipartUpload sync.RWMutex lockAbortMultipartUpload sync.RWMutex
lockChangeBucketOwner sync.RWMutex lockChangeBucketOwner sync.RWMutex
lockCompleteMultipartUpload sync.RWMutex lockCompleteMultipartUpload sync.RWMutex
lockCopyObject sync.RWMutex lockCopyObject sync.RWMutex
lockCreateBucket sync.RWMutex lockCreateBucket sync.RWMutex
lockCreateMultipartUpload sync.RWMutex lockCreateMultipartUpload sync.RWMutex
lockDeleteBucket sync.RWMutex lockDeleteBucket sync.RWMutex
lockDeleteBucketPolicy sync.RWMutex lockDeleteBucketOwnershipControls sync.RWMutex
lockDeleteBucketTagging sync.RWMutex lockDeleteBucketPolicy sync.RWMutex
lockDeleteObject sync.RWMutex lockDeleteBucketTagging sync.RWMutex
lockDeleteObjectTagging sync.RWMutex lockDeleteObject sync.RWMutex
lockDeleteObjects sync.RWMutex lockDeleteObjectTagging sync.RWMutex
lockGetBucketAcl sync.RWMutex lockDeleteObjects sync.RWMutex
lockGetBucketPolicy sync.RWMutex lockGetBucketAcl sync.RWMutex
lockGetBucketTagging sync.RWMutex lockGetBucketOwnershipControls sync.RWMutex
lockGetBucketVersioning sync.RWMutex lockGetBucketPolicy sync.RWMutex
lockGetObject sync.RWMutex lockGetBucketTagging sync.RWMutex
lockGetObjectAcl sync.RWMutex lockGetBucketVersioning sync.RWMutex
lockGetObjectAttributes sync.RWMutex lockGetObject sync.RWMutex
lockGetObjectLegalHold sync.RWMutex lockGetObjectAcl sync.RWMutex
lockGetObjectLockConfiguration sync.RWMutex lockGetObjectAttributes sync.RWMutex
lockGetObjectRetention sync.RWMutex lockGetObjectLegalHold sync.RWMutex
lockGetObjectTagging sync.RWMutex lockGetObjectLockConfiguration sync.RWMutex
lockHeadBucket sync.RWMutex lockGetObjectRetention sync.RWMutex
lockHeadObject sync.RWMutex lockGetObjectTagging sync.RWMutex
lockListBuckets sync.RWMutex lockHeadBucket sync.RWMutex
lockListBucketsAndOwners sync.RWMutex lockHeadObject sync.RWMutex
lockListMultipartUploads sync.RWMutex lockListBuckets sync.RWMutex
lockListObjectVersions sync.RWMutex lockListBucketsAndOwners sync.RWMutex
lockListObjects sync.RWMutex lockListMultipartUploads sync.RWMutex
lockListObjectsV2 sync.RWMutex lockListObjectVersions sync.RWMutex
lockListParts sync.RWMutex lockListObjects sync.RWMutex
lockPutBucketAcl sync.RWMutex lockListObjectsV2 sync.RWMutex
lockPutBucketPolicy sync.RWMutex lockListParts sync.RWMutex
lockPutBucketTagging sync.RWMutex lockPutBucketAcl sync.RWMutex
lockPutBucketVersioning sync.RWMutex lockPutBucketOwnershipControls sync.RWMutex
lockPutObject sync.RWMutex lockPutBucketPolicy sync.RWMutex
lockPutObjectAcl sync.RWMutex lockPutBucketTagging sync.RWMutex
lockPutObjectLegalHold sync.RWMutex lockPutBucketVersioning sync.RWMutex
lockPutObjectLockConfiguration sync.RWMutex lockPutObject sync.RWMutex
lockPutObjectRetention sync.RWMutex lockPutObjectAcl sync.RWMutex
lockPutObjectTagging sync.RWMutex lockPutObjectLegalHold sync.RWMutex
lockRestoreObject sync.RWMutex lockPutObjectLockConfiguration sync.RWMutex
lockSelectObjectContent sync.RWMutex lockPutObjectRetention sync.RWMutex
lockShutdown sync.RWMutex lockPutObjectTagging sync.RWMutex
lockString sync.RWMutex lockRestoreObject sync.RWMutex
lockUploadPart sync.RWMutex lockSelectObjectContent sync.RWMutex
lockUploadPartCopy sync.RWMutex lockShutdown sync.RWMutex
lockString sync.RWMutex
lockUploadPart sync.RWMutex
lockUploadPartCopy sync.RWMutex
} }
// AbortMultipartUpload calls AbortMultipartUploadFunc. // AbortMultipartUpload calls AbortMultipartUploadFunc.
@@ -1003,6 +1048,42 @@ func (mock *BackendMock) DeleteBucketCalls() []struct {
return calls return calls
} }
// DeleteBucketOwnershipControls calls DeleteBucketOwnershipControlsFunc.
func (mock *BackendMock) DeleteBucketOwnershipControls(contextMoqParam context.Context, bucket string) error {
if mock.DeleteBucketOwnershipControlsFunc == nil {
panic("BackendMock.DeleteBucketOwnershipControlsFunc: method is nil but Backend.DeleteBucketOwnershipControls was just called")
}
callInfo := struct {
ContextMoqParam context.Context
Bucket string
}{
ContextMoqParam: contextMoqParam,
Bucket: bucket,
}
mock.lockDeleteBucketOwnershipControls.Lock()
mock.calls.DeleteBucketOwnershipControls = append(mock.calls.DeleteBucketOwnershipControls, callInfo)
mock.lockDeleteBucketOwnershipControls.Unlock()
return mock.DeleteBucketOwnershipControlsFunc(contextMoqParam, bucket)
}
// DeleteBucketOwnershipControlsCalls gets all the calls that were made to DeleteBucketOwnershipControls.
// Check the length with:
//
// len(mockedBackend.DeleteBucketOwnershipControlsCalls())
func (mock *BackendMock) DeleteBucketOwnershipControlsCalls() []struct {
ContextMoqParam context.Context
Bucket string
} {
var calls []struct {
ContextMoqParam context.Context
Bucket string
}
mock.lockDeleteBucketOwnershipControls.RLock()
calls = mock.calls.DeleteBucketOwnershipControls
mock.lockDeleteBucketOwnershipControls.RUnlock()
return calls
}
// DeleteBucketPolicy calls DeleteBucketPolicyFunc. // DeleteBucketPolicy calls DeleteBucketPolicyFunc.
func (mock *BackendMock) DeleteBucketPolicy(contextMoqParam context.Context, bucket string) error { func (mock *BackendMock) DeleteBucketPolicy(contextMoqParam context.Context, bucket string) error {
if mock.DeleteBucketPolicyFunc == nil { if mock.DeleteBucketPolicyFunc == nil {
@@ -1223,6 +1304,42 @@ func (mock *BackendMock) GetBucketAclCalls() []struct {
return calls return calls
} }
// GetBucketOwnershipControls calls GetBucketOwnershipControlsFunc.
func (mock *BackendMock) GetBucketOwnershipControls(contextMoqParam context.Context, bucket string) (types.ObjectOwnership, error) {
if mock.GetBucketOwnershipControlsFunc == nil {
panic("BackendMock.GetBucketOwnershipControlsFunc: method is nil but Backend.GetBucketOwnershipControls was just called")
}
callInfo := struct {
ContextMoqParam context.Context
Bucket string
}{
ContextMoqParam: contextMoqParam,
Bucket: bucket,
}
mock.lockGetBucketOwnershipControls.Lock()
mock.calls.GetBucketOwnershipControls = append(mock.calls.GetBucketOwnershipControls, callInfo)
mock.lockGetBucketOwnershipControls.Unlock()
return mock.GetBucketOwnershipControlsFunc(contextMoqParam, bucket)
}
// GetBucketOwnershipControlsCalls gets all the calls that were made to GetBucketOwnershipControls.
// Check the length with:
//
// len(mockedBackend.GetBucketOwnershipControlsCalls())
func (mock *BackendMock) GetBucketOwnershipControlsCalls() []struct {
ContextMoqParam context.Context
Bucket string
} {
var calls []struct {
ContextMoqParam context.Context
Bucket string
}
mock.lockGetBucketOwnershipControls.RLock()
calls = mock.calls.GetBucketOwnershipControls
mock.lockGetBucketOwnershipControls.RUnlock()
return calls
}
// GetBucketPolicy calls GetBucketPolicyFunc. // GetBucketPolicy calls GetBucketPolicyFunc.
func (mock *BackendMock) GetBucketPolicy(contextMoqParam context.Context, bucket string) ([]byte, error) { func (mock *BackendMock) GetBucketPolicy(contextMoqParam context.Context, bucket string) ([]byte, error) {
if mock.GetBucketPolicyFunc == nil { if mock.GetBucketPolicyFunc == nil {
@@ -1971,6 +2088,46 @@ func (mock *BackendMock) PutBucketAclCalls() []struct {
return calls return calls
} }
// PutBucketOwnershipControls calls PutBucketOwnershipControlsFunc.
func (mock *BackendMock) PutBucketOwnershipControls(contextMoqParam context.Context, bucket string, ownership types.ObjectOwnership) error {
if mock.PutBucketOwnershipControlsFunc == nil {
panic("BackendMock.PutBucketOwnershipControlsFunc: method is nil but Backend.PutBucketOwnershipControls was just called")
}
callInfo := struct {
ContextMoqParam context.Context
Bucket string
Ownership types.ObjectOwnership
}{
ContextMoqParam: contextMoqParam,
Bucket: bucket,
Ownership: ownership,
}
mock.lockPutBucketOwnershipControls.Lock()
mock.calls.PutBucketOwnershipControls = append(mock.calls.PutBucketOwnershipControls, callInfo)
mock.lockPutBucketOwnershipControls.Unlock()
return mock.PutBucketOwnershipControlsFunc(contextMoqParam, bucket, ownership)
}
// PutBucketOwnershipControlsCalls gets all the calls that were made to PutBucketOwnershipControls.
// Check the length with:
//
// len(mockedBackend.PutBucketOwnershipControlsCalls())
func (mock *BackendMock) PutBucketOwnershipControlsCalls() []struct {
ContextMoqParam context.Context
Bucket string
Ownership types.ObjectOwnership
} {
var calls []struct {
ContextMoqParam context.Context
Bucket string
Ownership types.ObjectOwnership
}
mock.lockPutBucketOwnershipControls.RLock()
calls = mock.calls.PutBucketOwnershipControls
mock.lockPutBucketOwnershipControls.RUnlock()
return calls
}
// PutBucketPolicy calls PutBucketPolicyFunc. // PutBucketPolicy calls PutBucketPolicyFunc.
func (mock *BackendMock) PutBucketPolicy(contextMoqParam context.Context, bucket string, policy []byte) error { func (mock *BackendMock) PutBucketPolicy(contextMoqParam context.Context, bucket string, policy []byte) error {
if mock.PutBucketPolicyFunc == nil { if mock.PutBucketPolicyFunc == nil {
+180 -6
View File
@@ -566,6 +566,43 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error {
}) })
} }
if ctx.Request().URI().QueryArgs().Has("ownershipControls") {
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
Readonly: c.readonly,
Acl: parsedAcl,
AclPermission: types.PermissionRead,
IsRoot: isRoot,
Acc: acct,
Bucket: bucket,
Action: auth.GetBucketOwnershipControlsAction,
})
if err != nil {
return SendXMLResponse(ctx, nil, err,
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionGetBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
})
}
data, err := c.be.GetBucketOwnershipControls(ctx.Context(), bucket)
return SendXMLResponse(ctx,
s3response.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: data,
},
},
}, err,
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionGetBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
})
}
if ctx.Request().URI().QueryArgs().Has("versioning") { if ctx.Request().URI().QueryArgs().Has("versioning") {
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{ err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
Readonly: c.readonly, Readonly: c.readonly,
@@ -933,6 +970,9 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
grantReadACP := ctx.Get("X-Amz-Grant-Read-Acp") grantReadACP := ctx.Get("X-Amz-Grant-Read-Acp")
granWrite := ctx.Get("X-Amz-Grant-Write") granWrite := ctx.Get("X-Amz-Grant-Write")
grantWriteACP := ctx.Get("X-Amz-Grant-Write-Acp") grantWriteACP := ctx.Get("X-Amz-Grant-Write-Acp")
objectOwnership := types.ObjectOwnership(
ctx.Get("X-Amz-Object-Ownership", string(types.ObjectOwnershipBucketOwnerEnforced)),
)
mfa := ctx.Get("X-Amz-Mfa") mfa := ctx.Get("X-Amz-Mfa")
contentMD5 := ctx.Get("Content-MD5") contentMD5 := ctx.Get("Content-MD5")
acct := ctx.Locals("account").(auth.Account) acct := ctx.Locals("account").(auth.Account)
@@ -1000,6 +1040,57 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
}) })
} }
if ctx.Request().URI().QueryArgs().Has("ownershipControls") {
parsedAcl := ctx.Locals("parsedAcl").(auth.ACL)
var ownershipControls s3response.OwnershipControls
if err := xml.Unmarshal(ctx.Body(), &ownershipControls); err != nil {
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrMalformedXML),
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionPutBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
})
}
if len(ownershipControls.Rules) != 1 || !utils.IsValidOwnership(ownershipControls.Rules[0].ObjectOwnership) {
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrMalformedXML),
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionPutBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
})
}
if err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
Readonly: c.readonly,
Acl: parsedAcl,
AclPermission: types.PermissionWrite,
IsRoot: isRoot,
Acc: acct,
Bucket: bucket,
Action: auth.PutBucketOwnershipControlsAction,
}); err != nil {
return SendResponse(ctx, err,
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionPutBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
})
}
err := c.be.PutBucketOwnershipControls(ctx.Context(), bucket, ownershipControls.Rules[0].ObjectOwnership)
return SendResponse(ctx, err,
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionPutBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
})
}
if ctx.Request().URI().QueryArgs().Has("versioning") { if ctx.Request().URI().QueryArgs().Has("versioning") {
parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) parsedAcl := ctx.Locals("parsedAcl").(auth.ACL)
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{ err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
@@ -1141,10 +1232,33 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
grants := grantFullControl + grantRead + grantReadACP + granWrite + grantWriteACP grants := grantFullControl + grantRead + grantReadACP + granWrite + grantWriteACP
if ctx.Request().URI().QueryArgs().Has("acl") { if ctx.Request().URI().QueryArgs().Has("acl") {
parsedAcl := ctx.Locals("parsedAcl").(auth.ACL)
var input *s3.PutBucketAclInput var input *s3.PutBucketAclInput
parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) ownership, err := c.be.GetBucketOwnershipControls(ctx.Context(), bucket)
err := auth.VerifyAccess(ctx.Context(), c.be, if err != nil && !errors.Is(err, s3err.GetAPIError(s3err.ErrOwnershipControlsNotFound)) {
return SendResponse(ctx, err,
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionPutBucketAcl,
BucketOwner: parsedAcl.Owner,
})
}
if ownership == types.ObjectOwnershipBucketOwnerEnforced {
if c.debug {
log.Println("bucket acls are disabled")
}
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrAclNotSupported),
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionPutBucketAcl,
BucketOwner: parsedAcl.Owner,
})
}
err = auth.VerifyAccess(ctx.Context(), c.be,
auth.AccessOptions{ auth.AccessOptions{
Readonly: c.readonly, Readonly: c.readonly,
Acl: parsedAcl, Acl: parsedAcl,
@@ -1259,7 +1373,6 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
} }
} }
fmt.Println(*input, parsedAcl)
updAcl, err := auth.UpdateACL(input, parsedAcl, c.iam) updAcl, err := auth.UpdateACL(input, parsedAcl, c.iam)
if err != nil { if err != nil {
return SendResponse(ctx, err, return SendResponse(ctx, err,
@@ -1289,16 +1402,45 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
Action: metrics.ActionCreateBucket, Action: metrics.ActionCreateBucket,
}) })
} }
if ok := utils.IsValidOwnership(objectOwnership); !ok {
if c.debug {
log.Printf("invalid bucket object ownership: %v", objectOwnership)
}
return SendResponse(ctx, s3err.APIError{
Code: "InvalidArgument",
Description: fmt.Sprintf("Invalid x-amz-object-ownership header: %v", objectOwnership),
HTTPStatusCode: http.StatusBadRequest,
},
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionCreateBucket,
BucketOwner: acct.Access,
})
}
if acl+grants != "" && objectOwnership == types.ObjectOwnershipBucketOwnerEnforced {
if c.debug {
log.Printf("bucket acls are disabled for %v object ownership", objectOwnership)
}
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidBucketAclWithObjectOwnership),
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionCreateBucket,
BucketOwner: acct.Access,
})
}
if acl != "" && grants != "" { if acl != "" && grants != "" {
if c.debug { if c.debug {
log.Printf("invalid request: %q (grants) %q (acl)", grants, acl) log.Printf("invalid request: %q (grants) %q (acl)", grants, acl)
} }
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest), return SendResponse(ctx, s3err.GetAPIError(s3err.ErrBothCannedAndHeaderGrants),
&MetaOpts{ &MetaOpts{
Logger: c.logger, Logger: c.logger,
MetricsMng: c.mm, MetricsMng: c.mm,
Action: metrics.ActionPutBucketAcl, Action: metrics.ActionCreateBucket,
BucketOwner: acct.Access, BucketOwner: acct.Access,
}) })
} }
@@ -1334,7 +1476,7 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
err = c.be.CreateBucket(ctx.Context(), &s3.CreateBucketInput{ err = c.be.CreateBucket(ctx.Context(), &s3.CreateBucketInput{
Bucket: &bucket, Bucket: &bucket,
ObjectOwnership: types.ObjectOwnership(acct.Access), ObjectOwnership: objectOwnership,
ObjectLockEnabledForBucket: &lockEnabled, ObjectLockEnabledForBucket: &lockEnabled,
}, updAcl) }, updAcl)
return SendResponse(ctx, err, return SendResponse(ctx, err,
@@ -2042,6 +2184,38 @@ func (c S3ApiController) DeleteBucket(ctx *fiber.Ctx) error {
}) })
} }
if ctx.Request().URI().QueryArgs().Has("ownershipControls") {
err := auth.VerifyAccess(ctx.Context(), c.be,
auth.AccessOptions{
Readonly: c.readonly,
Acl: parsedAcl,
AclPermission: types.PermissionWrite,
IsRoot: isRoot,
Acc: acct,
Bucket: bucket,
Action: auth.PutBucketOwnershipControlsAction,
})
if err != nil {
return SendResponse(ctx, err,
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionDeleteBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
})
}
err = c.be.DeleteBucketOwnershipControls(ctx.Context(), bucket)
return SendResponse(ctx, err,
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: metrics.ActionDeleteBucketOwnershipControls,
BucketOwner: parsedAcl.Owner,
Status: http.StatusNoContent,
})
}
if ctx.Request().URI().QueryArgs().Has("policy") { if ctx.Request().URI().QueryArgs().Has("policy") {
err := auth.VerifyAccess(ctx.Context(), c.be, err := auth.VerifyAccess(ctx.Context(), c.be,
auth.AccessOptions{ auth.AccessOptions{
+90 -3
View File
@@ -395,6 +395,9 @@ func TestS3ApiController_ListActions(t *testing.T) {
GetObjectLockConfigurationFunc: func(contextMoqParam context.Context, bucket string) ([]byte, error) { GetObjectLockConfigurationFunc: func(contextMoqParam context.Context, bucket string) ([]byte, error) {
return objectLockResult, nil return objectLockResult, nil
}, },
GetBucketOwnershipControlsFunc: func(contextMoqParam context.Context, bucket string) (types.ObjectOwnership, error) {
return types.ObjectOwnershipBucketOwnerEnforced, nil
},
}, },
} }
@@ -448,6 +451,15 @@ func TestS3ApiController_ListActions(t *testing.T) {
wantErr: false, wantErr: false,
statusCode: 404, statusCode: 404,
}, },
{
name: "Get-bucket-ownership-control-success",
app: app,
args: args{
req: httptest.NewRequest(http.MethodGet, "/my-bucket?ownershipControls", nil),
},
wantErr: false,
statusCode: 200,
},
{ {
name: "Get-bucket-tagging-success", name: "Get-bucket-tagging-success",
app: app, app: app,
@@ -562,7 +574,7 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
app := fiber.New() app := fiber.New()
// Mock valid acl // Mock valid acl
acl := auth.ACL{Owner: "valid access", ACL: "public-read-write"} acl := auth.ACL{Owner: "valid access"}
acldata, err := json.Marshal(acl) acldata, err := json.Marshal(acl)
if err != nil { if err != nil {
t.Errorf("Failed to parse the params: %v", err.Error()) t.Errorf("Failed to parse the params: %v", err.Error())
@@ -636,6 +648,22 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
</ObjectLockConfiguration> </ObjectLockConfiguration>
` `
ownershipBody := `
<OwnershipControls xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Rule>
<ObjectOwnership>BucketOwnerEnforced</ObjectOwnership>
</Rule>
</OwnershipControls>
`
invalidOwnershipBody := `
<OwnershipControls xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Rule>
<ObjectOwnership>invalid_value</ObjectOwnership>
</Rule>
</OwnershipControls>
`
s3ApiController := S3ApiController{ s3ApiController := S3ApiController{
be: &BackendMock{ be: &BackendMock{
GetBucketAclFunc: func(context.Context, *s3.GetBucketAclInput) ([]byte, error) { GetBucketAclFunc: func(context.Context, *s3.GetBucketAclInput) ([]byte, error) {
@@ -659,6 +687,12 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
PutObjectLockConfigurationFunc: func(contextMoqParam context.Context, bucket string, config []byte) error { PutObjectLockConfigurationFunc: func(contextMoqParam context.Context, bucket string, config []byte) error {
return nil return nil
}, },
PutBucketOwnershipControlsFunc: func(contextMoqParam context.Context, bucket string, ownership types.ObjectOwnership) error {
return nil
},
GetBucketOwnershipControlsFunc: func(contextMoqParam context.Context, bucket string) (types.ObjectOwnership, error) {
return types.ObjectOwnershipBucketOwnerPreferred, nil
},
}, },
} }
// Mock ctx.Locals // Mock ctx.Locals
@@ -691,6 +725,9 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
errAclBodyReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", strings.NewReader(body)) errAclBodyReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", strings.NewReader(body))
errAclBodyReq.Header.Set("X-Amz-Grant-Read", "hello") errAclBodyReq.Header.Set("X-Amz-Grant-Read", "hello")
invAclOwnershipReq := httptest.NewRequest(http.MethodPut, "/my-bucket", nil)
invAclOwnershipReq.Header.Set("X-Amz-Grant-Read", "hello")
tests := []struct { tests := []struct {
name string name string
app *fiber.App app *fiber.App
@@ -716,6 +753,24 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
wantErr: false, wantErr: false,
statusCode: 200, statusCode: 200,
}, },
{
name: "Put-bucket-ownership-controls-invalid-ownership",
app: app,
args: args{
req: httptest.NewRequest(http.MethodPut, "/my-bucket?ownershipControls", strings.NewReader(invalidOwnershipBody)),
},
wantErr: false,
statusCode: 400,
},
{
name: "Put-bucket-ownership-controls-success",
app: app,
args: args{
req: httptest.NewRequest(http.MethodPut, "/my-bucket?ownershipControls", strings.NewReader(ownershipBody)),
},
wantErr: false,
statusCode: 200,
},
{ {
name: "Put-object-lock-configuration-invalid-body", name: "Put-object-lock-configuration-invalid-body",
app: app, app: app,
@@ -816,7 +871,16 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
statusCode: 200, statusCode: 200,
}, },
{ {
name: "Put-bucket-invalid-bucket-name", name: "Create-bucket-invalid-acl-ownership-combination",
app: app,
args: args{
req: invAclOwnershipReq,
},
wantErr: false,
statusCode: 400,
},
{
name: "Create-bucket-invalid-bucket-name",
app: app, app: app,
args: args{ args: args{
req: httptest.NewRequest(http.MethodPut, "/aa", nil), req: httptest.NewRequest(http.MethodPut, "/aa", nil),
@@ -825,7 +889,7 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
statusCode: 400, statusCode: 400,
}, },
{ {
name: "Put-bucket-success", name: "Create-bucket-success",
app: app, app: app,
args: args{ args: args{
req: httptest.NewRequest(http.MethodPut, "/my-bucket", nil), req: httptest.NewRequest(http.MethodPut, "/my-bucket", nil),
@@ -1160,6 +1224,12 @@ func TestS3ApiController_DeleteBucket(t *testing.T) {
DeleteBucketTaggingFunc: func(contextMoqParam context.Context, bucket string) error { DeleteBucketTaggingFunc: func(contextMoqParam context.Context, bucket string) error {
return nil return nil
}, },
DeleteBucketPolicyFunc: func(contextMoqParam context.Context, bucket string) error {
return nil
},
DeleteBucketOwnershipControlsFunc: func(contextMoqParam context.Context, bucket string) error {
return nil
},
}, },
} }
@@ -1198,6 +1268,23 @@ func TestS3ApiController_DeleteBucket(t *testing.T) {
wantErr: false, wantErr: false,
statusCode: 204, statusCode: 204,
}, },
{
name: "Delete-bucket-ownership-controls-success",
app: app,
args: args{
req: httptest.NewRequest(http.MethodDelete, "/my-bucket?ownershipControls", nil),
},
wantErr: false,
statusCode: 204,
}, {
name: "Delete-bucket-policy-success",
app: app,
args: args{
req: httptest.NewRequest(http.MethodDelete, "/my-bucket?policy", nil),
},
wantErr: false,
statusCode: 204,
},
} }
for _, tt := range tests { for _, tt := range tests {
resp, err := tt.app.Test(tt.args.req) resp, err := tt.app.Test(tt.args.req)
+2 -1
View File
@@ -50,7 +50,8 @@ func AclParser(be backend.Backend, logger s3log.AuditLogger, readonly bool) fibe
!ctx.Request().URI().QueryArgs().Has("tagging") && !ctx.Request().URI().QueryArgs().Has("tagging") &&
!ctx.Request().URI().QueryArgs().Has("versioning") && !ctx.Request().URI().QueryArgs().Has("versioning") &&
!ctx.Request().URI().QueryArgs().Has("policy") && !ctx.Request().URI().QueryArgs().Has("policy") &&
!ctx.Request().URI().QueryArgs().Has("object-lock") { !ctx.Request().URI().QueryArgs().Has("object-lock") &&
!ctx.Request().URI().QueryArgs().Has("ownershipControls") {
if err := auth.MayCreateBucket(acct, isRoot); err != nil { if err := auth.MayCreateBucket(acct, isRoot); err != nil {
return controllers.SendXMLResponse(ctx, nil, err, &controllers.MetaOpts{Logger: logger, Action: "CreateBucket"}) return controllers.SendXMLResponse(ctx, nil, err, &controllers.MetaOpts{Logger: logger, Action: "CreateBucket"})
} }
+13
View File
@@ -326,3 +326,16 @@ func ParsObjectLockHdrs(ctx *fiber.Ctx) (*objLockCfg, error) {
LegalHoldStatus: legalHold, LegalHoldStatus: legalHold,
}, nil }, nil
} }
func IsValidOwnership(val types.ObjectOwnership) bool {
switch val {
case types.ObjectOwnershipBucketOwnerEnforced:
return true
case types.ObjectOwnershipBucketOwnerPreferred:
return true
case types.ObjectOwnershipObjectWriter:
return true
default:
return false
}
}
+47
View File
@@ -335,3 +335,50 @@ func TestFilterObjectAttributes(t *testing.T) {
}) })
} }
} }
func TestIsValidOwnership(t *testing.T) {
type args struct {
val types.ObjectOwnership
}
tests := []struct {
name string
args args
want bool
}{
{
name: "valid-BucketOwnerEnforced",
args: args{
val: types.ObjectOwnershipBucketOwnerEnforced,
},
want: true,
},
{
name: "valid-BucketOwnerPreferred",
args: args{
val: types.ObjectOwnershipBucketOwnerPreferred,
},
want: true,
},
{
name: "valid-ObjectWriter",
args: args{
val: types.ObjectOwnershipObjectWriter,
},
want: true,
},
{
name: "invalid_value",
args: args{
val: types.ObjectOwnership("invalid_value"),
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsValidOwnership(tt.args.val); got != tt.want {
t.Errorf("IsValidOwnership() = %v, want %v", got, tt.want)
}
})
}
}
+24
View File
@@ -123,6 +123,10 @@ const (
ErrBucketTaggingNotFound ErrBucketTaggingNotFound
ErrObjectLockInvalidHeaders ErrObjectLockInvalidHeaders
ErrRequestTimeTooSkewed ErrRequestTimeTooSkewed
ErrInvalidBucketAclWithObjectOwnership
ErrBothCannedAndHeaderGrants
ErrOwnershipControlsNotFound
ErrAclNotSupported
// Non-AWS errors // Non-AWS errors
ErrExistingObjectIsDirectory ErrExistingObjectIsDirectory
@@ -472,6 +476,26 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "The difference between the request time and the server's time is too large.", Description: "The difference between the request time and the server's time is too large.",
HTTPStatusCode: http.StatusForbidden, HTTPStatusCode: http.StatusForbidden,
}, },
ErrInvalidBucketAclWithObjectOwnership: {
Code: "ErrInvalidBucketAclWithObjectOwnership",
Description: "Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting",
HTTPStatusCode: http.StatusBadRequest,
},
ErrBothCannedAndHeaderGrants: {
Code: "InvalidRequest",
Description: "Specifying both Canned ACLs and Header Grants is not allowed",
HTTPStatusCode: http.StatusBadRequest,
},
ErrOwnershipControlsNotFound: {
Code: "OwnershipControlsNotFoundError",
Description: "The bucket ownership controls were not found",
HTTPStatusCode: http.StatusNotFound,
},
ErrAclNotSupported: {
Code: "AccessControlListNotSupported",
Description: "The bucket does not allow ACLs",
HTTPStatusCode: http.StatusBadRequest,
},
// non aws errors // non aws errors
ErrExistingObjectIsDirectory: { ErrExistingObjectIsDirectory: {
+4
View File
@@ -217,3 +217,7 @@ type Grantee struct {
ID string ID string
DisplayName string DisplayName string
} }
type OwnershipControls struct {
Rules []types.OwnershipControlsRule `xml:"Rule"`
}
+41
View File
@@ -65,6 +65,8 @@ func TestCreateBucket(s *S3Conf) {
CreateBucket_invalid_bucket_name(s) CreateBucket_invalid_bucket_name(s)
CreateBucket_existing_bucket(s) CreateBucket_existing_bucket(s)
CreateBucket_owned_by_you(s) CreateBucket_owned_by_you(s)
CreateBucket_invalid_ownership(s)
CreateBucket_ownership_with_acl(s)
CreateBucket_as_user(s) CreateBucket_as_user(s)
CreateBucket_default_acl(s) CreateBucket_default_acl(s)
CreateBucket_non_default_acl(s) CreateBucket_non_default_acl(s)
@@ -89,6 +91,24 @@ func TestDeleteBucket(s *S3Conf) {
DeleteBucket_success_status_code(s) DeleteBucket_success_status_code(s)
} }
func TestPutBucketOwnershipControls(s *S3Conf) {
PutBucketOwnershipControls_non_existing_bucket(s)
PutBucketOwnershipControls_multiple_rules(s)
PutBucketOwnershipControls_invalid_ownership(s)
PutBucketOwnershipControls_success(s)
}
func TestGetBucketOwnershipControls(s *S3Conf) {
GetBucketOwnershipControls_non_existing_bucket(s)
GetBucketOwnershipControls_default_ownership(s)
GetBucketOwnershipControls_success(s)
}
func TestDeleteBucketOwnershipControls(s *S3Conf) {
DeleteBucketOwnershipControls_non_existing_bucket(s)
DeleteBucketOwnershipControls_success(s)
}
func TestPutBucketTagging(s *S3Conf) { func TestPutBucketTagging(s *S3Conf) {
PutBucketTagging_non_existing_bucket(s) PutBucketTagging_non_existing_bucket(s)
PutBucketTagging_long_tags(s) PutBucketTagging_long_tags(s)
@@ -267,6 +287,7 @@ func TestCompleteMultipartUpload(s *S3Conf) {
func TestPutBucketAcl(s *S3Conf) { func TestPutBucketAcl(s *S3Conf) {
PutBucketAcl_non_existing_bucket(s) PutBucketAcl_non_existing_bucket(s)
PutBucketAcl_disabled(s)
PutBucketAcl_invalid_acl_canned_and_acp(s) PutBucketAcl_invalid_acl_canned_and_acp(s)
PutBucketAcl_invalid_acl_canned_and_grants(s) PutBucketAcl_invalid_acl_canned_and_grants(s)
PutBucketAcl_invalid_acl_acp_and_grants(s) PutBucketAcl_invalid_acl_acp_and_grants(s)
@@ -280,6 +301,9 @@ func TestPutBucketAcl(s *S3Conf) {
func TestGetBucketAcl(s *S3Conf) { func TestGetBucketAcl(s *S3Conf) {
GetBucketAcl_non_existing_bucket(s) GetBucketAcl_non_existing_bucket(s)
GetBucketAcl_translation_canned_public_read(s)
GetBucketAcl_translation_canned_public_read_write(s)
GetBucketAcl_translation_canned_private(s)
GetBucketAcl_access_denied(s) GetBucketAcl_access_denied(s)
GetBucketAcl_success(s) GetBucketAcl_success(s)
} }
@@ -395,6 +419,9 @@ func TestFullFlow(s *S3Conf) {
TestHeadBucket(s) TestHeadBucket(s)
TestListBuckets(s) TestListBuckets(s)
TestDeleteBucket(s) TestDeleteBucket(s)
TestPutBucketOwnershipControls(s)
TestGetBucketOwnershipControls(s)
TestDeleteBucketOwnershipControls(s)
TestPutBucketTagging(s) TestPutBucketTagging(s)
TestGetBucketTagging(s) TestGetBucketTagging(s)
TestDeleteBucketTagging(s) TestDeleteBucketTagging(s)
@@ -505,6 +532,8 @@ func GetIntTests() IntTests {
"CreateBucket_invalid_bucket_name": CreateBucket_invalid_bucket_name, "CreateBucket_invalid_bucket_name": CreateBucket_invalid_bucket_name,
"CreateBucket_existing_bucket": CreateBucket_existing_bucket, "CreateBucket_existing_bucket": CreateBucket_existing_bucket,
"CreateBucket_owned_by_you": CreateBucket_owned_by_you, "CreateBucket_owned_by_you": CreateBucket_owned_by_you,
"CreateBucket_invalid_ownership": CreateBucket_invalid_ownership,
"CreateBucket_ownership_with_acl": CreateBucket_ownership_with_acl,
"CreateBucket_as_user": CreateBucket_as_user, "CreateBucket_as_user": CreateBucket_as_user,
"CreateDeleteBucket_success": CreateDeleteBucket_success, "CreateDeleteBucket_success": CreateDeleteBucket_success,
"CreateBucket_default_acl": CreateBucket_default_acl, "CreateBucket_default_acl": CreateBucket_default_acl,
@@ -518,6 +547,15 @@ func GetIntTests() IntTests {
"DeleteBucket_non_existing_bucket": DeleteBucket_non_existing_bucket, "DeleteBucket_non_existing_bucket": DeleteBucket_non_existing_bucket,
"DeleteBucket_non_empty_bucket": DeleteBucket_non_empty_bucket, "DeleteBucket_non_empty_bucket": DeleteBucket_non_empty_bucket,
"DeleteBucket_success_status_code": DeleteBucket_success_status_code, "DeleteBucket_success_status_code": DeleteBucket_success_status_code,
"PutBucketOwnershipControls_non_existing_bucket": PutBucketOwnershipControls_non_existing_bucket,
"PutBucketOwnershipControls_multiple_rules": PutBucketOwnershipControls_multiple_rules,
"PutBucketOwnershipControls_invalid_ownership": PutBucketOwnershipControls_invalid_ownership,
"PutBucketOwnershipControls_success": PutBucketOwnershipControls_success,
"GetBucketOwnershipControls_non_existing_bucket": GetBucketOwnershipControls_non_existing_bucket,
"GetBucketOwnershipControls_default_ownership": GetBucketOwnershipControls_default_ownership,
"GetBucketOwnershipControls_success": GetBucketOwnershipControls_success,
"DeleteBucketOwnershipControls_non_existing_bucket": DeleteBucketOwnershipControls_non_existing_bucket,
"DeleteBucketOwnershipControls_success": DeleteBucketOwnershipControls_success,
"PutBucketTagging_non_existing_bucket": PutBucketTagging_non_existing_bucket, "PutBucketTagging_non_existing_bucket": PutBucketTagging_non_existing_bucket,
"PutBucketTagging_long_tags": PutBucketTagging_long_tags, "PutBucketTagging_long_tags": PutBucketTagging_long_tags,
"PutBucketTagging_success": PutBucketTagging_success, "PutBucketTagging_success": PutBucketTagging_success,
@@ -636,6 +674,9 @@ func GetIntTests() IntTests {
"PutBucketAcl_success_canned_acl": PutBucketAcl_success_canned_acl, "PutBucketAcl_success_canned_acl": PutBucketAcl_success_canned_acl,
"PutBucketAcl_success_acp": PutBucketAcl_success_acp, "PutBucketAcl_success_acp": PutBucketAcl_success_acp,
"GetBucketAcl_non_existing_bucket": GetBucketAcl_non_existing_bucket, "GetBucketAcl_non_existing_bucket": GetBucketAcl_non_existing_bucket,
"GetBucketAcl_translation_canned_public_read": GetBucketAcl_translation_canned_public_read,
"GetBucketAcl_translation_canned_public_read_write": GetBucketAcl_translation_canned_public_read_write,
"GetBucketAcl_translation_canned_private": GetBucketAcl_translation_canned_private,
"GetBucketAcl_access_denied": GetBucketAcl_access_denied, "GetBucketAcl_access_denied": GetBucketAcl_access_denied,
"GetBucketAcl_success": GetBucketAcl_success, "GetBucketAcl_success": GetBucketAcl_success,
"PutBucketPolicy_non_existing_bucket": PutBucketPolicy_non_existing_bucket, "PutBucketPolicy_non_existing_bucket": PutBucketPolicy_non_existing_bucket,
+473 -42
View File
@@ -1720,47 +1720,76 @@ func CreateBucket_owned_by_you(s *S3Conf) error {
}) })
} }
func CreateBucket_default_acl(s *S3Conf) error { func CreateBucket_invalid_ownership(s *S3Conf) error {
testName := "CreateBucket_default_acl" testName := "CreateBucket_invalid_ownership"
runF(testName) runF(testName)
bucket := getBucketName() invalidOwnership := types.ObjectOwnership("invalid_ownership")
client := s3.NewFromConfig(s.Config()) err := setup(s, getBucketName(), withOwnership(invalidOwnership))
if err := checkApiErr(err, s3err.APIError{
err := setup(s, bucket) Code: "InvalidArgument",
if err != nil { Description: fmt.Sprintf("Invalid x-amz-object-ownership header: %v", invalidOwnership),
HTTPStatusCode: http.StatusBadRequest,
}); err != nil {
failF("%v: %v", testName, err) failF("%v: %v", testName, err)
return fmt.Errorf("%v: %w", testName, err) return fmt.Errorf("%v: %w", testName, err)
} }
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
out, err := client.GetBucketAcl(ctx, &s3.GetBucketAclInput{Bucket: &bucket})
cancel()
if err != nil {
failF("%v: %v", testName, err)
return fmt.Errorf("%v: %w", testName, err)
}
if *out.Owner.ID != s.awsID {
failF("%v: expected bucket owner to be %v, instead got %v", testName, s.awsID, *out.Owner.ID)
return fmt.Errorf("%v: expected bucket owner to be %v, instead got %v", testName, s.awsID, *out.Owner.ID)
}
if len(out.Grants) != 0 {
failF("%v: expected grants to be empty instead got %v", testName, len(out.Grants))
return fmt.Errorf("%v: expected grants to be empty instead got %v", testName, len(out.Grants))
}
err = teardown(s, bucket)
if err != nil {
failF("%v: %v", err)
return fmt.Errorf("%v: %w", testName, err)
}
passF(testName) passF(testName)
return nil return nil
} }
func CreateBucket_ownership_with_acl(s *S3Conf) error {
testName := "CreateBucket_ownership_with_acl"
runF(testName)
client := s3.NewFromConfig(s.Config())
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := client.CreateBucket(ctx, &s3.CreateBucketInput{
Bucket: getPtr(getBucketName()),
ObjectOwnership: types.ObjectOwnershipBucketOwnerEnforced,
ACL: types.BucketCannedACLPublicRead,
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidBucketAclWithObjectOwnership)); err != nil {
failF("%v: %v", testName, err)
return fmt.Errorf("%v: %w", testName, err)
}
passF(testName)
return nil
}
func CreateBucket_default_acl(s *S3Conf) error {
testName := "CreateBucket_default_acl"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
out, err := s3client.GetBucketAcl(ctx, &s3.GetBucketAclInput{Bucket: &bucket})
cancel()
if err != nil {
return err
}
if *out.Owner.ID != s.awsID {
return fmt.Errorf("expected bucket owner to be %v, instead got %v", s.awsID, *out.Owner.ID)
}
if len(out.Grants) != 1 {
return fmt.Errorf("expected grants length to be 1, instead got %v", len(out.Grants))
}
grt := out.Grants[0]
if grt.Permission != types.PermissionFullControl {
return fmt.Errorf("expected the grantee to have full-control permission, instead got %v", grt.Permission)
}
if *grt.Grantee.ID != s.awsID {
return fmt.Errorf("expected the grantee id to be %v, instead got %v", s.awsID, *grt.Grantee.ID)
}
return nil
})
}
func CreateBucket_non_default_acl(s *S3Conf) error { func CreateBucket_non_default_acl(s *S3Conf) error {
testName := "CreateBucket_non_default_acl" testName := "CreateBucket_non_default_acl"
runF(testName) runF(testName)
@@ -1776,6 +1805,12 @@ func CreateBucket_non_default_acl(s *S3Conf) error {
} }
grants := []types.Grant{ grants := []types.Grant{
{
Grantee: &types.Grantee{
ID: &s.awsID,
},
Permission: types.PermissionFullControl,
},
{ {
Grantee: &types.Grantee{ Grantee: &types.Grantee{
ID: getPtr("grt1"), ID: getPtr("grt1"),
@@ -1800,7 +1835,13 @@ func CreateBucket_non_default_acl(s *S3Conf) error {
client := s3.NewFromConfig(s.Config()) client := s3.NewFromConfig(s.Config())
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err = client.CreateBucket(ctx, &s3.CreateBucketInput{Bucket: &bucket, GrantFullControl: getPtr("grt1"), GrantReadACP: getPtr("grt2"), GrantWrite: getPtr("grt3")}) _, err = client.CreateBucket(ctx, &s3.CreateBucketInput{
Bucket: &bucket,
GrantFullControl: getPtr("grt1"),
GrantReadACP: getPtr("grt2"),
GrantWrite: getPtr("grt3"),
ObjectOwnership: types.ObjectOwnershipBucketOwnerPreferred,
})
cancel() cancel()
if err != nil { if err != nil {
failF("%v: %v", err) failF("%v: %v", err)
@@ -2195,6 +2236,220 @@ func DeleteBucket_success_status_code(s *S3Conf) error {
return nil return nil
} }
func PutBucketOwnershipControls_non_existing_bucket(s *S3Conf) error {
testName := "PutBucketOwnershipControls_non_existing_bucket"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketOwnershipControls(ctx, &s3.PutBucketOwnershipControlsInput{
Bucket: getPtr(getBucketName()),
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnershipBucketOwnerPreferred,
},
},
},
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchBucket)); err != nil {
return err
}
return nil
})
}
func PutBucketOwnershipControls_multiple_rules(s *S3Conf) error {
testName := "PutBucketOwnershipControls_multiple_rules"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketOwnershipControls(ctx, &s3.PutBucketOwnershipControlsInput{
Bucket: &bucket,
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnershipBucketOwnerPreferred,
},
{
ObjectOwnership: types.ObjectOwnershipObjectWriter,
},
},
},
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrMalformedXML)); err != nil {
return err
}
return nil
})
}
func PutBucketOwnershipControls_invalid_ownership(s *S3Conf) error {
testName := "PutBucketOwnershipControls_invalid_ownership"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketOwnershipControls(ctx, &s3.PutBucketOwnershipControlsInput{
Bucket: &bucket,
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnership("invalid_ownership"),
},
},
},
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrMalformedXML)); err != nil {
return err
}
return nil
})
}
func PutBucketOwnershipControls_success(s *S3Conf) error {
testName := "PutBucketOwnershipControls_success"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketOwnershipControls(ctx, &s3.PutBucketOwnershipControlsInput{
Bucket: &bucket,
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnershipObjectWriter,
},
},
},
})
cancel()
if err != nil {
return err
}
return nil
})
}
func GetBucketOwnershipControls_non_existing_bucket(s *S3Conf) error {
testName := "GetBucketOwnershipControls_non_existing_bucket"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.GetBucketOwnershipControls(ctx, &s3.GetBucketOwnershipControlsInput{
Bucket: getPtr(getBucketName()),
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchBucket)); err != nil {
return err
}
return nil
})
}
func GetBucketOwnershipControls_default_ownership(s *S3Conf) error {
testName := "GetBucketOwnershipControls_default_ownership"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
resp, err := s3client.GetBucketOwnershipControls(ctx, &s3.GetBucketOwnershipControlsInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
if len(resp.OwnershipControls.Rules) != 1 {
return fmt.Errorf("expected ownership control rules length to be 1, instead got %v", len(resp.OwnershipControls.Rules))
}
if resp.OwnershipControls.Rules[0].ObjectOwnership != types.ObjectOwnershipBucketOwnerEnforced {
return fmt.Errorf("expected the bucket ownership to be %v, instead got %v", types.ObjectOwnershipBucketOwnerEnforced, resp.OwnershipControls.Rules[0].ObjectOwnership)
}
return nil
})
}
func GetBucketOwnershipControls_success(s *S3Conf) error {
testName := "GetBucketOwnershipControls_success"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketOwnershipControls(ctx, &s3.PutBucketOwnershipControlsInput{
Bucket: &bucket,
OwnershipControls: &types.OwnershipControls{
Rules: []types.OwnershipControlsRule{
{
ObjectOwnership: types.ObjectOwnershipObjectWriter,
},
},
},
})
cancel()
if err != nil {
return err
}
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
resp, err := s3client.GetBucketOwnershipControls(ctx, &s3.GetBucketOwnershipControlsInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
if len(resp.OwnershipControls.Rules) != 1 {
return fmt.Errorf("expected ownership control rules length to be 1, instead got %v", len(resp.OwnershipControls.Rules))
}
if resp.OwnershipControls.Rules[0].ObjectOwnership != types.ObjectOwnershipObjectWriter {
return fmt.Errorf("expected the bucket ownership to be %v, instead got %v", types.ObjectOwnershipObjectWriter, resp.OwnershipControls.Rules[0].ObjectOwnership)
}
return nil
})
}
func DeleteBucketOwnershipControls_non_existing_bucket(s *S3Conf) error {
testName := "DeleteBucketOwnershipControls_non_existing_bucket"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.DeleteBucketOwnershipControls(ctx, &s3.DeleteBucketOwnershipControlsInput{
Bucket: getPtr(getBucketName()),
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchBucket)); err != nil {
return err
}
return nil
})
}
func DeleteBucketOwnershipControls_success(s *S3Conf) error {
testName := "DeleteBucketOwnershipControls_success"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.DeleteBucketOwnershipControls(ctx, &s3.DeleteBucketOwnershipControlsInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
_, err = s3client.GetBucketOwnershipControls(ctx, &s3.GetBucketOwnershipControlsInput{
Bucket: &bucket,
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrOwnershipControlsNotFound)); err != nil {
return err
}
return nil
})
}
func PutBucketTagging_non_existing_bucket(s *S3Conf) error { func PutBucketTagging_non_existing_bucket(s *S3Conf) error {
testName := "PutBucketTagging_non_existing_bucket" testName := "PutBucketTagging_non_existing_bucket"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
@@ -5893,6 +6148,23 @@ func PutBucketAcl_non_existing_bucket(s *S3Conf) error {
}) })
} }
func PutBucketAcl_disabled(s *S3Conf) error {
testName := "PutBucketAcl_disabled"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketAcl(ctx, &s3.PutBucketAclInput{
Bucket: &bucket,
ACL: types.BucketCannedACLPublicRead,
GrantRead: &s.awsID,
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrAclNotSupported)); err != nil {
return err
}
return nil
})
}
func PutBucketAcl_invalid_acl_canned_and_acp(s *S3Conf) error { func PutBucketAcl_invalid_acl_canned_and_acp(s *S3Conf) error {
testName := "PutBucketAcl_invalid_acl_canned_and_acp" testName := "PutBucketAcl_invalid_acl_canned_and_acp"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
@@ -5908,7 +6180,7 @@ func PutBucketAcl_invalid_acl_canned_and_acp(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_invalid_acl_canned_and_grants(s *S3Conf) error { func PutBucketAcl_invalid_acl_canned_and_grants(s *S3Conf) error {
@@ -5938,7 +6210,7 @@ func PutBucketAcl_invalid_acl_canned_and_grants(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_invalid_acl_acp_and_grants(s *S3Conf) error { func PutBucketAcl_invalid_acl_acp_and_grants(s *S3Conf) error {
@@ -5968,7 +6240,7 @@ func PutBucketAcl_invalid_acl_acp_and_grants(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_invalid_owner(s *S3Conf) error { func PutBucketAcl_invalid_owner(s *S3Conf) error {
@@ -5997,7 +6269,7 @@ func PutBucketAcl_invalid_owner(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_invalid_owner_not_in_body(s *S3Conf) error { func PutBucketAcl_invalid_owner_not_in_body(s *S3Conf) error {
@@ -6023,7 +6295,7 @@ func PutBucketAcl_invalid_owner_not_in_body(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_success_access_denied(s *S3Conf) error { func PutBucketAcl_success_access_denied(s *S3Conf) error {
@@ -6068,7 +6340,7 @@ func PutBucketAcl_success_access_denied(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_success_canned_acl(s *S3Conf) error { func PutBucketAcl_success_canned_acl(s *S3Conf) error {
@@ -6100,7 +6372,7 @@ func PutBucketAcl_success_canned_acl(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_success_acp(s *S3Conf) error { func PutBucketAcl_success_acp(s *S3Conf) error {
@@ -6141,7 +6413,7 @@ func PutBucketAcl_success_acp(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketAcl_success_grants(s *S3Conf) error { func PutBucketAcl_success_grants(s *S3Conf) error {
@@ -6186,7 +6458,7 @@ func PutBucketAcl_success_grants(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func GetBucketAcl_non_existing_bucket(s *S3Conf) error { func GetBucketAcl_non_existing_bucket(s *S3Conf) error {
@@ -6205,6 +6477,156 @@ func GetBucketAcl_non_existing_bucket(s *S3Conf) error {
}) })
} }
func GetBucketAcl_translation_canned_public_read(s *S3Conf) error {
testName := "GetBucketAcl_translation_canned_public_read"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
grants := []types.Grant{
{
Grantee: &types.Grantee{
ID: &s.awsID,
Type: types.TypeCanonicalUser,
},
Permission: types.PermissionFullControl,
},
{
Grantee: &types.Grantee{
ID: getPtr("all-users"),
Type: types.TypeCanonicalUser,
},
Permission: types.PermissionRead,
},
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketAcl(ctx, &s3.PutBucketAclInput{
Bucket: &bucket,
ACL: types.BucketCannedACLPublicRead,
})
cancel()
if err != nil {
return err
}
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
out, err := s3client.GetBucketAcl(ctx, &s3.GetBucketAclInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
if ok := compareGrants(out.Grants, grants); !ok {
return fmt.Errorf("expected grants to be %v, instead got %v", grants, out.Grants)
}
if *out.Owner.ID != s.awsID {
return fmt.Errorf("expected bucket owner to be %v, instead got %v", s.awsID, *out.Owner.ID)
}
return nil
}, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
}
func GetBucketAcl_translation_canned_public_read_write(s *S3Conf) error {
testName := "GetBucketAcl_translation_canned_public_read_write"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
grants := []types.Grant{
{
Grantee: &types.Grantee{
ID: &s.awsID,
Type: types.TypeCanonicalUser,
},
Permission: types.PermissionFullControl,
},
{
Grantee: &types.Grantee{
ID: getPtr("all-users"),
Type: types.TypeCanonicalUser,
},
Permission: types.PermissionRead,
},
{
Grantee: &types.Grantee{
ID: getPtr("all-users"),
Type: types.TypeCanonicalUser,
},
Permission: types.PermissionWrite,
},
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketAcl(ctx, &s3.PutBucketAclInput{
Bucket: &bucket,
ACL: types.BucketCannedACLPublicReadWrite,
})
cancel()
if err != nil {
return err
}
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
out, err := s3client.GetBucketAcl(ctx, &s3.GetBucketAclInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
if ok := compareGrants(out.Grants, grants); !ok {
return fmt.Errorf("expected grants to be %v, instead got %v", grants, out.Grants)
}
if *out.Owner.ID != s.awsID {
return fmt.Errorf("expected bucket owner to be %v, instead got %v", s.awsID, *out.Owner.ID)
}
return nil
}, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
}
func GetBucketAcl_translation_canned_private(s *S3Conf) error {
testName := "GetBucketAcl_translation_canned_private"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
grants := []types.Grant{
{
Grantee: &types.Grantee{
ID: &s.awsID,
Type: types.TypeCanonicalUser,
},
Permission: types.PermissionFullControl,
},
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketAcl(ctx, &s3.PutBucketAclInput{
Bucket: &bucket,
ACL: types.BucketCannedACLPrivate,
})
cancel()
if err != nil {
return err
}
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
out, err := s3client.GetBucketAcl(ctx, &s3.GetBucketAclInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
if ok := compareGrants(out.Grants, grants); !ok {
return fmt.Errorf("expected grants to be %v, instead got %v", grants, out.Grants)
}
if *out.Owner.ID != s.awsID {
return fmt.Errorf("expected bucket owner to be %v, instead got %v", s.awsID, *out.Owner.ID)
}
return nil
}, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
}
func GetBucketAcl_access_denied(s *S3Conf) error { func GetBucketAcl_access_denied(s *S3Conf) error {
testName := "GetBucketAcl_access_denied" testName := "GetBucketAcl_access_denied"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
@@ -6291,6 +6713,15 @@ func GetBucketAcl_success(s *S3Conf) error {
return err return err
} }
grants = append([]types.Grant{
{
Grantee: &types.Grantee{
ID: &s.awsID,
},
Permission: types.PermissionFullControl,
},
}, grants...)
if ok := compareGrants(out.Grants, grants); !ok { if ok := compareGrants(out.Grants, grants); !ok {
return fmt.Errorf("expected grants to be %v, instead got %v", grants, out.Grants) return fmt.Errorf("expected grants to be %v, instead got %v", grants, out.Grants)
} }
@@ -6299,7 +6730,7 @@ func GetBucketAcl_success(s *S3Conf) error {
} }
return nil return nil
}) }, withOwnership(types.ObjectOwnershipBucketOwnerPreferred))
} }
func PutBucketPolicy_non_existing_bucket(s *S3Conf) error { func PutBucketPolicy_non_existing_bucket(s *S3Conf) error {
+5
View File
@@ -66,6 +66,7 @@ func setup(s *S3Conf, bucket string, opts ...setupOpt) error {
_, err := s3client.CreateBucket(ctx, &s3.CreateBucketInput{ _, err := s3client.CreateBucket(ctx, &s3.CreateBucketInput{
Bucket: &bucket, Bucket: &bucket,
ObjectLockEnabledForBucket: &cfg.LockEnabled, ObjectLockEnabledForBucket: &cfg.LockEnabled,
ObjectOwnership: cfg.Ownership,
}) })
cancel() cancel()
return err return err
@@ -121,6 +122,7 @@ func teardown(s *S3Conf, bucket string) error {
type setupCfg struct { type setupCfg struct {
LockEnabled bool LockEnabled bool
Ownership types.ObjectOwnership
} }
type setupOpt func(*setupCfg) type setupOpt func(*setupCfg)
@@ -128,6 +130,9 @@ type setupOpt func(*setupCfg)
func withLock() setupOpt { func withLock() setupOpt {
return func(s *setupCfg) { s.LockEnabled = true } return func(s *setupCfg) { s.LockEnabled = true }
} }
func withOwnership(o types.ObjectOwnership) setupOpt {
return func(s *setupCfg) { s.Ownership = o }
}
func actionHandler(s *S3Conf, testName string, handler func(s3client *s3.Client, bucket string) error, opts ...setupOpt) error { func actionHandler(s *S3Conf, testName string, handler func(s3client *s3.Client, bucket string) error, opts ...setupOpt) error {
runF(testName) runF(testName)