diff --git a/cmd/crypto/metadata.go b/cmd/crypto/metadata.go index 1ab5b7a2e..283e87f96 100644 --- a/cmd/crypto/metadata.go +++ b/cmd/crypto/metadata.go @@ -65,6 +65,17 @@ func RemoveInternalEntries(metadata map[string]string) { delete(metadata, S3KMSSealedKey) } +// IsSourceEncrypted returns true if the source is encrypted +func IsSourceEncrypted(metadata map[string]string) bool { + if _, ok := metadata[SSECAlgorithm]; ok { + return true + } + if _, ok := metadata[SSEHeader]; ok { + return true + } + return false +} + // IsEncrypted returns true if the object metadata indicates // that it was uploaded using some form of server-side-encryption. // diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 0fda3f460..f83ba8b56 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -1021,6 +1021,8 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re rawReader := srcInfo.Reader pReader := NewPutObjReader(srcInfo.Reader, nil, nil) + // Check if either the source is encrypted or the destination will be encrypted. + objectEncryption := crypto.IsSourceEncrypted(srcInfo.UserDefined) || crypto.IsRequested(r.Header) var encMetadata = make(map[string]string) if objectAPI.IsEncryptionSupported() && !isCompressed { // Encryption parameters not applicable for this object. @@ -1202,7 +1204,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re // if encryption is enabled we do not need explicit "REPLACE" metadata to // be enabled as well - this is to allow for key-rotation. if !isDirectiveReplace(r.Header.Get(xhttp.AmzMetadataDirective)) && !isDirectiveReplace(r.Header.Get(xhttp.AmzTagDirective)) && - srcInfo.metadataOnly && !crypto.IsEncrypted(srcInfo.UserDefined) && srcOpts.VersionID == "" { + srcInfo.metadataOnly && !crypto.IsEncrypted(srcInfo.UserDefined) && srcOpts.VersionID == "" && !objectEncryption { // If x-amz-metadata-directive is not set to REPLACE then we need // to error out if source and destination are same. writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidCopyDest), r.URL, guessIsBrowserReq(r))