feat: Closes #441, Added access control integration tests, fixed some bugs in bucket policy and acl access checking flow

This commit is contained in:
jonaustin09
2024-03-28 14:52:56 -04:00
parent 0011ccd80e
commit e6203c5765
8 changed files with 376 additions and 49 deletions
+15 -11
View File
@@ -206,15 +206,6 @@ func splitUnique(s, divider string) []string {
}
func verifyACL(acl ACL, access string, permission types.Permission) error {
// Default disabled ACL case
if acl.ACL == "" && len(acl.Grantees) == 0 {
if acl.Owner == access {
return nil
}
return s3err.GetAPIError(s3err.ErrAccessDenied)
}
if acl.ACL != "" {
if (permission == "READ" || permission == "READ_ACP") && (acl.ACL != "public-read" && acl.ACL != "public-read-write") {
return s3err.GetAPIError(s3err.ErrAccessDenied)
@@ -225,6 +216,9 @@ func verifyACL(acl ACL, access string, permission types.Permission) error {
return nil
} else {
if len(acl.Grantees) == 0 {
return nil
}
grantee := Grantee{Access: access, Permission: permission}
granteeFullCtrl := Grantee{Access: access, Permission: "FULL_CONTROL"}
@@ -298,10 +292,20 @@ func VerifyAccess(ctx context.Context, be backend.Backend, opts AccessOptions) e
return nil
}
if err := verifyACL(opts.Acl, opts.Acc.Access, opts.AclPermission); err != nil {
policy, err := be.GetBucketPolicy(ctx, opts.Bucket)
if err != nil {
return err
}
if err := verifyBucketPolicy(ctx, be, opts.Acc.Access, opts.Bucket, opts.Object, opts.Action); err != nil {
// If bucket policy is not set and the ACL is default, only the owner has access
if len(policy) == 0 && 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 {
return err
}
+14 -19
View File
@@ -15,12 +15,10 @@
package auth
import (
"context"
"encoding/json"
"fmt"
"net/http"
"github.com/versity/versitygw/backend"
"github.com/versity/versitygw/s3err"
)
@@ -41,8 +39,13 @@ func (bp *BucketPolicy) Validate(bucket string, iam IAMService) error {
func (bp *BucketPolicy) isAllowed(principal string, action Action, resource string) bool {
for _, statement := range bp.Statement {
if statement.isAllowed(principal, action, resource) {
return true
if statement.findMatch(principal, action, resource) {
switch statement.Effect {
case BucketPolicyAccessTypeAllow:
return true
case BucketPolicyAccessTypeDeny:
return false
}
}
}
@@ -83,14 +86,9 @@ func (bpi *BucketPolicyItem) Validate(bucket string, iam IAMService) error {
return nil
}
func (bpi *BucketPolicyItem) isAllowed(principal string, action Action, resource string) bool {
func (bpi *BucketPolicyItem) findMatch(principal string, action Action, resource string) bool {
if bpi.Principals.Contains(principal) && bpi.Actions.FindMatch(action) && bpi.Resources.FindMatch(resource) {
switch bpi.Effect {
case BucketPolicyAccessTypeAllow:
return true
case BucketPolicyAccessTypeDeny:
return false
}
return true
}
return false
@@ -117,26 +115,23 @@ func ValidatePolicyDocument(policyBin []byte, bucket string, iam IAMService) err
return nil
}
func verifyBucketPolicy(ctx context.Context, be backend.Backend, access, bucket, object string, action Action) error {
policyDoc, err := be.GetBucketPolicy(ctx, bucket)
if err != nil {
return err
}
func verifyBucketPolicy(policy []byte, access, bucket, object string, action Action) error {
// If bucket policy is not set
if len(policyDoc) == 0 {
if len(policy) == 0 {
return nil
}
var bucketPolicy BucketPolicy
if err := json.Unmarshal(policyDoc, &bucketPolicy); err != nil {
if err := json.Unmarshal(policy, &bucketPolicy); err != nil {
return err
}
resource := bucket
if object != "" {
resource += "" + object
resource += "/" + object
}
fmt.Println(access, action, resource)
if !bucketPolicy.isAllowed(access, action, resource) {
return s3err.GetAPIError(s3err.ErrAccessDenied)
}