docs(kms): correct the static backend's MinIO compatibility claim (#5596)

* docs(kms): correct the static backend's MinIO compatibility claim

`StaticConfig` claimed the backend derives DEKs via "HMAC-SHA256 +
AES-256-GCM, matching the MinIO builtin/static KMS wire format". Neither
half holds: the configured key is used directly as the AES-256-GCM key
with no derivation step, and wrapped DEKs are serialized as RustFS's own
`DataKeyEnvelope` JSON. MinIO's KMS ciphertext uses a different shape,
which `is_data_key_envelope` explicitly classifies as foreign (see the
`minio_legacy` case in encryption/dek.rs).

The claim as written tells a migrating operator that MinIO-written
ciphertext will open here, which it will not. Restate what the backend
actually does and point at rustfs/backlog#1638 for the real interop work.

Also refresh the neighbouring ciphertext-format note in static_kms.rs,
which still described a raw `ciphertext || nonce` layout that the JSON
envelope replaced.

* ci(minio-interop): fix the dead test selector and guard against empty runs

The job selected its tests with `-p rustfs-ecstore -E
'binary(minio_generated_read_test)'`. #5435 moved those reader tests from
crates/ecstore/tests/minio_generated_read_test.rs into the `rustfs` crate
as a `#[cfg(test)] mod`, which removed that test binary; the selector has
selected zero interop tests since. Point it at the tests where they now
live, verified locally:

  cargo nextest list --run-ignored all -p rustfs --features rio-v2 \
    -E 'test(minio_generated_read_test::)'   # 4 tests, was 0

Add a guard step in front of the run. The old `binary(...)` form happened
to fail loudly once its binary disappeared, but the name-based form that
replaces it is a valid filterset even when it matches nothing, so a later
rename would silently reduce this job to a pass that asserts nothing. The
guard counts the selection and fails with an explicit reason; the count
comes from `filter-match.status`, since the JSON's top-level `test-count`
is the package total and ignores `-E`. `--no-tests=fail` on the run step
covers the same case if the guard is ever dropped.

Also record in the header what this job does and does not prove: MinIO
wrapped-DEK envelopes are still rejected by both envelope parsers, and
that work is tracked in rustfs/backlog#1638.
This commit is contained in:
Zhengchao An
2026-08-02 05:31:30 +08:00
committed by GitHub
parent a12043f49f
commit da6fc5314d
3 changed files with 58 additions and 7 deletions
+4 -1
View File
@@ -19,7 +19,10 @@
//!
//! ## Ciphertext format
//!
//! encrypted_data(plaintext_len+16) || nonce (12 bytes)
//! A JSON-serialized `DataKeyEnvelope` carrying the AES-256-GCM ciphertext, the
//! 12-byte nonce and the authenticated encryption context. This is a
//! RustFS-internal format; it is not interchangeable with MinIO's KMS
//! ciphertext (see the note on `StaticConfig`).
use crate::backends::{BackendCapabilities, KmsBackend, empty_key_page, list_keys_page_size};
use crate::config::{BackendConfig, KmsConfig};
+9 -2
View File
@@ -297,8 +297,15 @@ impl Default for LocalConfig {
/// Static single-key KMS backend configuration
///
/// Uses a pre-configured AES-256 key to derive data encryption keys via
/// HMAC-SHA256 + AES-256-GCM, matching the MinIO builtin/static KMS wire format.
/// The configured 32-byte key is used directly as the AES-256-GCM key that
/// wraps data encryption keys — there is no HMAC-SHA256 derivation step — and
/// each wrapped DEK is serialized as a RustFS `DataKeyEnvelope` JSON blob.
///
/// This mirrors the *concept* of MinIO's builtin/static single-key KMS, but is
/// not wire-compatible with it: MinIO wraps DEKs in a different (`{"aead": ...}`)
/// blob that this backend neither produces nor accepts, so KMS ciphertext
/// written by MinIO cannot be opened here. Reading MinIO-written SSE objects is
/// tracked separately in rustfs/backlog#1638.
#[derive(Clone, Default, Serialize, Deserialize)]
pub struct StaticConfig {
/// Key identifier (name) for the single configured key