mirror of
https://github.com/pgsty/minio.git
synced 2026-09-08 11:34:04 +03:00
codex/embedded-console-compat
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
236e163c0b |
fix: repair an undecodable SSE-C replica on retransmit
PutObjectHandler's precondition callback ran DecryptObjectInfo on the stored object before checkPreconditionsPUT, so an authenticated raw SSE-C replica overwrite was rejected when the stored version could not decrypt. A replica a pre-fix destination (issue #109) left as compress(ciphertext) or a re-encrypted body has an invalid decrypted length, so DecryptObjectInfo returned errObjectTampered and the retransmission that repairs it never ran -- the version stayed damaged through resync. #134's raw-replica exemption only covered the version/ETag duplicate check inside checkPreconditionsPUT, one step too late. Skip the stored object's decryption precondition only for a PURE raw SSE-C replica overwrite (a trusted SSE-C replica write with no public precondition), keyed on the incoming request's restored SSE-C metadata, the same predicate checkPreconditionsPUT uses. Such a write fully replaces the object, so requiring the damaged stored version to decrypt is both wrong and unnecessary. A conditional request keeps the check: DecryptObjectInfo also normalizes the stored sealed ETag to the client-visible one, and If-Match/If-None-Match must compare against that, not the sealed ETag -- skipping it for every replica inverted both conditions. Ordinary writes and non-SSE-C replicas are unchanged. Adds red/green regressions: a raw retransmit over a version staged as an undecodable body returns 500 XMinioObjectTampered before this change and 200 with full customer-key recovery after; and a conditional replica PUT (If-Match / If-None-Match) on the client-visible ETag is honoured rather than inverted. Fixes the single-PUT compression-damage recovery gap in Signed-off-by: Feng Ruohang <rh@vonng.com> #120. |
||
|
|
7220210e8d |
test: reconcile #134 fixtures with #119 and refresh the rebrand baseline
Rebased onto current main. #119 made PutObjectPart derive an encrypted part's plaintext length and reject a part that cannot be a valid sio stream, so TestReplicaLockReconcileNullVersion's completeNullMPU fixture (a 4-byte plaintext part under SSE-C metadata) no longer stores; build it with sio.Encrypt like the other encrypted-part fixtures. Also regenerate the rebrand-guard baseline for the replication SSE header the retransmit path reintroduces (headers 84 -> 85). Mechanical integration only. Signed-off-by: Feng Ruohang <rh@vonng.com> |
||
|
|
109d824e5f |
fix: retransmit and re-order Object Lock for SSE-C replicas (single erasure set)
Issue #120 routes an existing SSE-C replica through PutObjectHandler and NewMultipartUploadHandler. On main those handlers assigned the incoming retention and legal hold directly, without the source-timestamp ordering #111 added to CopyObjectHandler and without persisting the ordering timestamps, so in active-active replication a retransmit carrying an older value could overwrite a destination version's newer lock state. Share #111's ordering decision as applyReplicatedObjectLock in cmd/bucket-object-lock.go and call it from CopyObject, PUT and multipart initiation. A request that is not an actual trusted replica keeps ordinary write semantics (a validated value is applied and stamped now); only a real replica update is ordered against the stored version, so a marker-only peer write no longer drops a validated hold or default retention. CopyObject keeps its SSE-C key-rotation encMetadata reconciliation inline. putReplicationOpts now emits a stored retention ordering timestamp even when the value keys are absent, so a removal recorded on the retransmit PUT path still replicates onward. replicateAll marks Failed and carries the error when putReplicationOpts fails. The handler decision is made against the version as it stands then, which a concurrent lock update can outrun before the write commits, and for multipart across the whole initiation-to-completion span. Close that window under the object write lock the receiving erasure set holds: a trusted SSE-C replica full write sets ObjectOptions.ReplicaLockReconcile, and erasureObjects.PutObject and CompleteMultipartUpload re-run the ordering (reconcileStoredObjectLock, which orders retention and legal hold independently by their reserved timestamps) against the destination version read on that set before committing. Persisted upload metadata records the null version as an empty VersionID, so completion looks that up as the null version rather than the latest. The reconcile runs only against an existing version; a not-found destination keeps the write's own accepted lock, including a pre-upgrade upload that persisted values without ordering timestamps, and a non-not-found read error fails the write. Scoped to the SSE-C paths this issue enables; CopyObject is left as #111 wrote it. Scope: this orders Object Lock against the destination version under the write lock and is correct for a single erasure set. A multi-pool deployment -- where a version can have duplicate copies across pools, object ModTime ties do not track per-field lock timestamps, and the object namespace lock is per-pool -- needs a cross-pool lock-safe reconcile and is deliberately out of scope here, tracked in pgsty/silo#TBD-multipool-lock. Tests: TestAPISSECReplicaRetransmitObjectLockOrdering and its multipart sibling; TestAPIReplicaMultipartNewerHoldSurvivesCompletion and TestReplicaPutObjectLockReconcileUnderWriteLock (a hold or retention reaching the version after the handler decision, or after multipart initiation, survives the commit; a pre-upgrade upload on an absent version keeps its lock); TestReplicaLockReconcileNullVersion (a null-version completion reconciles the null version, not a coexisting UUID version, and an absent null version keeps its accepted lock); TestAPIReplicaMarkerOnlyAppliesObjectLock; TestReplicaStoredLock; the timestamp-only putReplicationOpts round trip; and the retransmit, exemption and target-head tests. The #111 CopyObject replica suite and the existing #120 suite stay green, as do the PUT/multipart handler and object-layer regression suites. Compatibility: the shared helper preserves #111's CopyObject behavior; a non-replica PUT or multipart initiation that sets Object Lock now also stamps the reserved ordering timestamp, matching CopyObject since #111; only trusted SSE-C replica writes take the in-lock reconcile. Refs pgsty/silo#120 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L7qJqWwy8oFA6aCXWRzXQe Signed-off-by: Feng Ruohang <rh@vonng.com> |
||
|
|
87746913fc |
fix: retransmit existing SSE-C replicas instead of metadata-copying them
The replication sender's target HEAD carries no SSE-C customer key, so for
an SSE-C object the target answers 400 and replicateAll fell into a
metadata-only CopyObject that fails on any non-empty SSE-C object (the
undecryptable source checksum makes the target recompute one and rewrite
the data with a plaintext-sized reader). Once a non-empty SSE-C replica
existed, tag, retention and legal-hold changes never reached it, a heal
never retransmitted, and a resync neither repaired the replica nor
counted it correctly. Forcing a full retransmit alone was not enough:
checkPreconditionsPUT rejects a write whose PreserveETag and VersionID
match the stored version, only the single-part sealed ETag is truncated
before that comparison, so a multipart SSE-C retransmit answered 412,
which the sender turns into success. Inherited from upstream
|