From 4661af11dd1065901ce8e0a83d5cd91215daf4e8 Mon Sep 17 00:00:00 2001 From: Ben McClelland Date: Fri, 29 Sep 2023 17:00:28 -0700 Subject: [PATCH] feat: replace access/role context locals with full account info --- auth/iam.go | 2 +- auth/iam_internal.go | 6 +-- backend/posix/posix.go | 2 + s3api/controllers/admin.go | 24 ++++----- s3api/controllers/admin_test.go | 2 +- s3api/controllers/base.go | 82 ++++++++++++++--------------- s3api/controllers/base_test.go | 34 ++++++------ s3api/controllers/iam_moq_test.go | 14 ++--- s3api/middlewares/acl-parser.go | 4 +- s3api/middlewares/authentication.go | 4 +- 10 files changed, 84 insertions(+), 90 deletions(-) diff --git a/auth/iam.go b/auth/iam.go index 99748da..535649c 100644 --- a/auth/iam.go +++ b/auth/iam.go @@ -29,7 +29,7 @@ type Account struct { // //go:generate moq -out ../s3api/controllers/iam_moq_test.go -pkg controllers . IAMService type IAMService interface { - CreateAccount(access string, account Account) error + CreateAccount(account Account) error GetUserAccount(access string) (Account, error) DeleteUserAccount(access string) error ListUserAccounts() ([]Account, error) diff --git a/auth/iam_internal.go b/auth/iam_internal.go index 2b4610d..d3792c6 100644 --- a/auth/iam_internal.go +++ b/auth/iam_internal.go @@ -64,7 +64,7 @@ func NewInternal(s Storer) (*IAMServiceInternal, error) { // CreateAccount creates a new IAM account. Returns an error if the account // already exists. -func (s *IAMServiceInternal) CreateAccount(access string, account Account) error { +func (s *IAMServiceInternal) CreateAccount(account Account) error { s.mu.Lock() defer s.mu.Unlock() @@ -79,11 +79,11 @@ func (s *IAMServiceInternal) CreateAccount(access string, account Account) error conf = IAMConfig{AccessAccounts: map[string]Account{}} } - _, ok := conf.AccessAccounts[access] + _, ok := conf.AccessAccounts[account.Access] if ok { return nil, fmt.Errorf("account already exists") } - conf.AccessAccounts[access] = account + conf.AccessAccounts[account.Access] = account b, err := json.Marshal(conf) if err != nil { diff --git a/backend/posix/posix.go b/backend/posix/posix.go index 729816c..4821aaf 100644 --- a/backend/posix/posix.go +++ b/backend/posix/posix.go @@ -148,6 +148,8 @@ func (p *Posix) ListBuckets(_ context.Context, owner string, isAdmin bool) (s3re sort.Sort(backend.ByBucketName(buckets)) + fmt.Println("ListAllMyBucketsResult owner:", owner) + return s3response.ListAllMyBucketsResult{ Buckets: s3response.ListAllMyBucketsList{ Bucket: buckets, diff --git a/s3api/controllers/admin.go b/s3api/controllers/admin.go index 483f606..5f9446e 100644 --- a/s3api/controllers/admin.go +++ b/s3api/controllers/admin.go @@ -33,18 +33,18 @@ func NewAdminController(iam auth.IAMService, be backend.Backend) AdminController func (c AdminController) CreateUser(ctx *fiber.Ctx) error { access, secret, role := ctx.Query("access"), ctx.Query("secret"), ctx.Query("role") - requesterRole := ctx.Locals("role").(string) + acct := ctx.Locals("account").(auth.Account) - if requesterRole != "admin" { + if acct.Role != "admin" { return fmt.Errorf("access denied: only admin users have access to this resource") } if role != "user" && role != "admin" { return fmt.Errorf("invalid parameters: user role have to be one of the following: 'user', 'admin'") } - user := auth.Account{Secret: secret, Role: role} + user := auth.Account{Access: access, Secret: secret, Role: role} - err := c.iam.CreateAccount(access, user) + err := c.iam.CreateAccount(user) if err != nil { return fmt.Errorf("failed to create a user: %w", err) } @@ -54,8 +54,8 @@ func (c AdminController) CreateUser(ctx *fiber.Ctx) error { func (c AdminController) DeleteUser(ctx *fiber.Ctx) error { access := ctx.Query("access") - requesterRole := ctx.Locals("role").(string) - if requesterRole != "admin" { + acct := ctx.Locals("account").(auth.Account) + if acct.Role != "admin" { return fmt.Errorf("access denied: only admin users have access to this resource") } @@ -68,8 +68,8 @@ func (c AdminController) DeleteUser(ctx *fiber.Ctx) error { } func (c AdminController) ListUsers(ctx *fiber.Ctx) error { - role := ctx.Locals("role").(string) - if role != "admin" { + acct := ctx.Locals("account").(auth.Account) + if acct.Role != "admin" { return fmt.Errorf("access denied: only admin users have access to this resource") } accs, err := c.iam.ListUserAccounts() @@ -81,8 +81,8 @@ func (c AdminController) ListUsers(ctx *fiber.Ctx) error { } func (c AdminController) ChangeBucketOwner(ctx *fiber.Ctx) error { - role := ctx.Locals("role").(string) - if role != "admin" { + acct := ctx.Locals("account").(auth.Account) + if acct.Role != "admin" { return fmt.Errorf("access denied: only admin users have access to this resource") } owner := ctx.Query("owner") @@ -105,8 +105,8 @@ func (c AdminController) ChangeBucketOwner(ctx *fiber.Ctx) error { } func (c AdminController) ListBuckets(ctx *fiber.Ctx) error { - role := ctx.Locals("role").(string) - if role != "admin" { + acct := ctx.Locals("account").(auth.Account) + if acct.Role != "admin" { return fmt.Errorf("access denied: only admin users have access to this resource") } diff --git a/s3api/controllers/admin_test.go b/s3api/controllers/admin_test.go index fc918a8..35edef0 100644 --- a/s3api/controllers/admin_test.go +++ b/s3api/controllers/admin_test.go @@ -33,7 +33,7 @@ func TestAdminController_CreateUser(t *testing.T) { adminController := AdminController{ iam: &IAMServiceMock{ - CreateAccountFunc: func(access string, account auth.Account) error { + CreateAccountFunc: func(account auth.Account) error { return nil }, }, diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index f64820b..5b3a308 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -53,8 +53,8 @@ func New(be backend.Backend, iam auth.IAMService, logger s3log.AuditLogger, evs } func (c S3ApiController) ListBuckets(ctx *fiber.Ctx) error { - access, role := ctx.Locals("access").(string), ctx.Locals("role").(string) - res, err := c.be.ListBuckets(ctx.Context(), access, role == "admin") + acct := ctx.Locals("account").(auth.Account) + res, err := c.be.ListBuckets(ctx.Context(), acct.Access, acct.Role == "admin") return SendXMLResponse(ctx, res, err, &MetaOpts{Logger: c.logger, Action: "ListBucket"}) } @@ -66,7 +66,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { maxParts := ctx.QueryInt("max-parts", 0) partNumberMarker := ctx.Query("part-number-marker") acceptRange := ctx.Get("Range") - access := ctx.Locals("access").(string) + acct := ctx.Locals("account").(auth.Account) isRoot := ctx.Locals("isRoot").(bool) parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) if keyEnd != "" { @@ -74,7 +74,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { } if ctx.Request().URI().QueryArgs().Has("tagging") { - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "GetObjectTagging", BucketOwner: parsedAcl.Owner}) } @@ -102,7 +102,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { } } - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "ListParts", BucketOwner: parsedAcl.Owner}) } @@ -117,7 +117,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { } if ctx.Request().URI().QueryArgs().Has("acl") { - if err := auth.VerifyACL(parsedAcl, access, "READ_ACP", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ_ACP", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "GetObjectAcl", BucketOwner: parsedAcl.Owner}) } res, err := c.be.GetObjectAcl(ctx.Context(), &s3.GetObjectAclInput{ @@ -128,7 +128,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { } if attrs := ctx.Get("X-Amz-Object-Attributes"); attrs != "" { - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "GetObjectAttributes", BucketOwner: parsedAcl.Owner}) } var oattrs []types.ObjectAttributes @@ -143,7 +143,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { return SendXMLResponse(ctx, res, err, &MetaOpts{Logger: c.logger, Action: "GetObjectAttributes", BucketOwner: parsedAcl.Owner}) } - if err := auth.VerifyACL(parsedAcl, access, "READ_ACP", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ_ACP", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "GetObject", BucketOwner: parsedAcl.Owner}) } @@ -224,12 +224,12 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error { keyMarker := ctx.Query("key-marker") maxUploadsStr := ctx.Query("max-uploads") uploadIdMarker := ctx.Query("upload-id-marker") - access := ctx.Locals("access").(string) + acct := ctx.Locals("account").(auth.Account) isRoot := ctx.Locals("isRoot").(bool) parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) if ctx.Request().URI().QueryArgs().Has("acl") { - if err := auth.VerifyACL(parsedAcl, access, "READ_ACP", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ_ACP", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "GetBucketAcl", BucketOwner: parsedAcl.Owner}) } @@ -243,7 +243,7 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error { } if ctx.Request().URI().QueryArgs().Has("uploads") { - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "ListMultipartUploads", BucketOwner: parsedAcl.Owner}) } maxUploads, err := utils.ParseUint(maxUploadsStr) @@ -266,7 +266,7 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error { } if ctx.QueryInt("list-type") == 2 { - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "ListObjectsV2", BucketOwner: parsedAcl.Owner}) } maxkeys, err := utils.ParseUint(maxkeysStr) @@ -287,7 +287,7 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error { return SendXMLResponse(ctx, res, err, &MetaOpts{Logger: c.logger, Action: "ListObjectsV2", BucketOwner: parsedAcl.Owner}) } - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "ListObjects", BucketOwner: parsedAcl.Owner}) } @@ -311,7 +311,7 @@ func (c S3ApiController) ListActions(ctx *fiber.Ctx) error { } func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error { - bucket, acl, grantFullControl, grantRead, grantReadACP, granWrite, grantWriteACP, access, isRoot := + bucket, acl, grantFullControl, grantRead, grantReadACP, granWrite, grantWriteACP, acct, isRoot := ctx.Params("bucket"), ctx.Get("X-Amz-Acl"), ctx.Get("X-Amz-Grant-Full-Control"), @@ -319,7 +319,7 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error { ctx.Get("X-Amz-Grant-Read-Acp"), ctx.Get("X-Amz-Grant-Write"), ctx.Get("X-Amz-Grant-Write-Acp"), - ctx.Locals("access").(string), + ctx.Locals("account").(auth.Account), ctx.Locals("isRoot").(bool) grants := grantFullControl + grantRead + grantReadACP + granWrite + grantWriteACP @@ -329,7 +329,7 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error { var accessControlPolicy auth.AccessControlPolicy parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) - if err := auth.VerifyACL(parsedAcl, access, "WRITE_ACP", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE_ACP", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "PutBucketAcl", BucketOwner: parsedAcl.Owner}) } @@ -391,9 +391,9 @@ func (c S3ApiController) PutBucketActions(ctx *fiber.Ctx) error { err := c.be.CreateBucket(ctx.Context(), &s3.CreateBucketInput{ Bucket: &bucket, - ObjectOwnership: types.ObjectOwnership(access), + ObjectOwnership: types.ObjectOwnership(acct.Access), }) - return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "CreateBucket", BucketOwner: access}) + return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "CreateBucket", BucketOwner: acct.Access}) } func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { @@ -401,7 +401,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { keyStart := ctx.Params("key") keyEnd := ctx.Params("*1") uploadId := ctx.Query("uploadId") - access := ctx.Locals("access").(string) + acct := ctx.Locals("account").(auth.Account) isRoot := ctx.Locals("isRoot").(bool) parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) tagging := ctx.Get("x-amz-tagging") @@ -452,7 +452,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { tags[tag.Key] = tag.Value } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "PutObjectTagging", BucketOwner: parsedAcl.Owner}) } @@ -490,7 +490,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidPart), &MetaOpts{Logger: c.logger, Action: "UploadPart", BucketOwner: parsedAcl.Owner}) } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "UploadPart", BucketOwner: parsedAcl.Owner}) } @@ -574,7 +574,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { } if copySource != "" { - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "CopyObject", BucketOwner: parsedAcl.Owner}) } @@ -604,7 +604,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { CopySourceIfNoneMatch: ©SrcIfNoneMatch, CopySourceIfModifiedSince: &mtime, CopySourceIfUnmodifiedSince: &umtime, - ExpectedBucketOwner: &access, + ExpectedBucketOwner: &acct.Access, Metadata: metadata, }) if err == nil { @@ -628,7 +628,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { metadata := utils.GetUserMetaData(&ctx.Request().Header) - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "PutObject", BucketOwner: parsedAcl.Owner}) } @@ -659,9 +659,9 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { } func (c S3ApiController) DeleteBucket(ctx *fiber.Ctx) error { - bucket, access, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("access").(string), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) + bucket, acct, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("account").(auth.Account), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "DeleteBucket", BucketOwner: parsedAcl.Owner}) } @@ -672,14 +672,14 @@ func (c S3ApiController) DeleteBucket(ctx *fiber.Ctx) error { } func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) error { - bucket, access, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("access").(string), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) + bucket, acct, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("account").(auth.Account), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) var dObj s3response.DeleteObjects if err := xml.Unmarshal(ctx.Body(), &dObj); err != nil { return SendResponse(ctx, s3err.GetAPIError(s3err.ErrInvalidRequest), &MetaOpts{Logger: c.logger, Action: "DeleteObjects", BucketOwner: parsedAcl.Owner}) } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "DeleteObjects", BucketOwner: parsedAcl.Owner}) } @@ -697,7 +697,7 @@ func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error { key := ctx.Params("key") keyEnd := ctx.Params("*1") uploadId := ctx.Query("uploadId") - access := ctx.Locals("access").(string) + acct := ctx.Locals("account").(auth.Account) isRoot := ctx.Locals("isRoot").(bool) parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) @@ -706,7 +706,7 @@ func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error { } if ctx.Request().URI().QueryArgs().Has("tagging") { - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "RemoveObjectTagging", BucketOwner: parsedAcl.Owner}) } @@ -724,7 +724,7 @@ func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error { if uploadId != "" { expectedBucketOwner, requestPayer := ctx.Get("X-Amz-Expected-Bucket-Owner"), ctx.Get("X-Amz-Request-Payer") - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "AbortMultipartUpload", BucketOwner: parsedAcl.Owner}) } @@ -738,7 +738,7 @@ func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "AbortMultipartUpload", BucketOwner: parsedAcl.Owner, Status: 204}) } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "DeleteObject", BucketOwner: parsedAcl.Owner}) } @@ -757,9 +757,9 @@ func (c S3ApiController) DeleteActions(ctx *fiber.Ctx) error { } func (c S3ApiController) HeadBucket(ctx *fiber.Ctx) error { - bucket, access, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("access").(string), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) + bucket, acct, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("account").(auth.Account), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "HeadBucket", BucketOwner: parsedAcl.Owner}) } @@ -775,14 +775,14 @@ const ( ) func (c S3ApiController) HeadObject(ctx *fiber.Ctx) error { - bucket, access, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("access").(string), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) + bucket, acct, isRoot, parsedAcl := ctx.Params("bucket"), ctx.Locals("account").(auth.Account), ctx.Locals("isRoot").(bool), ctx.Locals("parsedAcl").(auth.ACL) key := ctx.Params("key") keyEnd := ctx.Params("*1") if keyEnd != "" { key = strings.Join([]string{key, keyEnd}, "/") } - if err := auth.VerifyACL(parsedAcl, access, "READ", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "READ", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "HeadObject", BucketOwner: parsedAcl.Owner}) } @@ -841,7 +841,7 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error { key := ctx.Params("key") keyEnd := ctx.Params("*1") uploadId := ctx.Query("uploadId") - access := ctx.Locals("access").(string) + acct := ctx.Locals("account").(auth.Account) isRoot := ctx.Locals("isRoot").(bool) parsedAcl := ctx.Locals("parsedAcl").(auth.ACL) @@ -856,7 +856,7 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "RestoreObject", BucketOwner: parsedAcl.Owner}) } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "RestoreObject", BucketOwner: parsedAcl.Owner}) } @@ -884,7 +884,7 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error { }) } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "SelectObjectContent", BucketOwner: parsedAcl.Owner}) } @@ -914,7 +914,7 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error { }) } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "CompleteMultipartUpload", BucketOwner: parsedAcl.Owner}) } @@ -945,7 +945,7 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error { } } - if err := auth.VerifyACL(parsedAcl, access, "WRITE", isRoot); err != nil { + if err := auth.VerifyACL(parsedAcl, acct.Access, "WRITE", isRoot); err != nil { return SendXMLResponse(ctx, nil, err, &MetaOpts{Logger: c.logger, Action: "CreateMultipartUpload", BucketOwner: parsedAcl.Owner}) } diff --git a/s3api/controllers/base_test.go b/s3api/controllers/base_test.go index c410e85..11e7f92 100644 --- a/s3api/controllers/base_test.go +++ b/s3api/controllers/base_test.go @@ -98,8 +98,7 @@ func TestS3ApiController_ListBuckets(t *testing.T) { } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") - ctx.Locals("role", "admin") + ctx.Locals("account", auth.Account{Access: "valid access", Role: "admin:"}) ctx.Locals("isDebug", false) return ctx.Next() }) @@ -116,8 +115,7 @@ func TestS3ApiController_ListBuckets(t *testing.T) { } appErr.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") - ctx.Locals("role", "admin") + ctx.Locals("account", auth.Account{Access: "valid access", Role: "admin:"}) ctx.Locals("isDebug", false) return ctx.Next() }) @@ -207,7 +205,7 @@ func TestS3ApiController_GetActions(t *testing.T) { }, } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -347,7 +345,7 @@ func TestS3ApiController_ListActions(t *testing.T) { } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -369,7 +367,7 @@ func TestS3ApiController_ListActions(t *testing.T) { } appError := fiber.New() appError.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -507,7 +505,7 @@ func TestS3ApiController_PutBucketActions(t *testing.T) { } // Mock ctx.Locals app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{Owner: "valid access"}) @@ -680,7 +678,7 @@ func TestS3ApiController_PutActions(t *testing.T) { }, } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -879,7 +877,7 @@ func TestS3ApiController_DeleteBucket(t *testing.T) { } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -936,7 +934,7 @@ func TestS3ApiController_DeleteObjects(t *testing.T) { } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -1013,7 +1011,7 @@ func TestS3ApiController_DeleteActions(t *testing.T) { } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -1034,7 +1032,7 @@ func TestS3ApiController_DeleteActions(t *testing.T) { }} appErr.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -1117,7 +1115,7 @@ func TestS3ApiController_HeadBucket(t *testing.T) { } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -1140,7 +1138,7 @@ func TestS3ApiController_HeadBucket(t *testing.T) { } appErr.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -1219,7 +1217,7 @@ func TestS3ApiController_HeadObject(t *testing.T) { } app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -1242,7 +1240,7 @@ func TestS3ApiController_HeadObject(t *testing.T) { } appErr.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) @@ -1322,7 +1320,7 @@ func TestS3ApiController_CreateActions(t *testing.T) { ` app.Use(func(ctx *fiber.Ctx) error { - ctx.Locals("access", "valid access") + ctx.Locals("account", auth.Account{Access: "valid access"}) ctx.Locals("isRoot", true) ctx.Locals("isDebug", false) ctx.Locals("parsedAcl", auth.ACL{}) diff --git a/s3api/controllers/iam_moq_test.go b/s3api/controllers/iam_moq_test.go index f51493b..686bb88 100644 --- a/s3api/controllers/iam_moq_test.go +++ b/s3api/controllers/iam_moq_test.go @@ -18,7 +18,7 @@ var _ auth.IAMService = &IAMServiceMock{} // // // make and configure a mocked auth.IAMService // mockedIAMService := &IAMServiceMock{ -// CreateAccountFunc: func(access string, account auth.Account) error { +// CreateAccountFunc: func(account auth.Account) error { // panic("mock out the CreateAccount method") // }, // DeleteUserAccountFunc: func(access string) error { @@ -38,7 +38,7 @@ var _ auth.IAMService = &IAMServiceMock{} // } type IAMServiceMock struct { // CreateAccountFunc mocks the CreateAccount method. - CreateAccountFunc func(access string, account auth.Account) error + CreateAccountFunc func(account auth.Account) error // DeleteUserAccountFunc mocks the DeleteUserAccount method. DeleteUserAccountFunc func(access string) error @@ -53,8 +53,6 @@ type IAMServiceMock struct { calls struct { // CreateAccount holds details about calls to the CreateAccount method. CreateAccount []struct { - // Access is the access argument value. - Access string // Account is the account argument value. Account auth.Account } @@ -79,21 +77,19 @@ type IAMServiceMock struct { } // CreateAccount calls CreateAccountFunc. -func (mock *IAMServiceMock) CreateAccount(access string, account auth.Account) error { +func (mock *IAMServiceMock) CreateAccount(account auth.Account) error { if mock.CreateAccountFunc == nil { panic("IAMServiceMock.CreateAccountFunc: method is nil but IAMService.CreateAccount was just called") } callInfo := struct { - Access string Account auth.Account }{ - Access: access, Account: account, } mock.lockCreateAccount.Lock() mock.calls.CreateAccount = append(mock.calls.CreateAccount, callInfo) mock.lockCreateAccount.Unlock() - return mock.CreateAccountFunc(access, account) + return mock.CreateAccountFunc(account) } // CreateAccountCalls gets all the calls that were made to CreateAccount. @@ -101,11 +97,9 @@ func (mock *IAMServiceMock) CreateAccount(access string, account auth.Account) e // // len(mockedIAMService.CreateAccountCalls()) func (mock *IAMServiceMock) CreateAccountCalls() []struct { - Access string Account auth.Account } { var calls []struct { - Access string Account auth.Account } mock.lockCreateAccount.RLock() diff --git a/s3api/middlewares/acl-parser.go b/s3api/middlewares/acl-parser.go index db9b6ad..43562a7 100644 --- a/s3api/middlewares/acl-parser.go +++ b/s3api/middlewares/acl-parser.go @@ -28,7 +28,7 @@ import ( func AclParser(be backend.Backend, logger s3log.AuditLogger) fiber.Handler { return func(ctx *fiber.Ctx) error { - isRoot, access := ctx.Locals("isRoot").(bool), ctx.Locals("access").(string) + isRoot, acct := ctx.Locals("isRoot").(bool), ctx.Locals("account").(auth.Account) path := ctx.Path() pathParts := strings.Split(path, "/") bucket := pathParts[1] @@ -39,7 +39,7 @@ func AclParser(be backend.Backend, logger s3log.AuditLogger) fiber.Handler { return ctx.Next() } if len(pathParts) == 2 && pathParts[1] != "" && ctx.Method() == http.MethodPut && !ctx.Request().URI().QueryArgs().Has("acl") { - if err := auth.IsAdmin(access, isRoot); err != nil { + if err := auth.IsAdmin(acct.Access, isRoot); err != nil { return controllers.SendXMLResponse(ctx, nil, err, &controllers.MetaOpts{Logger: logger, Action: "CreateBucket"}) } return ctx.Next() diff --git a/s3api/middlewares/authentication.go b/s3api/middlewares/authentication.go index 23c88c5..b485cd1 100644 --- a/s3api/middlewares/authentication.go +++ b/s3api/middlewares/authentication.go @@ -95,7 +95,6 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, logger s3log.Au }, &controllers.MetaOpts{Logger: logger}) } - ctx.Locals("access", creds[0]) ctx.Locals("isRoot", creds[0] == root.Access) _, err := time.Parse(YYYYMMDD, creds[1]) @@ -116,7 +115,7 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, logger s3log.Au if err != nil { return controllers.SendResponse(ctx, err, &controllers.MetaOpts{Logger: logger}) } - ctx.Locals("role", account.Role) + ctx.Locals("account", account) // Check X-Amz-Date header date := ctx.Get("X-Amz-Date") @@ -199,6 +198,7 @@ type accounts struct { func (a accounts) getAccount(access string) (auth.Account, error) { if access == a.root.Access { return auth.Account{ + Access: a.root.Access, Secret: a.root.Secret, Role: "admin", }, nil