diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go index 5888fe494..40dee95fb 100644 --- a/cmd/auth-handler.go +++ b/cmd/auth-handler.go @@ -363,17 +363,6 @@ func checkRequestAuthTypeWithRequestTags(ctx context.Context, r *http.Request, a return authorizeRequestWithTags(ctx, r, action, "", requestTags) } -// checkRequestAuthTypeWithVID is similar to checkRequestAuthType -// passes versionID additionally. -func checkRequestAuthTypeWithVID(ctx context.Context, r *http.Request, action policy.Action, bucketName, objectName, versionID string) (s3Err APIErrorCode) { - logger.GetReqInfo(ctx).BucketName = bucketName - logger.GetReqInfo(ctx).ObjectName = objectName - logger.GetReqInfo(ctx).VersionID = versionID - - _, _, s3Err = checkRequestAuthTypeCredential(ctx, r, action) - return s3Err -} - func authenticateRequest(ctx context.Context, r *http.Request, action policy.Action) (s3Err APIErrorCode) { if logger.GetReqInfo(ctx) == nil { bugLogIf(ctx, errors.New("unexpected context.Context does not have a logger.ReqInfo"), logger.ErrorKind) diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index ab1c4336e..c427e082b 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -465,11 +465,6 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, deleteObjectsFn := objectAPI.DeleteObjects - // Return Malformed XML as S3 spec if the number of objects is empty - if len(deleteObjectsReq.Objects) == 0 || len(deleteObjectsReq.Objects) > maxDeleteList { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMalformedXML), r.URL) - return - } reqInfo := logger.GetReqInfo(ctx) if reqInfo == nil { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) @@ -481,6 +476,11 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) return } + // Return Malformed XML as S3 spec if the number of objects is empty. + if len(deleteObjectsReq.Objects) == 0 || len(deleteObjectsReq.Objects) > maxDeleteList { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMalformedXML), r.URL) + return + } objectsToDelete := map[ObjectToDelete]int{} getObjectInfoFn := objectAPI.GetObjectInfo diff --git a/cmd/delete-version-authz_test.go b/cmd/delete-version-authz_test.go index 79fe25398..035c8e9d4 100644 --- a/cmd/delete-version-authz_test.go +++ b/cmd/delete-version-authz_test.go @@ -319,6 +319,7 @@ func testAPIDeleteObjectVersionDenyAndReplicationCompatibility(obj ObjectLayer, {"Effect":"Allow","Action":["s3:DeleteObject","s3:DeleteObjectVersion","s3:ReplicateDelete"],"Resource":["arn:aws:s3:::`+bucket+`/*"]}, {"Effect":"Deny","Action":"s3:DeleteObjectVersion","Resource":"arn:aws:s3:::`+bucket+`/deny/*"} ]`) + deleteOnly := newObjectAttributesAuthzUser(t, instanceType, bucket, `"s3:DeleteObject"`) t.Run("ordinary explicit deny wins", func(t *testing.T) { object := "deny/ordinary" @@ -351,6 +352,25 @@ func testAPIDeleteObjectVersionDenyAndReplicationCompatibility(obj ObjectLayer, t.Fatalf("status %d, want 403: %s", rec.Code, rec.Body.String()) } }) + + t.Run("marker alone cannot enter the replication path", func(t *testing.T) { + object := "replication/fake-marker" + versionID := put(t, object) + target := getDeleteObjectURL("", bucket, object) + "?" + url.Values{xhttp.VersionID: {versionID}}.Encode() + req, err := newTestSignedRequestV4(http.MethodDelete, target, 0, nil, deleteOnly.AccessKey, deleteOnly.SecretKey, + map[string]string{xhttp.MinIOSourceReplicationRequest: "true"}) + if err != nil { + t.Fatal(err) + } + rec := httptest.NewRecorder() + apiRouter.ServeHTTP(rec, req) + if rec.Code != http.StatusForbidden { + t.Fatalf("status %d, want 403: %s", rec.Code, rec.Body.String()) + } + if _, err = obj.GetObjectInfo(t.Context(), bucket, object, ObjectOptions{VersionID: versionID}); err != nil { + t.Fatalf("fake marker removed the version: %v", err) + } + }) } func newDeleteAuthzPolicyUser(t *testing.T, instanceType, bucket, statements string) auth.Credentials {