s3api: resolve volume data encryption in CopyObject SSE flows (#11646) (#11683)

* s3api: resolve volume data encryption in CopyObject SSE flows (#11646)

* s3api: honor bucket-default KMS key on copy and fix transformed-upload metadata

- Synthesize the destination bucket's default encryption as request
  headers before any SSE evaluation, so the configured KMS key ID and
  bucket-key setting reach the copy paths instead of only a boolean.
- uploadTransformedChunkData returns the upload result so callers record
  the uploader's cipher key AND compression decision; a wrongly cleared
  IsCompressed made transformed copies unreadable.
- decompressChunkVolumeCipher fails loudly when a compressed chunk does
  not decompress, instead of uploading still-compressed bytes marked
  uncompressed.
- copyMultipartSSECChunk now strips the volume cipher and re-encrypts on
  upload like the other transform paths.
- The ciphered inner upload now uses the caller's private BytesBuffer.

* s3api: extract copy bucket-default header synthesis for coverage

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* s3api: test bucket-default encryption header synthesis on copy

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* s3api: validate copy encryption headers before bucket defaults and resolve empty KMS key

* s3api: name the AWS-managed SSE-KMS default key once

---------

Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-10-10 10:59:36 +08:00
1 parent ea65746947
commit d3dc03c85a
8 files changed
+364 -6

No files matched your search

@@ -7,6 +7,8 @@ import (
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/pb/s3_pb"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
weed_server "github.com/seaweedfs/seaweedfs/weed/server"
)
@@ -185,3 +187,29 @@ func (s3a *S3ApiServer) applyCopyBucketDefaultEncryption(state *EncryptionState,
}
}
}
// applyCopyBucketDefaultEncryptionHeaders surfaces a bucket's default
// encryption as request headers, so multi-chunk copy paths that only read
// request headers honor it too.
func applyCopyBucketDefaultEncryptionHeaders(r *http.Request, cfg *s3_pb.EncryptionConfiguration) {
if cfg == nil {
return
}
switch cfg.SseAlgorithm {
case EncryptionTypeKMS:
r.Header.Set(s3_constants.AmzServerSideEncryption, "aws:kms")
// aws:kms with no configured key resolves the AWS default, the same
// fallback applySSEKMSDefaultEncryption uses for uploads; an empty
// key ID here would let the copy paths take their plaintext branch.
keyID := cfg.KmsKeyId
if keyID == "" {
keyID = s3_constants.SSEKMSDefaultKeyID
}
r.Header.Set(s3_constants.AmzServerSideEncryptionAwsKmsKeyId, keyID)
if cfg.BucketKeyEnabled {
r.Header.Set(s3_constants.AmzServerSideEncryptionBucketKeyEnabled, "true")
}
case EncryptionTypeAES256:
r.Header.Set(s3_constants.AmzServerSideEncryption, "AES256")
}
}