Compare commits

..

1 Commits

Author SHA1 Message Date
overtrue 24b9ce0dc8 refactor(kms): drop the dead duplicate api_types::DeleteKeyRequest
api_types carried a second DeleteKeyRequest that nothing referenced: it is
absent from the lib.rs re-export list, so rustfs_kms::DeleteKeyRequest has
always resolved to types::DeleteKeyRequest through `pub use types::*`, and
the admin handler builds the real type via `use rustfs_kms::types::*`.

The copy had also drifted apart from the type it shadowed. It still called
force_immediate "for development/testing only" and described the 7-30 day
window as advisory, and it never gained the confirm_key_id field that the
immediate-deletion gate now requires. A caller that reached into api_types
and deserialized into it would silently drop confirm_key_id.

api_types::DeleteKeyResponse stays: it is live, pinned by the
kms_management_responses_have_stable_json_shapes snapshot alongside the
list/describe/cancel response shapes, and it mirrors the admin wire
response rather than duplicating types::DeleteKeyResponse, whose fields
differ. Its doc comment now records why no request twin sits beside it.
2026-08-02 10:45:08 +08:00
3 changed files with 10 additions and 19 deletions
+5 -12
View File
@@ -1343,18 +1343,11 @@ pub struct CreateKeyResponse {
pub key_metadata: KeyMetadata,
}
/// Request to delete a key
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteKeyRequest {
/// Key ID to delete
pub key_id: String,
/// Number of days to wait before deletion (7-30 days, optional)
pub pending_window_in_days: Option<u32>,
/// Force immediate deletion (for development/testing only)
pub force_immediate: Option<bool>,
}
/// Response from delete key operation
/// JSON shape returned by the admin delete-key endpoint.
///
/// The delete *request* shape lives in [`crate::types::DeleteKeyRequest`] —
/// there is deliberately no copy here, because the immediate-deletion gate
/// (`force_immediate` + `confirm_key_id`) must have exactly one definition.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteKeyResponse {
/// Success flag
+3 -4
View File
@@ -65,10 +65,9 @@ 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; 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.
/// 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.
StorageOnly,
/// Vault KV2 with material wrapped by Vault Transit before storage. Not
/// produced by any current backend; the row exists so a future direction
+2 -3
View File
@@ -21,8 +21,7 @@ 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.
- 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.
- The backend reports this boundary in its `backend_info` metadata as `at_rest_protection: vault-kv2-acl`.
- 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.**
@@ -52,7 +51,7 @@ Notes:
## Master key rotation: retention, destruction, and upgrade ordering
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.
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.
### Vault KV2 versioned retention model