diff options
Diffstat (limited to 'weed/s3api/s3api_object_handlers_copy.go')
| -rw-r--r-- | weed/s3api/s3api_object_handlers_copy.go | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/weed/s3api/s3api_object_handlers_copy.go b/weed/s3api/s3api_object_handlers_copy.go index 4dd31c8ce..0c465d3db 100644 --- a/weed/s3api/s3api_object_handlers_copy.go +++ b/weed/s3api/s3api_object_handlers_copy.go @@ -171,8 +171,14 @@ func (s3a *S3ApiServer) CopyObjectHandler(w http.ResponseWriter, r *http.Request // Skip encryption-specific headers that might conflict with destination encryption type skipHeader := false + // Skip orphaned SSE-S3 headers (header exists but key is missing) + // This prevents confusion about the object's actual encryption state + if isOrphanedSSES3Header(k, entry.Extended) { + skipHeader = true + } + // If we're doing cross-encryption, skip conflicting headers - if len(entry.GetChunks()) > 0 { + if !skipHeader && len(entry.GetChunks()) > 0 { // Detect source and destination encryption types srcHasSSEC := IsSSECEncrypted(entry.Extended) srcHasSSEKMS := IsSSEKMSEncrypted(entry.Extended) @@ -297,7 +303,7 @@ func (s3a *S3ApiServer) CopyObjectHandler(w http.ResponseWriter, r *http.Request // For non-versioned destination, use regular copy // Remove any versioning-related metadata from source that shouldn't carry over cleanupVersioningMetadata(dstEntry.Extended) - + dstPath := util.FullPath(fmt.Sprintf("%s/%s%s", s3a.option.BucketsPath, dstBucket, dstObject)) dstDir, dstName := dstPath.DirAndName() @@ -2350,6 +2356,27 @@ func shouldCreateVersionForCopy(versioningState string) bool { return versioningState == s3_constants.VersioningEnabled } +// isOrphanedSSES3Header checks if a header is an orphaned SSE-S3 encryption header. +// An orphaned header is one where the encryption indicator exists but the actual key is missing. +// This can happen when an object was previously encrypted but then copied without encryption, +// leaving behind the header but removing the key. These orphaned headers should be stripped +// during copy operations to prevent confusion about the object's actual encryption state. +// Fixes GitHub issue #7562. +func isOrphanedSSES3Header(headerKey string, metadata map[string][]byte) bool { + if headerKey != s3_constants.AmzServerSideEncryption { + return false + } + + // The header is AmzServerSideEncryption. Check if its value indicates SSE-S3. + if string(metadata[headerKey]) == "AES256" { + // It's an SSE-S3 header. It's orphaned if the actual encryption key is missing. + _, hasKey := metadata[s3_constants.SeaweedFSSSES3Key] + return !hasKey + } + + return false +} + // shouldSkipEncryptionHeader determines if a header should be skipped when copying extended attributes // based on the source and destination encryption types. This consolidates the repetitive logic for // filtering encryption-related headers during copy operations. |
