diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go index d28c1097a..932d106d5 100644 --- a/cmd/auth-handler.go +++ b/cmd/auth-handler.go @@ -346,8 +346,26 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio // Request is allowed return the appropriate access key. return cred.AccessKey, owner, ErrNone } + + if action == policy.ListBucketVersionsAction { + // In AWS S3 s3:ListBucket permission is same as s3:ListBucketVersions permission + // verify as a fallback. + if globalPolicySys.IsAllowed(policy.Args{ + AccountName: cred.AccessKey, + Action: policy.ListBucketAction, + BucketName: bucketName, + ConditionValues: getConditionValues(r, locationConstraint, "", nil), + IsOwner: false, + ObjectName: objectName, + }) { + // Request is allowed return the appropriate access key. + return cred.AccessKey, owner, ErrNone + } + } + return cred.AccessKey, owner, ErrAccessDenied } + if globalIAMSys.IsAllowed(iampolicy.Args{ AccountName: cred.AccessKey, Action: iampolicy.Action(action), @@ -360,6 +378,22 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio // Request is allowed return the appropriate access key. return cred.AccessKey, owner, ErrNone } + if action == policy.ListBucketVersionsAction { + // In AWS S3 s3:ListBucket permission is same as s3:ListBucketVersions permission + // verify as a fallback. + if globalIAMSys.IsAllowed(iampolicy.Args{ + AccountName: cred.AccessKey, + Action: iampolicy.Action(policy.ListBucketAction), + BucketName: bucketName, + ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), + ObjectName: objectName, + IsOwner: owner, + Claims: claims, + }) { + // Request is allowed return the appropriate access key. + return cred.AccessKey, owner, ErrNone + } + } return cred.AccessKey, owner, ErrAccessDenied } diff --git a/cmd/bucket-listobjects-handlers.go b/cmd/bucket-listobjects-handlers.go index 1f83b663b..9e9a55aff 100644 --- a/cmd/bucket-listobjects-handlers.go +++ b/cmd/bucket-listobjects-handlers.go @@ -93,7 +93,7 @@ func (api objectAPIHandlers) ListObjectVersionsHandler(w http.ResponseWriter, r return } - if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { + if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketVersionsAction, bucket, ""); s3Error != ErrNone { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) return } diff --git a/pkg/bucket/policy/action.go b/pkg/bucket/policy/action.go index 277d70221..ed5eb94d7 100644 --- a/pkg/bucket/policy/action.go +++ b/pkg/bucket/policy/action.go @@ -71,6 +71,9 @@ const ( // ListBucketMultipartUploadsAction - ListMultipartUploads Rest API action. ListBucketMultipartUploadsAction = "s3:ListBucketMultipartUploads" + // ListBucketVersionsAction - ListBucket versions Rest API action. + ListBucketVersionsAction = "s3:ListBucketVersions" + // ListenNotificationAction - ListenNotification Rest API action. // This is MinIO extension. ListenNotificationAction = "s3:ListenNotification" @@ -215,6 +218,7 @@ var supportedActions = map[Action]struct{}{ HeadBucketAction: {}, ListAllMyBucketsAction: {}, ListBucketAction: {}, + ListBucketVersionsAction: {}, ListBucketMultipartUploadsAction: {}, ListenNotificationAction: {}, ListenBucketNotificationAction: {}, @@ -323,6 +327,13 @@ var actionConditionKeyMap = map[Action]condition.KeySet{ condition.S3MaxKeys, }, condition.CommonKeys...)...), + ListBucketVersionsAction: condition.NewKeySet( + append([]condition.Key{ + condition.S3Prefix, + condition.S3Delimiter, + condition.S3MaxKeys, + }, condition.CommonKeys...)...), + ListBucketMultipartUploadsAction: condition.NewKeySet(condition.CommonKeys...), ListenNotificationAction: condition.NewKeySet(condition.CommonKeys...), diff --git a/pkg/iam/policy/action.go b/pkg/iam/policy/action.go index 4ae35fdff..12a92a207 100644 --- a/pkg/iam/policy/action.go +++ b/pkg/iam/policy/action.go @@ -67,6 +67,9 @@ const ( // ListBucketAction - ListBucket Rest API action. ListBucketAction = "s3:ListBucket" + // ListBucketVersionsAction - ListBucketVersions Rest API action. + ListBucketVersionsAction = "s3:ListBucketVersions" + // ListBucketMultipartUploadsAction - ListMultipartUploads Rest API action. ListBucketMultipartUploadsAction = "s3:ListBucketMultipartUploads" @@ -194,6 +197,7 @@ var supportedActions = map[Action]struct{}{ HeadBucketAction: {}, ListAllMyBucketsAction: {}, ListBucketAction: {}, + ListBucketVersionsAction: {}, ListBucketMultipartUploadsAction: {}, ListenNotificationAction: {}, ListenBucketNotificationAction: {}, @@ -312,6 +316,13 @@ var actionConditionKeyMap = map[Action]condition.KeySet{ condition.S3MaxKeys, }, condition.CommonKeys...)...), + ListBucketVersionsAction: condition.NewKeySet( + append([]condition.Key{ + condition.S3Prefix, + condition.S3Delimiter, + condition.S3MaxKeys, + }, condition.CommonKeys...)...), + ListBucketMultipartUploadsAction: condition.NewKeySet(condition.CommonKeys...), ListenNotificationAction: condition.NewKeySet(condition.CommonKeys...),