mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-11 07:36:53 +00:00
Fix KMS configuration synchronization across cluster nodes (#855)
* Initial plan * Add KMS configuration persistence to cluster storage Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * Apply code formatting to KMS configuration changes Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * add comment * fix fmt * fix * Fix overlapping dependabot cargo configurations Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> * improve code for comment and replace `Once_Cell` to `std::sync::OnceLock` --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <4829346+houseme@users.noreply.github.com> Co-authored-by: houseme <housemecn@gmail.com> Co-authored-by: loverustfs <155562731+loverustfs@users.noreply.github.com>
This commit is contained in:
@@ -19,14 +19,65 @@ use crate::admin::auth::validate_admin_request;
|
||||
use crate::auth::{check_key_valid, get_session_token};
|
||||
use hyper::StatusCode;
|
||||
use matchit::Params;
|
||||
use rustfs_ecstore::config::com::{read_config, save_config};
|
||||
use rustfs_ecstore::new_object_layer_fn;
|
||||
use rustfs_kms::{
|
||||
ConfigureKmsRequest, ConfigureKmsResponse, KmsConfigSummary, KmsServiceStatus, KmsStatusResponse, StartKmsRequest,
|
||||
ConfigureKmsRequest, ConfigureKmsResponse, KmsConfig, KmsConfigSummary, KmsServiceStatus, KmsStatusResponse, StartKmsRequest,
|
||||
StartKmsResponse, StopKmsResponse, get_global_kms_service_manager,
|
||||
};
|
||||
use rustfs_policy::policy::action::{Action, AdminAction};
|
||||
use s3s::{Body, S3Request, S3Response, S3Result, s3_error};
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
/// Path to store KMS configuration in the cluster metadata
|
||||
const KMS_CONFIG_PATH: &str = "config/kms_config.json";
|
||||
|
||||
/// Save KMS configuration to cluster storage
|
||||
async fn save_kms_config(config: &KmsConfig) -> Result<(), String> {
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
return Err("Storage layer not initialized".to_string());
|
||||
};
|
||||
|
||||
let data = serde_json::to_vec(config).map_err(|e| format!("Failed to serialize KMS config: {e}"))?;
|
||||
|
||||
save_config(store, KMS_CONFIG_PATH, data)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to save KMS config to storage: {e}"))?;
|
||||
|
||||
info!("KMS configuration persisted to cluster storage at {}", KMS_CONFIG_PATH);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load KMS configuration from cluster storage
|
||||
pub async fn load_kms_config() -> Option<KmsConfig> {
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
warn!("Storage layer not initialized, cannot load KMS config");
|
||||
return None;
|
||||
};
|
||||
|
||||
match read_config(store, KMS_CONFIG_PATH).await {
|
||||
Ok(data) => match serde_json::from_slice::<KmsConfig>(&data) {
|
||||
Ok(config) => {
|
||||
info!("Loaded KMS configuration from cluster storage");
|
||||
Some(config)
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to deserialize KMS config: {}", e);
|
||||
None
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
// Config not found is normal on first run
|
||||
if e.to_string().contains("ConfigNotFound") || e.to_string().contains("not found") {
|
||||
info!("No persisted KMS configuration found (first run or not configured yet)");
|
||||
} else {
|
||||
warn!("Failed to load KMS config from storage: {}", e);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure KMS service handler
|
||||
pub struct ConfigureKmsHandler;
|
||||
|
||||
@@ -82,11 +133,19 @@ impl Operation for ConfigureKmsHandler {
|
||||
let kms_config = configure_request.to_kms_config();
|
||||
|
||||
// Configure the service
|
||||
let (success, message, status) = match service_manager.configure(kms_config).await {
|
||||
let (success, message, status) = match service_manager.configure(kms_config.clone()).await {
|
||||
Ok(()) => {
|
||||
let status = service_manager.get_status().await;
|
||||
info!("KMS configured successfully with status: {:?}", status);
|
||||
(true, "KMS configured successfully".to_string(), status)
|
||||
// Persist the configuration to cluster storage
|
||||
if let Err(e) = save_kms_config(&kms_config).await {
|
||||
let error_msg = format!("KMS configured in memory but failed to persist: {e}");
|
||||
error!("{}", error_msg);
|
||||
let status = service_manager.get_status().await;
|
||||
(false, error_msg, status)
|
||||
} else {
|
||||
let status = service_manager.get_status().await;
|
||||
info!("KMS configured successfully and persisted with status: {:?}", status);
|
||||
(true, "KMS configured successfully".to_string(), status)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let error_msg = format!("Failed to configure KMS: {e}");
|
||||
@@ -441,11 +500,19 @@ impl Operation for ReconfigureKmsHandler {
|
||||
let kms_config = configure_request.to_kms_config();
|
||||
|
||||
// Reconfigure the service (stops, reconfigures, and starts)
|
||||
let (success, message, status) = match service_manager.reconfigure(kms_config).await {
|
||||
let (success, message, status) = match service_manager.reconfigure(kms_config.clone()).await {
|
||||
Ok(()) => {
|
||||
let status = service_manager.get_status().await;
|
||||
info!("KMS reconfigured successfully with status: {:?}", status);
|
||||
(true, "KMS reconfigured and restarted successfully".to_string(), status)
|
||||
// Persist the configuration to cluster storage
|
||||
if let Err(e) = save_kms_config(&kms_config).await {
|
||||
let error_msg = format!("KMS reconfigured in memory but failed to persist: {e}");
|
||||
error!("{}", error_msg);
|
||||
let status = service_manager.get_status().await;
|
||||
(false, error_msg, status)
|
||||
} else {
|
||||
let status = service_manager.get_status().await;
|
||||
info!("KMS reconfigured successfully and persisted with status: {:?}", status);
|
||||
(true, "KMS reconfigured and restarted successfully".to_string(), status)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let error_msg = format!("Failed to reconfigure KMS: {e}");
|
||||
|
||||
+28
-3
@@ -550,7 +550,7 @@ async fn init_kms_system(opt: &config::Opt) -> Result<()> {
|
||||
|
||||
// If KMS is enabled in configuration, configure and start the service
|
||||
if opt.kms_enable {
|
||||
info!("KMS is enabled, configuring and starting service...");
|
||||
info!("KMS is enabled via command line, configuring and starting service...");
|
||||
|
||||
// Create KMS configuration from command line options
|
||||
let kms_config = match opt.kms_backend.as_str() {
|
||||
@@ -619,9 +619,34 @@ async fn init_kms_system(opt: &config::Opt) -> Result<()> {
|
||||
.await
|
||||
.map_err(|e| Error::other(format!("Failed to start KMS: {e}")))?;
|
||||
|
||||
info!("KMS service configured and started successfully");
|
||||
info!("KMS service configured and started successfully from command line options");
|
||||
} else {
|
||||
info!("KMS service manager initialized. KMS is ready for dynamic configuration via API.");
|
||||
// Try to load persisted KMS configuration from cluster storage
|
||||
info!("Attempting to load persisted KMS configuration from cluster storage...");
|
||||
|
||||
if let Some(persisted_config) = admin::handlers::kms_dynamic::load_kms_config().await {
|
||||
info!("Found persisted KMS configuration, attempting to configure and start service...");
|
||||
|
||||
// Configure the KMS service with persisted config
|
||||
match service_manager.configure(persisted_config).await {
|
||||
Ok(()) => {
|
||||
// Start the KMS service
|
||||
match service_manager.start().await {
|
||||
Ok(()) => {
|
||||
info!("KMS service configured and started successfully from persisted configuration");
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to start KMS with persisted configuration: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to configure KMS with persisted configuration: {}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info!("No persisted KMS configuration found. KMS is ready for dynamic configuration via API.");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user