Skip to content

[P2] Federated CopyObject lets the proxy's auto-encryption override the destination bucket's default SSE #167

Description

@Vonng

Summary

On a cross-deployment CopyObject in legacy etcd bucket federation, when the proxy injects destination SSE headers into a request that supplied none, those headers suppress the destination bucket's default encryption configuration. With MINIO_KMS_AUTO_ENCRYPTION=on on the proxy:

  • the proxy adds x-amz-server-side-encryption: aws:kms (no key id) to a request that had no SSE header;
  • the remote PutObjectHandler sees an SSE header and skips its own bucket-default Apply;
  • if the remote bucket's default is SSE-KMS with a specific key, the object is sealed with the remote KMS default key instead; if the remote has no KMS, the copy fails.

A client-specified SSE header keeps winning, as it should. With auto-encryption off and no local configuration for the remote bucket, nothing is injected and the destination default applies today.

Pre-existing behaviour; #163 deliberately left sseConfig.Apply in place to keep that fix minimal. Found during the Codex post-merge review of #163 and confirmed with an experiment.

Mechanism

  • cmd/object-handlers.go line 1409: sseConfig.Apply(r.Header, sse.ApplyOptions{AutoEncrypt: globalAutoEncryption}) runs before the federation decision (remoteCallRequired is only computed around line 1529). globalBucketSSEConfigSys.Get(dstBucket) finds no local config for a remote bucket, so Apply acts on AutoEncrypt only.
  • internal/bucket/encryption/bucket-sse-config.go Apply: returns early if crypto.Requested(headers); with a nil config and AutoEncrypt it sets aws:kms.
  • The remote's PutObjectHandler runs the same Apply and returns early because the header is present.

Decision

Whose default governs a federated copy: the proxy's or the destination bucket owner's? Recommendation: the destination's. The proxy has no knowledge of the remote bucket's SSE configuration or KMS, the remote already enforces its defaults for every direct PutObject, and S3 CopyObject applies the destination bucket's default encryption when the request names none.

Proposed fix

  • Move the existing remote-copy decision ahead of the destination-default application, and for remote copies skip the local destination SSE-config lookup and Apply. Explicit destination SSE options and source decryption are unchanged. Do not change the shared BucketSSEConfig.Apply, the replication receiver PUT, source KMS decryption, or local copies.
  • Behaviour change to document: a proxy with auto-encryption on and a remote without any default encryption will store the copy unencrypted at the remote, which is what a direct PutObject to that remote does today.
  • No matching change in the multipart handlers: CopyObjectPartHandler forwards parts without applying bucket SSE defaults, and CreateMultipartUpload is routed to the bucket owner by the bucket-forwarding middleware (cmd/generic-handlers.go around line 474) before its handler applies defaults; multipart encryption is fixed at initiation and cannot be re-chosen per part. Site-replication upload forwarding is a different middleware and is out of scope.

Test plan

The shared-backend fixture cannot express "the proxy sees no destination SSE config while the destination sees its configured key": installing the remote bucket's config also makes it visible to the proxy, which would then inject the correct key id and mask the defect. Two layers:

  • A sequential unit-style test of the pipeline local Apply → SDK header construction → remote Apply with separate configuration views, asserting the header set that reaches the remote handler.
  • An integration test with the configuration view isolated per side (fixture change), using a KMS backend that distinguishes the default key from a bucket-configured key. Cover: no client SSE with remote default KMS key; explicit AES256; explicit KMS with and without key id; SSE-C; remote without KMS. Do not flip process-global switches from inside concurrent handlers.

Priority

P2: reproducible wrong key selection or copy failure under a common proxy configuration; no data loss.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions