mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-10 23:26:53 +00:00
feat(admin): expose KMS backup and restore behind explicit guards (#5579)
* feat(kms): add backup and restore admin API Wires the merged KMS backup contract, Local export and Local restore into the admin API: export a sealed bundle, run a zero-write restore preflight, execute a confirmed restore, roll an interrupted restore back, and report subsystem readiness. - Dedicated kms:Backup / kms:Restore actions, recorded in the admin route matrix. Neither is reachable through any other KMS action. - Restore requires two independent confirmations: an echo of the bundle manifest's backup id, and an explicitly named conflict policy (the default never writes). - The backup KEK comes from the environment and is refused when it reuses a secret of the configured backend, compared both as the literal value and as raw key bytes. - No endpoint accepts a path: bundles are addressed by a validated name under a configured root, and the restore target is always the server's own configured key directory. - Bundles now carry a sanitized configuration artifact built as an allowlist projection, so a future backend credential field cannot leak into a bundle by default. Restore verifies it and never applies it. - Audit entries go through the existing KMS admin wiring and carry identifiers only. * test(kms): pin the backup admin API gates Fixes the test KEK to a real 32-byte value and drives the export refusal from the configured backend rather than from the handle that happens to be available, so a Local handle cannot export on behalf of a backend whose material RustFS does not own.
This commit is contained in:
@@ -1765,6 +1765,10 @@ impl KmsBackend for LocalKmsBackend {
|
||||
self.client.health_check().await.map(|_| true)
|
||||
}
|
||||
|
||||
fn local_backup_client(&self) -> Option<&LocalKmsClient> {
|
||||
Some(&self.client)
|
||||
}
|
||||
|
||||
fn capabilities(&self) -> BackendCapabilities {
|
||||
// Rotation stays unadvertised until historical key versions can be
|
||||
// retained (see LocalKmsClient::rotate_key); without version history
|
||||
|
||||
@@ -241,6 +241,19 @@ pub trait KmsBackend: Send + Sync {
|
||||
async fn remove_expired_key(&self, _key_id: &str, _now: &Zoned) -> Result<ExpiredKeyRemoval> {
|
||||
Err(KmsError::unsupported_capability("backend without deletion support", "remove_expired_key"))
|
||||
}
|
||||
|
||||
/// The running client to export a full-material backup bundle from.
|
||||
///
|
||||
/// Only the Local backend owns key material RustFS is allowed to export in
|
||||
/// full (see [`crate::backup::BackupResponsibility`]); every other backend
|
||||
/// keeps its cryptographic root outside RustFS and returns `None` here.
|
||||
///
|
||||
/// The export must run against the *running* client so that its fence
|
||||
/// actually blocks concurrent create/delete work — a second client opened
|
||||
/// on the same key directory would fence nothing.
|
||||
fn local_backup_client(&self) -> Option<&local::LocalKmsClient> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Outcome of [`KmsBackend::remove_expired_key`].
|
||||
|
||||
Reference in New Issue
Block a user