fix: Fixes #197, Fixed PutBucketAcl action input validation

This commit is contained in:
jonaustin09
2023-08-25 00:40:17 +04:00
parent a2439264b2
commit e8b06a72f9
4 changed files with 118 additions and 20 deletions

View File

@@ -135,7 +135,9 @@ func TestPutBucketAcl(s *S3Conf) {
PutBucketAcl_invalid_acl_acp_and_grants(s)
PutBucketAcl_invalid_owner(s)
PutBucketAcl_success_access_denied(s)
PutBucketAcl_success(s)
PutBucketAcl_success_grants(s)
PutBucketAcl_success_canned_acl(s)
PutBucketAcl_success_acp(s)
}
func TestGetBucketAcl(s *S3Conf) {

View File

@@ -2268,8 +2268,91 @@ func PutBucketAcl_success_access_denied(s *S3Conf) {
})
}
func PutBucketAcl_success(s *S3Conf) {
testName := "PutBucketAcl_success"
func PutBucketAcl_success_canned_acl(s *S3Conf) {
testName := "PutBucketAcl_success_canned_acl"
actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
err := createUsers(s, []user{{"grt1", "grt1secret", "user"}})
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err = s3client.PutBucketAcl(ctx, &s3.PutBucketAclInput{
Bucket: &bucket,
AccessControlPolicy: &types.AccessControlPolicy{
Owner: &types.Owner{
ID: &s.awsID,
},
},
ACL: types.BucketCannedACLPublicReadWrite,
})
cancel()
if err != nil {
return err
}
newConf := *s
newConf.awsID = "grt1"
newConf.awsSecret = "grt1secret"
userClient := s3.NewFromConfig(newConf.Config())
err = putObjects(userClient, []string{"my-obj"}, bucket)
if err != nil {
return err
}
return nil
})
}
func PutBucketAcl_success_acp(s *S3Conf) {
testName := "PutBucketAcl_success_acp"
actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
err := createUsers(s, []user{{"grt1", "grt1secret", "user"}})
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err = s3client.PutBucketAcl(ctx, &s3.PutBucketAclInput{
Bucket: &bucket,
AccessControlPolicy: &types.AccessControlPolicy{
Owner: &types.Owner{
ID: &s.awsID,
},
},
GrantRead: getPtr("grt1"),
})
cancel()
if err != nil {
return err
}
newConf := *s
newConf.awsID = "grt1"
newConf.awsSecret = "grt1secret"
userClient := s3.NewFromConfig(newConf.Config())
err = putObjects(userClient, []string{"my-obj"}, bucket)
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrAccessDenied)); err != nil {
return err
}
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
_, err = userClient.HeadBucket(ctx, &s3.HeadBucketInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
return nil
})
}
func PutBucketAcl_success_grants(s *S3Conf) {
testName := "PutBucketAcl_success_grants"
actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
err := createUsers(s, []user{{"grt1", "grt1secret", "user"}})
if err != nil {

View File

@@ -294,9 +294,8 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error {
}
func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
bucket, bucketOwner, acl, grantFullControl, grantRead, grantReadACP, granWrite, grantWriteACP, access, isRoot :=
bucket, acl, grantFullControl, grantRead, grantReadACP, granWrite, grantWriteACP, access, isRoot :=
ctx.Params("bucket"),
ctx.Get("X-Amz-Expected-Bucket-Owner"),
ctx.Get("X-Amz-Acl"),
ctx.Get("X-Amz-Grant-Full-Control"),
ctx.Get("X-Amz-Grant-Read"),
@@ -309,21 +308,21 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
grants := grantFullControl + grantRead + grantReadACP + granWrite + grantWriteACP
if ctx.Request().URI().QueryArgs().Has("acl") {
parsedAcl := ctx.Locals("parsedAcl").(auth.ACL)
var input *s3.PutBucketAclInput
var accessControlPolicy auth.AccessControlPolicy
parsedAcl := ctx.Locals("parsedAcl").(auth.ACL)
if err := auth.VerifyACL(parsedAcl, bucket, access, "WRITE_ACP", isRoot); err != nil {
return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "PutBucketAcl", BucketOwner: parsedAcl.Owner})
}
if len(ctx.Body()) > 0 {
if grants+acl != "" {
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest), &MetaOpts{Logger: c.logger, Action: "PutBucketAcl", BucketOwner: parsedAcl.Owner})
}
err := xml.Unmarshal(ctx.Body(), &accessControlPolicy)
if err != nil {
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest), &MetaOpts{Logger: c.logger, Action: "PutBucketAcl", BucketOwner: parsedAcl.Owner})
}
var accessControlPolicy auth.AccessControlPolicy
err := xml.Unmarshal(ctx.Body(), &accessControlPolicy)
if err != nil {
if len(accessControlPolicy.AccessControlList.Grants) > 0 {
if grants+acl != "" {
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest), &MetaOpts{Logger: c.logger, Action: "PutBucketAcl", BucketOwner: parsedAcl.Owner})
}
@@ -337,14 +336,14 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
if acl != "private" && acl != "public-read" && acl != "public-read-write" {
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest), &MetaOpts{Logger: c.logger, Action: "PutBucketAcl", BucketOwner: parsedAcl.Owner})
}
if len(ctx.Body()) > 0 || grants != "" {
if len(accessControlPolicy.AccessControlList.Grants) > 0 || grants != "" {
return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest), &MetaOpts{Logger: c.logger, Action: "PutBucketAcl", BucketOwner: parsedAcl.Owner})
}
input = &s3.PutBucketAclInput{
Bucket: &bucket,
ACL: types.BucketCannedACL(acl),
AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &bucketOwner}},
AccessControlPolicy: &types.AccessControlPolicy{Owner: &accessControlPolicy.Owner},
}
}
if grants != "" {
@@ -355,7 +354,7 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error {
GrantReadACP: &grantReadACP,
GrantWrite: &granWrite,
GrantWriteACP: &grantWriteACP,
AccessControlPolicy: &types.AccessControlPolicy{Owner: &types.Owner{ID: &bucketOwner}},
AccessControlPolicy: &types.AccessControlPolicy{Owner: &accessControlPolicy.Owner},
ACL: "",
}
}

View File

@@ -481,6 +481,22 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
</AccessControlPolicy>
`
invOwnerBody := `
<AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Owner>
<ID>hello</ID>
</Owner>
</AccessControlPolicy>
`
succBody := `
<AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Owner>
<ID>valid access</ID>
</Owner>
</AccessControlPolicy>
`
s3ApiController := S3ApiController{
be: &BackendMock{
GetBucketAclFunc: func(context.Context, *s3.GetBucketAclInput) ([]byte, error) {
@@ -514,14 +530,12 @@ func TestS3ApiController_PutBucketActions(t *testing.T) {
errAclReq.Header.Set("X-Amz-Grant-Read", "hello")
// PutBucketAcl incorrect bucket owner case
incorrectBucketOwner := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil)
incorrectBucketOwner := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", strings.NewReader(invOwnerBody))
incorrectBucketOwner.Header.Set("X-Amz-Acl", "private")
incorrectBucketOwner.Header.Set("X-Amz-Expected-Bucket-Owner", "invalid access")
// PutBucketAcl acl success
aclSuccReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", nil)
aclSuccReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", strings.NewReader(succBody))
aclSuccReq.Header.Set("X-Amz-Acl", "private")
aclSuccReq.Header.Set("X-Amz-Expected-Bucket-Owner", "valid access")
// Invalid acl body case
errAclBodyReq := httptest.NewRequest(http.MethodPut, "/my-bucket?acl", strings.NewReader(body))