From 8bb147cb709efdad993857d0325df62e7bd5eee5 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Sun, 2 Aug 2026 11:28:15 +0800 Subject: [PATCH] docs(kms): drop claims about an interface that no longer exists (#5602) docs(kms): correct the KV2 at-rest boundary and rotation rejection claims The Vault KV2 section claimed the backend reports its confidentiality boundary as `at_rest_protection: vault-kv2-acl` through `backend_info`. That accessor, the `BackendInfo` type and its assertion test were removed in rustfs/rustfs#5501, and no replacement reports the boundary. State instead that the boundary is documented only, that `kms/status` exposes a capability matrix covering supported operations rather than key-material location, and that the backup manifest's `at_rest_protection` field is a bundle declaration rather than a backend self-report. The rotation section named `InvalidOperation` as the error Local and Static return. Neither advertises `rotate`, so the product path falls to the shared `KmsBackend` default and returns `UnsupportedCapability`; `InvalidOperation` survives only in a test-only client helper. --- crates/kms/src/backup/capability.rs | 7 ++++--- docs/operations/kms-backend-security.md | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/kms/src/backup/capability.rs b/crates/kms/src/backup/capability.rs index 97ea531bc..342c93ebb 100644 --- a/crates/kms/src/backup/capability.rs +++ b/crates/kms/src/backup/capability.rs @@ -65,9 +65,10 @@ pub enum AtRestProtection { /// for bundling purposes: re-wrap is mandatory. LegacyUnspecified, /// Vault KV2 as currently shipped: material confidentiality relies on - /// Vault ACLs, KV2 at-rest encryption, and TLS only (the backend reports - /// `at_rest_protection = "vault-kv2-acl"`); RustFS applies no - /// cryptographic wrapping of its own. + /// Vault ACLs, KV2 at-rest encryption, and TLS only; RustFS applies no + /// cryptographic wrapping of its own. The backend reports nothing about + /// that boundary at runtime, so this value is a backup-manifest + /// declaration, not a backend self-report. StorageOnly, /// Vault KV2 with material wrapped by Vault Transit before storage. Not /// produced by any current backend; the row exists so a future direction diff --git a/docs/operations/kms-backend-security.md b/docs/operations/kms-backend-security.md index f825ded19..9d40d8c77 100644 --- a/docs/operations/kms-backend-security.md +++ b/docs/operations/kms-backend-security.md @@ -21,7 +21,8 @@ The Vault KV2 backend uses Vault purely as a **secure storage** service: - Master key material is generated by RustFS and written to KV v2 as a Base64-encoded value (`encrypted_key_material` is an encoding, not a ciphertext). - The backend never calls the Vault Transit engine. The `mount_path` configuration field and the `RUSTFS_KMS_VAULT_MOUNT_PATH` environment variable are deprecated leftovers: they are accepted for compatibility and ignored. - Data-encryption keys (DEKs) handed to the object-encryption path are still wrapped with AES-256-GCM under the master key; the statement above concerns the master key's storage in Vault, not the DEK envelope. -- The backend reports this boundary in its `backend_info` metadata as `at_rest_protection: vault-kv2-acl`. +- No runtime interface reports this boundary. `GET /rustfs/admin/v3/kms/status` names the active backend (`backend_type: vault-kv2`) and returns a `capabilities` matrix, but that matrix enumerates only the operations the backend supports — nothing in it describes where master key material lives or who can read it. Determining which confidentiality boundary is in force means reading `backend_type` and applying the comparison table above; this document is the only statement of the boundary an operator can consult. +- The `at_rest_protection: storage-only` field carried by a KMS backup manifest is a different thing: it declares the protection state of key material inside a backup bundle, not a property the running backend reports about itself. - Key rotation retains every historical master key version as an immutable record under `{prefix}/{key_id}/versions/{N}` and only then moves the current-version pointer; see [Master key rotation](#master-key-rotation-retention-destruction-and-upgrade-ordering) for the retention preconditions and the cluster-upgrade ordering constraint. > **Warning: KV read access is equivalent to holding the master keys.** @@ -51,7 +52,7 @@ Notes: ## Master key rotation: retention, destruction, and upgrade ordering -Rotation support differs per backend. Local and Static reject rotation outright (`InvalidOperation`); their single key material is never overwritten. Vault Transit delegates rotation to the Transit engine's own key versioning (ciphertext is version-prefixed, e.g. `vault:v1:...`). Vault KV2 rotates by retaining every historical version, as described below. Rotation is reachable through the admin API as `POST /rustfs/admin/v3/kms/keys/rotate`, which the route policy classifies as high risk and gates behind `kms:RotateKey`; it is not exposed through the S3 surface. The upgrade ordering constraint below therefore applies to an operator action, not only to a call from inside the process. +Rotation support differs per backend. Local and Static advertise no `rotate` capability — `capabilities.rotate` is false in the `kms/status` response — and reject rotation with `UnsupportedCapability`; their single key material is never overwritten. Vault Transit delegates rotation to the Transit engine's own key versioning (ciphertext is version-prefixed, e.g. `vault:v1:...`). Vault KV2 rotates by retaining every historical version, as described below. Rotation is reachable through the admin API as `POST /rustfs/admin/v3/kms/keys/rotate`, which the route policy classifies as high risk and gates behind `kms:RotateKey`; it is not exposed through the S3 surface. The upgrade ordering constraint below therefore applies to an operator action, not only to a call from inside the process. ### Vault KV2 versioned retention model