From 6d18dba9a20d6e925c1792648fa8b2702d71b5f9 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 7 May 2025 08:37:12 -0700 Subject: [PATCH] return error for AppendObject() API (#21272) --- cmd/api-router.go | 5 +++++ cmd/handler-utils.go | 25 ++++++++++++++++++++++++- cmd/metacache-stream.go | 2 +- internal/http/headers.go | 3 +++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/cmd/api-router.go b/cmd/api-router.go index da85fa155..896ca48b1 100644 --- a/cmd/api-router.go +++ b/cmd/api-router.go @@ -387,6 +387,11 @@ func registerAPIRouter(router *mux.Router) { HeadersRegexp(xhttp.AmzSnowballExtract, "true"). HandlerFunc(s3APIMiddleware(api.PutObjectExtractHandler, traceHdrsS3HFlag)) + // AppendObject to be rejected + router.Methods(http.MethodPut).Path("/{object:.+}"). + HeadersRegexp(xhttp.AmzWriteOffsetBytes, ""). + HandlerFunc(s3APIMiddleware(errorResponseHandler)) + // PutObject router.Methods(http.MethodPut).Path("/{object:.+}"). HandlerFunc(s3APIMiddleware(api.PutObjectHandler, traceHdrsS3HFlag)) diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index a69b5504b..f32574870 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -25,6 +25,7 @@ import ( "net/textproto" "regexp" "strings" + "sync/atomic" "github.com/minio/madmin-go/v3" "github.com/minio/minio/internal/auth" @@ -427,9 +428,31 @@ func errorResponseHandler(w http.ResponseWriter, r *http.Request) { HTTPStatusCode: http.StatusUpgradeRequired, }, r.URL) default: + defer logger.AuditLog(r.Context(), w, r, mustGetClaimsFromToken(r)) + defer atomic.AddUint64(&globalHTTPStats.rejectedRequestsInvalid, 1) + + // When we are not running in S3 Express mode, generate appropriate error + // for x-amz-write-offset HEADER specified. + if _, ok := r.Header[xhttp.AmzWriteOffsetBytes]; ok { + tc, ok := r.Context().Value(mcontext.ContextTraceKey).(*mcontext.TraceCtxt) + if ok { + tc.FuncName = "s3.AppendObject" + tc.ResponseRecorder.LogErrBody = true + } + + writeErrorResponse(r.Context(), w, getAPIError(ErrNotImplemented), r.URL) + return + } + + tc, ok := r.Context().Value(mcontext.ContextTraceKey).(*mcontext.TraceCtxt) + if ok { + tc.FuncName = "s3.ValidRequest" + tc.ResponseRecorder.LogErrBody = true + } + writeErrorResponse(r.Context(), w, APIError{ Code: "BadRequest", - Description: fmt.Sprintf("An error occurred when parsing the HTTP request %s at '%s'", + Description: fmt.Sprintf("An unsupported API call for method: %s at '%s'", r.Method, r.URL.Path), HTTPStatusCode: http.StatusBadRequest, }, r.URL) diff --git a/cmd/metacache-stream.go b/cmd/metacache-stream.go index 0925683d5..cf61895fe 100644 --- a/cmd/metacache-stream.go +++ b/cmd/metacache-stream.go @@ -758,7 +758,7 @@ func (r *metacacheReader) Close() error { return nil } -// metacacheBlockWriter collects blocks and provides a callaback to store them. +// metacacheBlockWriter collects blocks and provides a callback to store them. type metacacheBlockWriter struct { wg sync.WaitGroup streamErr error diff --git a/internal/http/headers.go b/internal/http/headers.go index 7940b34b9..9195e122e 100644 --- a/internal/http/headers.go +++ b/internal/http/headers.go @@ -181,6 +181,9 @@ const ( AmzChecksumTypeFullObject = "FULL_OBJECT" AmzChecksumTypeComposite = "COMPOSITE" + // S3 Express API related constant reject it. + AmzWriteOffsetBytes = "x-amz-write-offset-bytes" + // Post Policy related AmzMetaUUID = "X-Amz-Meta-Uuid" AmzMetaName = "X-Amz-Meta-Name"