diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 1a9e96007..f2fa48ef9 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -720,16 +720,17 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re return } - // Deny if WORM is enabled - if globalWORMEnabled { + cpSrcDstSame := isStringEqual(pathJoin(srcBucket, srcObject), pathJoin(dstBucket, dstObject)) + + // Deny if WORM is enabled. If operation is key rotation of SSE-S3 encrypted object + // allow the operation + if globalWORMEnabled && !(cpSrcDstSame && crypto.S3.IsRequested(r.Header)) { if _, err = objectAPI.GetObjectInfo(ctx, dstBucket, dstObject, dstOpts); err == nil { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r)) return } } - cpSrcDstSame := isStringEqual(pathJoin(srcBucket, srcObject), pathJoin(dstBucket, dstObject)) - getObjectNInfo := objectAPI.GetObjectNInfo if api.CacheAPI() != nil { getObjectNInfo = api.CacheAPI().GetObjectNInfo @@ -762,6 +763,11 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re return } + // Deny if WORM is enabled, and it is not a SSE-S3 -> SSE-S3 key rotation or if metadata replacement is requested. + if globalWORMEnabled && cpSrcDstSame && (!crypto.S3.IsEncrypted(srcInfo.UserDefined) || isMetadataReplace(r.Header)) { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r)) + return + } // We have to copy metadata only if source and destination are same. // this changes for encryption which can be observed below. if cpSrcDstSame {