fix(kms): report accurate Vault KV2 security contract and disable unsafe rotation (#5474)

This commit is contained in:
Zhengchao An
2026-07-30 22:56:43 +08:00
committed by GitHub
parent 19cdd806a2
commit d4f2efa2ad
6 changed files with 308 additions and 50 deletions
+78
View File
@@ -0,0 +1,78 @@
# KMS backend security properties
RustFS ships several KMS backends. They differ not only in deployment effort
but in **where master key material lives and who can read it**. Pick a backend
based on the confidentiality boundary you need, not on the name alone.
## Backend comparison
| Backend | Config tag | Master key material location | At-rest protection of key material | Rotation | Intended use |
| --- | --- | --- | --- | --- | --- |
| Local | `Local` | Files under `key_dir`, encrypted with the configured local master key | Local master key (AES-GCM) + file permissions | Rejected (no versioned retention yet) | Development; single-node setups that accept host-level trust |
| Static | `Static` | Provided out-of-band via environment/file; never persisted by RustFS | Operator-managed secret distribution | Rejected (read-only backend) | Simple deployments with an external secret manager |
| Vault KV2 | `VaultKV2` (legacy alias `Vault`) | Stored **directly** in Vault KV v2 (Base64-encoded plaintext) | Vault ACLs + KV v2 at-rest encryption + TLS only | Rejected (no versioned retention yet) | Deployments that accept Vault KV ACLs as the sole confidentiality boundary |
| Vault Transit | `VaultTransit` | Key-encryption keys never leave Vault; only Transit ciphertext is visible outside | Vault Transit engine (cryptographic isolation) | Via Vault Transit key versioning | Deployments that need key material to be unreadable through storage APIs |
## Vault KV2: what the backend does and does not do
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`.
- Key rotation is rejected (`InvalidOperation`) until versioned key material
retention lands; rotating by overwriting the stored key would orphan every
DEK wrapped by the previous version.
> **Warning: KV read access is equivalent to holding the master keys.**
> Any Vault identity (token, AppRole, or policy) that can `read` the RustFS
> key path in KV v2 can recover the plaintext master key material and decrypt
> every object protected by those keys. Treat KV read grants on that path with
> the same care as handing out the keys themselves. If this is not acceptable,
> use the Vault Transit backend instead.
## Minimal Vault policy for the KV2 backend
Scope the RustFS token/AppRole to exactly the KV v2 mount and key prefix it is
configured with (defaults shown: mount `secret`, prefix `rustfs/kms/keys`),
and grant no other identity read access to that subtree:
```hcl
# RustFS KMS (Vault KV2 backend) — key storage only, no Transit access needed.
path "secret/data/rustfs/kms/keys/*" {
capabilities = ["create", "read", "update"]
}
path "secret/metadata/rustfs/kms/keys/*" {
capabilities = ["list", "read", "delete"]
}
```
Notes:
- `delete` on the metadata path is required for permanent key deletion
(`force_immediate`); drop it if you never hard-delete keys.
- Do not attach `sudo`, wildcard mounts, or Transit paths to this policy; the
KV2 backend does not use them.
- Auditing KV reads on the key prefix is strongly recommended: every read
event is a potential master-key disclosure.
## Choosing between Vault KV2 and Vault Transit
Use **Vault Transit** (`VaultTransit`) when key material must be
cryptographically isolated from anyone holding storage-level read access:
Transit keeps key-encryption keys inside Vault and only ever returns
ciphertext, and supports server-side key versioning/rotation.
Use **Vault KV2** only when you accept that the Vault ACL on the key path *is*
the confidentiality boundary and you want the operational simplicity of a
single KV mount.