diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index 5b0f88c05..fdd4781d7 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -891,9 +891,15 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http. vars := mux.Vars(r) bucket := vars["bucket"] + objectAPI := api.ObjectAPI() + if objectAPI == nil { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r)) + return + } + forceDelete := false - if vs, found := r.Header[http.CanonicalHeaderKey("x-minio-force-delete")]; found { - switch strings.ToLower(strings.Join(vs, "")) { + if value := r.Header.Get(xhttp.MinIOForceDelete); value != "" { + switch value { case "true": forceDelete = true case "false": @@ -903,14 +909,20 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http. } } - objectAPI := api.ObjectAPI() - if objectAPI == nil { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r)) - return + if forceDelete { + if s3Error := checkRequestAuthType(ctx, r, policy.ForceDeleteBucketAction, bucket, ""); s3Error != ErrNone { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) + return + } + } else { + if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketAction, bucket, ""); s3Error != ErrNone { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) + return + } } - if s3Error := checkRequestAuthType(ctx, r, policy.DeleteBucketAction, bucket, ""); s3Error != ErrNone { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) + if _, ok := globalBucketObjectLockConfig.Get(bucket); (ok || globalWORMEnabled) && forceDelete { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r)) return } diff --git a/cmd/http/headers.go b/cmd/http/headers.go index c8f34cd1c..26585e0a0 100644 --- a/cmd/http/headers.go +++ b/cmd/http/headers.go @@ -106,4 +106,7 @@ const ( // Server-Status MinIOServerStatus = "x-minio-server-status" + + // Delete special flag + MinIOForceDelete = "x-minio-force-delete" ) diff --git a/pkg/bucket/policy/action.go b/pkg/bucket/policy/action.go index c27c054f9..c52568b35 100644 --- a/pkg/bucket/policy/action.go +++ b/pkg/bucket/policy/action.go @@ -37,6 +37,10 @@ const ( // DeleteBucketAction - DeleteBucket Rest API action. DeleteBucketAction = "s3:DeleteBucket" + // ForceDeleteBucketAction - DeleteBucket Rest API action when x-minio-force-delete flag + // is specified. + ForceDeleteBucketAction = "s3:ForceDeleteBucket" + // DeleteBucketPolicyAction - DeleteBucketPolicy Rest API action. DeleteBucketPolicyAction = "s3:DeleteBucketPolicy" @@ -146,6 +150,7 @@ var supportedActions = map[Action]struct{}{ AbortMultipartUploadAction: {}, CreateBucketAction: {}, DeleteBucketAction: {}, + ForceDeleteBucketAction: {}, DeleteBucketPolicyAction: {}, DeleteObjectAction: {}, GetBucketLocationAction: {}, diff --git a/pkg/iam/policy/action.go b/pkg/iam/policy/action.go index 65467ca46..35d133472 100644 --- a/pkg/iam/policy/action.go +++ b/pkg/iam/policy/action.go @@ -38,6 +38,10 @@ const ( // DeleteBucketAction - DeleteBucket Rest API action. DeleteBucketAction = "s3:DeleteBucket" + // ForceDeleteBucketAction - DeleteBucket Rest API action when x-minio-force-delete flag + // is specified. + ForceDeleteBucketAction = "s3:ForceDeleteBucket" + // DeleteBucketPolicyAction - DeleteBucketPolicy Rest API action. DeleteBucketPolicyAction = "s3:DeleteBucketPolicy" @@ -136,6 +140,7 @@ var supportedActions = map[Action]struct{}{ AbortMultipartUploadAction: {}, CreateBucketAction: {}, DeleteBucketAction: {}, + ForceDeleteBucketAction: {}, DeleteBucketPolicyAction: {}, DeleteObjectAction: {}, GetBucketLocationAction: {},