mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-21 03:46:37 +00:00
feat(config): allow specifying keys via files (key files) (#1814)
Co-authored-by: houseme <housemecn@gmail.com> Co-authored-by: heihutu <30542132+heihutu@users.noreply.github.com>
This commit is contained in:
@@ -523,4 +523,82 @@ mod tests {
|
|||||||
assert_eq!(opt.server_domains[1], "127.0.0.1:9000");
|
assert_eq!(opt.server_domains[1], "127.0.0.1:9000");
|
||||||
assert_eq!(opt.server_domains[2], "localhost");
|
assert_eq!(opt.server_domains[2], "localhost");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_access_key_arguments_mutually_exclusive_cli() {
|
||||||
|
// Test that CLI args configuration fails on conflict
|
||||||
|
let args = vec![
|
||||||
|
"rustfs",
|
||||||
|
"/test/volume",
|
||||||
|
"--access-key",
|
||||||
|
"foobar",
|
||||||
|
"--access-key-file",
|
||||||
|
"/foo/bar",
|
||||||
|
];
|
||||||
|
let opt_res = Opt::try_parse_from(args);
|
||||||
|
|
||||||
|
// can't specify both access-key and access-key-file at once
|
||||||
|
assert!(opt_res.is_err());
|
||||||
|
let err = opt_res.err().unwrap();
|
||||||
|
assert_eq!(err.kind(), clap::error::ErrorKind::ArgumentConflict);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn test_access_key_arguments_mutually_exclusive_env_var() {
|
||||||
|
// Test that env var args configuration fails on conflict
|
||||||
|
with_env_var("RUSTFS_VOLUMES", "/data/my disk/vol1", || {
|
||||||
|
with_env_var("RUSTFS_ACCESS_KEY", "foo", || {
|
||||||
|
with_env_var("RUSTFS_ACCESS_KEY_FILE", "/foo/bar", || {
|
||||||
|
let args = vec!["rustfs"];
|
||||||
|
let opt_res = Opt::try_parse_from(args);
|
||||||
|
|
||||||
|
// can't specify both RUSTFS_ACCESS_KEY and RUSTFS_ACCESS_KEY_FILE at once
|
||||||
|
assert!(opt_res.is_err());
|
||||||
|
let err = opt_res.err().unwrap();
|
||||||
|
assert_eq!(err.kind(), clap::error::ErrorKind::ArgumentConflict);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_secret_key_arguments_mutually_exclusive_cli() {
|
||||||
|
// Test that CLI args configuration fails on conflict
|
||||||
|
let args = vec![
|
||||||
|
"rustfs",
|
||||||
|
"/test/volume",
|
||||||
|
"--secret-key",
|
||||||
|
"foobar",
|
||||||
|
"--secret-key-file",
|
||||||
|
"/foo/bar",
|
||||||
|
];
|
||||||
|
let opt_res = Opt::try_parse_from(args);
|
||||||
|
|
||||||
|
// can't specify both secret-key and secret-key-file at once
|
||||||
|
assert!(opt_res.is_err());
|
||||||
|
let err = opt_res.err().unwrap();
|
||||||
|
assert_eq!(err.kind(), clap::error::ErrorKind::ArgumentConflict);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn test_secret_key_arguments_mutually_exclusive_env_var() {
|
||||||
|
// Test that env var args configuration fails on conflict
|
||||||
|
with_env_var("RUSTFS_VOLUMES", "/data/my disk/vol1", || {
|
||||||
|
with_env_var("RUSTFS_SECRET_KEY", "foo", || {
|
||||||
|
with_env_var("RUSTFS_SECRET_KEY_FILE", "/foo/bar", || {
|
||||||
|
let args = vec!["rustfs"];
|
||||||
|
let opt_res = Opt::try_parse_from(args);
|
||||||
|
|
||||||
|
// can't specify both RUSTFS_SECRET_KEY and RUSTFS_SECRET_KEY_FILE at once
|
||||||
|
assert!(opt_res.is_err());
|
||||||
|
let err = opt_res.err().unwrap();
|
||||||
|
assert_eq!(err.kind(), clap::error::ErrorKind::ArgumentConflict);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+157
-14
@@ -15,6 +15,7 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clap::builder::NonEmptyStringValueParser;
|
use clap::builder::NonEmptyStringValueParser;
|
||||||
use const_str::concat;
|
use const_str::concat;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
shadow_rs::shadow!(build);
|
shadow_rs::shadow!(build);
|
||||||
|
|
||||||
@@ -77,20 +78,20 @@ pub struct Opt {
|
|||||||
pub server_domains: Vec<String>,
|
pub server_domains: Vec<String>,
|
||||||
|
|
||||||
/// Access key used for authentication.
|
/// Access key used for authentication.
|
||||||
#[arg(
|
#[arg(long, env = "RUSTFS_ACCESS_KEY", group = "access-key")]
|
||||||
long,
|
pub access_key: Option<String>,
|
||||||
default_value_t = rustfs_credentials::DEFAULT_ACCESS_KEY.to_string(),
|
|
||||||
env = "RUSTFS_ACCESS_KEY"
|
/// Access key stored in a file used for authentication.
|
||||||
)]
|
#[arg(long, env = "RUSTFS_ACCESS_KEY_FILE", group = "access-key")]
|
||||||
pub access_key: String,
|
pub access_key_file: Option<PathBuf>,
|
||||||
|
|
||||||
/// Secret key used for authentication.
|
/// Secret key used for authentication.
|
||||||
#[arg(
|
#[arg(long, env = "RUSTFS_SECRET_KEY", group = "secret-key")]
|
||||||
long,
|
pub secret_key: Option<String>,
|
||||||
default_value_t = rustfs_credentials::DEFAULT_SECRET_KEY.to_string(),
|
|
||||||
env = "RUSTFS_SECRET_KEY"
|
/// Secret key stored in a file used for authentication.
|
||||||
)]
|
#[arg(long, env = "RUSTFS_SECRET_KEY_FILE", group = "secret-key")]
|
||||||
pub secret_key: String,
|
pub secret_key_file: Option<PathBuf>,
|
||||||
|
|
||||||
/// Enable console server
|
/// Enable console server
|
||||||
#[arg(
|
#[arg(
|
||||||
@@ -161,9 +162,151 @@ pub struct Opt {
|
|||||||
pub buffer_profile: String,
|
pub buffer_profile: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for Opt {
|
#[derive(Clone)]
|
||||||
|
pub struct Config {
|
||||||
|
/// DIR points to a directory on a filesystem.
|
||||||
|
pub volumes: Vec<String>,
|
||||||
|
|
||||||
|
/// bind to a specific ADDRESS:PORT, ADDRESS can be an IP or hostname
|
||||||
|
pub address: String,
|
||||||
|
|
||||||
|
/// Domain name used for virtual-hosted-style requests.
|
||||||
|
pub server_domains: Vec<String>,
|
||||||
|
|
||||||
|
/// Access key used for authentication.
|
||||||
|
pub access_key: String,
|
||||||
|
|
||||||
|
/// Secret key used for authentication.
|
||||||
|
pub secret_key: String,
|
||||||
|
|
||||||
|
/// Enable console server
|
||||||
|
pub console_enable: bool,
|
||||||
|
|
||||||
|
/// Console server bind address
|
||||||
|
pub console_address: String,
|
||||||
|
|
||||||
|
/// Observability endpoint for trace, metrics and logs,only support grpc mode.
|
||||||
|
pub obs_endpoint: String,
|
||||||
|
|
||||||
|
/// tls path for rustfs API and console.
|
||||||
|
pub tls_path: Option<String>,
|
||||||
|
|
||||||
|
pub license: Option<String>,
|
||||||
|
|
||||||
|
pub region: Option<String>,
|
||||||
|
|
||||||
|
/// Enable KMS encryption for server-side encryption
|
||||||
|
pub kms_enable: bool,
|
||||||
|
|
||||||
|
/// KMS backend type (local or vault)
|
||||||
|
pub kms_backend: String,
|
||||||
|
|
||||||
|
/// KMS key directory for local backend
|
||||||
|
pub kms_key_dir: Option<String>,
|
||||||
|
|
||||||
|
/// Vault address for vault backend
|
||||||
|
pub kms_vault_address: Option<String>,
|
||||||
|
|
||||||
|
/// Vault token for vault backend
|
||||||
|
pub kms_vault_token: Option<String>,
|
||||||
|
|
||||||
|
/// Default KMS key ID for encryption
|
||||||
|
pub kms_default_key_id: Option<String>,
|
||||||
|
|
||||||
|
/// Disable adaptive buffer sizing with workload profiles
|
||||||
|
/// Set this flag to use legacy fixed-size buffer behavior from PR #869
|
||||||
|
pub buffer_profile_disable: bool,
|
||||||
|
|
||||||
|
/// Workload profile for adaptive buffer sizing
|
||||||
|
/// Options: GeneralPurpose, AiTraining, DataAnalytics, WebWorkload, IndustrialIoT, SecureStorage
|
||||||
|
pub buffer_profile: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
/// parse the command line arguments and environment arguments from [`Opt`] and convert them
|
||||||
|
/// into a ready to use [`Config`]
|
||||||
|
///
|
||||||
|
/// This includes some intermediate checks for mutually exclusive options
|
||||||
|
pub fn parse() -> std::io::Result<Self> {
|
||||||
|
let Opt {
|
||||||
|
volumes,
|
||||||
|
address,
|
||||||
|
server_domains,
|
||||||
|
access_key,
|
||||||
|
access_key_file,
|
||||||
|
secret_key,
|
||||||
|
secret_key_file,
|
||||||
|
console_enable,
|
||||||
|
console_address,
|
||||||
|
obs_endpoint,
|
||||||
|
tls_path,
|
||||||
|
license,
|
||||||
|
region,
|
||||||
|
kms_enable,
|
||||||
|
kms_backend,
|
||||||
|
kms_key_dir,
|
||||||
|
kms_vault_address,
|
||||||
|
kms_vault_token,
|
||||||
|
kms_default_key_id,
|
||||||
|
buffer_profile_disable,
|
||||||
|
buffer_profile,
|
||||||
|
} = Opt::parse();
|
||||||
|
|
||||||
|
let access_key = access_key
|
||||||
|
.map(Ok)
|
||||||
|
.or_else(|| {
|
||||||
|
let path = access_key_file.as_ref()?;
|
||||||
|
Some(std::fs::read_to_string(path))
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
// neither argument was specified ... using default
|
||||||
|
rustfs_credentials::DEFAULT_ACCESS_KEY.to_string()
|
||||||
|
})
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let secret_key = secret_key
|
||||||
|
.map(Ok)
|
||||||
|
.or_else(|| {
|
||||||
|
let path = secret_key_file.as_ref()?;
|
||||||
|
Some(std::fs::read_to_string(path))
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
// neither argument was specified ... using default
|
||||||
|
rustfs_credentials::DEFAULT_SECRET_KEY.to_string()
|
||||||
|
})
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
Ok(Config {
|
||||||
|
volumes,
|
||||||
|
address,
|
||||||
|
server_domains,
|
||||||
|
access_key,
|
||||||
|
secret_key,
|
||||||
|
console_enable,
|
||||||
|
console_address,
|
||||||
|
obs_endpoint,
|
||||||
|
tls_path,
|
||||||
|
license,
|
||||||
|
region,
|
||||||
|
kms_enable,
|
||||||
|
kms_backend,
|
||||||
|
kms_key_dir,
|
||||||
|
kms_vault_address,
|
||||||
|
kms_vault_token,
|
||||||
|
kms_default_key_id,
|
||||||
|
buffer_profile_disable,
|
||||||
|
buffer_profile,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Config {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("Opt")
|
f.debug_struct("Config")
|
||||||
.field("volumes", &self.volumes)
|
.field("volumes", &self.volumes)
|
||||||
.field("address", &self.address)
|
.field("address", &self.address)
|
||||||
.field("server_domains", &self.server_domains)
|
.field("server_domains", &self.server_domains)
|
||||||
|
|||||||
+16
-16
@@ -163,22 +163,22 @@ pub(crate) async fn add_bucket_notification_configuration(buckets: Vec<String>)
|
|||||||
/// If not enabled, it attempts to load any persisted KMS configuration from
|
/// If not enabled, it attempts to load any persisted KMS configuration from
|
||||||
/// cluster storage and starts the service if found.
|
/// cluster storage and starts the service if found.
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `opt` - The application configuration options
|
/// * `config` - The application configuration options
|
||||||
///
|
///
|
||||||
/// Returns `std::io::Result<()>` indicating success or failure
|
/// Returns `std::io::Result<()>` indicating success or failure
|
||||||
#[instrument(skip(opt))]
|
#[instrument(skip(config))]
|
||||||
pub(crate) async fn init_kms_system(opt: &config::Opt) -> std::io::Result<()> {
|
pub(crate) async fn init_kms_system(config: &config::Config) -> std::io::Result<()> {
|
||||||
// Initialize global KMS service manager (starts in NotConfigured state)
|
// Initialize global KMS service manager (starts in NotConfigured state)
|
||||||
let service_manager = rustfs_kms::init_global_kms_service_manager();
|
let service_manager = rustfs_kms::init_global_kms_service_manager();
|
||||||
|
|
||||||
// If KMS is enabled in configuration, configure and start the service
|
// If KMS is enabled in configuration, configure and start the service
|
||||||
if opt.kms_enable {
|
if config.kms_enable {
|
||||||
info!("KMS is enabled via command line, configuring and starting service...");
|
info!("KMS is enabled via command line, configuring and starting service...");
|
||||||
|
|
||||||
// Create KMS configuration from command line options
|
// Create KMS configuration from command line options
|
||||||
let kms_config = match opt.kms_backend.as_str() {
|
let kms_config = match config.kms_backend.as_str() {
|
||||||
"local" => {
|
"local" => {
|
||||||
let key_dir = opt
|
let key_dir = config
|
||||||
.kms_key_dir
|
.kms_key_dir
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| Error::other("KMS key directory is required for local backend"))?;
|
.ok_or_else(|| Error::other("KMS key directory is required for local backend"))?;
|
||||||
@@ -190,7 +190,7 @@ pub(crate) async fn init_kms_system(opt: &config::Opt) -> std::io::Result<()> {
|
|||||||
master_key: None,
|
master_key: None,
|
||||||
file_permissions: Some(0o600),
|
file_permissions: Some(0o600),
|
||||||
}),
|
}),
|
||||||
default_key_id: opt.kms_default_key_id.clone(),
|
default_key_id: config.kms_default_key_id.clone(),
|
||||||
timeout: std::time::Duration::from_secs(30),
|
timeout: std::time::Duration::from_secs(30),
|
||||||
retry_attempts: 3,
|
retry_attempts: 3,
|
||||||
enable_cache: true,
|
enable_cache: true,
|
||||||
@@ -198,11 +198,11 @@ pub(crate) async fn init_kms_system(opt: &config::Opt) -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"vault" => {
|
"vault" => {
|
||||||
let vault_address = opt
|
let vault_address = config
|
||||||
.kms_vault_address
|
.kms_vault_address
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| Error::other("Vault address is required for vault backend"))?;
|
.ok_or_else(|| Error::other("Vault address is required for vault backend"))?;
|
||||||
let vault_token = opt
|
let vault_token = config
|
||||||
.kms_vault_token
|
.kms_vault_token
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| Error::other("Vault token is required for vault backend"))?;
|
.ok_or_else(|| Error::other("Vault token is required for vault backend"))?;
|
||||||
@@ -220,14 +220,14 @@ pub(crate) async fn init_kms_system(opt: &config::Opt) -> std::io::Result<()> {
|
|||||||
key_path_prefix: "rustfs/kms/keys".to_string(),
|
key_path_prefix: "rustfs/kms/keys".to_string(),
|
||||||
tls: None,
|
tls: None,
|
||||||
})),
|
})),
|
||||||
default_key_id: opt.kms_default_key_id.clone(),
|
default_key_id: config.kms_default_key_id.clone(),
|
||||||
timeout: std::time::Duration::from_secs(30),
|
timeout: std::time::Duration::from_secs(30),
|
||||||
retry_attempts: 3,
|
retry_attempts: 3,
|
||||||
enable_cache: true,
|
enable_cache: true,
|
||||||
cache_config: rustfs_kms::config::CacheConfig::default(),
|
cache_config: rustfs_kms::config::CacheConfig::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return Err(Error::other(format!("Unsupported KMS backend: {}", opt.kms_backend))),
|
_ => return Err(Error::other(format!("Unsupported KMS backend: {}", config.kms_backend))),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Configure the KMS service
|
// Configure the KMS service
|
||||||
@@ -287,22 +287,22 @@ pub(crate) async fn init_kms_system(opt: &config::Opt) -> std::io::Result<()> {
|
|||||||
/// - Custom profile: Set via `--buffer-profile` or `RUSTFS_BUFFER_PROFILE` environment variable
|
/// - Custom profile: Set via `--buffer-profile` or `RUSTFS_BUFFER_PROFILE` environment variable
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `opt` - The application configuration options
|
/// * `config` - The application configuration options
|
||||||
pub(crate) fn init_buffer_profile_system(opt: &config::Opt) {
|
pub(crate) fn init_buffer_profile_system(config: &config::Config) {
|
||||||
use crate::config::workload_profiles::{
|
use crate::config::workload_profiles::{
|
||||||
RustFSBufferConfig, WorkloadProfile, init_global_buffer_config, set_buffer_profile_enabled,
|
RustFSBufferConfig, WorkloadProfile, init_global_buffer_config, set_buffer_profile_enabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
if opt.buffer_profile_disable {
|
if config.buffer_profile_disable {
|
||||||
// User explicitly disabled buffer profiling - use GeneralPurpose profile in disabled mode
|
// User explicitly disabled buffer profiling - use GeneralPurpose profile in disabled mode
|
||||||
info!("Buffer profiling disabled via --buffer-profile-disable, using GeneralPurpose profile");
|
info!("Buffer profiling disabled via --buffer-profile-disable, using GeneralPurpose profile");
|
||||||
set_buffer_profile_enabled(false);
|
set_buffer_profile_enabled(false);
|
||||||
} else {
|
} else {
|
||||||
// Enabled by default: use configured workload profile
|
// Enabled by default: use configured workload profile
|
||||||
info!("Buffer profiling enabled with profile: {}", opt.buffer_profile);
|
info!("Buffer profiling enabled with profile: {}", config.buffer_profile);
|
||||||
|
|
||||||
// Parse the workload profile from configuration string
|
// Parse the workload profile from configuration string
|
||||||
let profile = WorkloadProfile::from_name(&opt.buffer_profile);
|
let profile = WorkloadProfile::from_name(&config.buffer_profile);
|
||||||
|
|
||||||
// Log the selected profile for operational visibility
|
// Log the selected profile for operational visibility
|
||||||
info!("Active buffer profile: {:?}", profile);
|
info!("Active buffer profile: {:?}", profile);
|
||||||
|
|||||||
+22
-23
@@ -38,7 +38,6 @@ use crate::server::{
|
|||||||
SHUTDOWN_TIMEOUT, ServiceState, ServiceStateManager, ShutdownSignal, init_cert, init_event_notifier, shutdown_event_notifier,
|
SHUTDOWN_TIMEOUT, ServiceState, ServiceStateManager, ShutdownSignal, init_cert, init_event_notifier, shutdown_event_notifier,
|
||||||
start_audit_system, start_http_server, stop_audit_system, wait_for_shutdown,
|
start_audit_system, start_http_server, stop_audit_system, wait_for_shutdown,
|
||||||
};
|
};
|
||||||
use clap::Parser;
|
|
||||||
use license::init_license;
|
use license::init_license;
|
||||||
use rustfs_common::{GlobalReadiness, SystemStage, set_global_addr};
|
use rustfs_common::{GlobalReadiness, SystemStage, set_global_addr};
|
||||||
use rustfs_credentials::init_global_action_credentials;
|
use rustfs_credentials::init_global_action_credentials;
|
||||||
@@ -100,13 +99,13 @@ fn main() {
|
|||||||
}
|
}
|
||||||
async fn async_main() -> Result<()> {
|
async fn async_main() -> Result<()> {
|
||||||
// Parse the obtained parameters
|
// Parse the obtained parameters
|
||||||
let opt = config::Opt::parse();
|
let config = config::Config::parse()?;
|
||||||
|
|
||||||
// Initialize the configuration
|
// Initialize the configuration
|
||||||
init_license(opt.license.clone());
|
init_license(config.license.clone());
|
||||||
|
|
||||||
// Initialize Observability
|
// Initialize Observability
|
||||||
let guard = match init_obs(Some(opt.clone().obs_endpoint)).await {
|
let guard = match init_obs(Some(config.clone().obs_endpoint)).await {
|
||||||
Ok(g) => g,
|
Ok(g) => g,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failed to initialize observability: {e}");
|
println!("Failed to initialize observability: {e}");
|
||||||
@@ -135,7 +134,7 @@ async fn async_main() -> Result<()> {
|
|||||||
rustfs_trusted_proxies::init();
|
rustfs_trusted_proxies::init();
|
||||||
|
|
||||||
// Initialize TLS if a certificate path is provided
|
// Initialize TLS if a certificate path is provided
|
||||||
if let Some(tls_path) = &opt.tls_path {
|
if let Some(tls_path) = &config.tls_path {
|
||||||
match init_cert(tls_path).await {
|
match init_cert(tls_path).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!(target: "rustfs::main", "TLS initialized successfully with certs from {}", tls_path);
|
info!(target: "rustfs::main", "TLS initialized successfully with certs from {}", tls_path);
|
||||||
@@ -148,7 +147,7 @@ async fn async_main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run parameters
|
// Run parameters
|
||||||
match run(opt).await {
|
match run(config).await {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Server encountered an error and is shutting down: {}", e);
|
error!("Server encountered an error and is shutting down: {}", e);
|
||||||
@@ -157,17 +156,17 @@ async fn async_main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(opt))]
|
#[instrument(skip(config))]
|
||||||
async fn run(opt: config::Opt) -> Result<()> {
|
async fn run(config: config::Config) -> Result<()> {
|
||||||
debug!("opt: {:?}", &opt);
|
debug!("config: {:?}", &config);
|
||||||
// 1. Initialize global readiness tracker
|
// 1. Initialize global readiness tracker
|
||||||
let readiness = Arc::new(GlobalReadiness::new());
|
let readiness = Arc::new(GlobalReadiness::new());
|
||||||
|
|
||||||
if let Some(region) = &opt.region {
|
if let Some(region) = &config.region {
|
||||||
rustfs_ecstore::global::set_global_region(region.clone());
|
rustfs_ecstore::global::set_global_region(region.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let server_addr = parse_and_resolve_address(opt.address.as_str()).map_err(Error::other)?;
|
let server_addr = parse_and_resolve_address(config.address.as_str()).map_err(Error::other)?;
|
||||||
let server_port = server_addr.port();
|
let server_port = server_addr.port();
|
||||||
let server_address = server_addr.to_string();
|
let server_address = server_addr.to_string();
|
||||||
|
|
||||||
@@ -182,7 +181,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Set up AK and SK
|
// Set up AK and SK
|
||||||
match init_global_action_credentials(Some(opt.access_key.clone()), Some(opt.secret_key.clone())) {
|
match init_global_action_credentials(Some(config.access_key.clone()), Some(config.secret_key.clone())) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!(target: "rustfs::main::run", "Global action credentials initialized successfully.");
|
info!(target: "rustfs::main::run", "Global action credentials initialized successfully.");
|
||||||
}
|
}
|
||||||
@@ -195,10 +194,10 @@ async fn run(opt: config::Opt) -> Result<()> {
|
|||||||
|
|
||||||
set_global_rustfs_port(server_port);
|
set_global_rustfs_port(server_port);
|
||||||
|
|
||||||
set_global_addr(&opt.address).await;
|
set_global_addr(&config.address).await;
|
||||||
|
|
||||||
// For RPC
|
// For RPC
|
||||||
let (endpoint_pools, setup_type) = EndpointServerPools::from_volumes(server_address.clone().as_str(), opt.volumes.clone())
|
let (endpoint_pools, setup_type) = EndpointServerPools::from_volumes(server_address.clone().as_str(), config.volumes.clone())
|
||||||
.await
|
.await
|
||||||
.map_err(Error::other)?;
|
.map_err(Error::other)?;
|
||||||
|
|
||||||
@@ -248,16 +247,16 @@ async fn run(opt: config::Opt) -> Result<()> {
|
|||||||
state_manager.update(ServiceState::Starting);
|
state_manager.update(ServiceState::Starting);
|
||||||
|
|
||||||
let s3_shutdown_tx = {
|
let s3_shutdown_tx = {
|
||||||
let mut s3_opt = opt.clone();
|
let mut s3_config = config.clone();
|
||||||
s3_opt.console_enable = false;
|
s3_config.console_enable = false;
|
||||||
let s3_shutdown_tx = start_http_server(&s3_opt, state_manager.clone(), readiness.clone()).await?;
|
let s3_shutdown_tx = start_http_server(&s3_config, state_manager.clone(), readiness.clone()).await?;
|
||||||
Some(s3_shutdown_tx)
|
Some(s3_shutdown_tx)
|
||||||
};
|
};
|
||||||
|
|
||||||
let console_shutdown_tx = if opt.console_enable && !opt.console_address.is_empty() {
|
let console_shutdown_tx = if config.console_enable && !config.console_address.is_empty() {
|
||||||
let mut console_opt = opt.clone();
|
let mut console_config = config.clone();
|
||||||
console_opt.address = console_opt.console_address.clone();
|
console_config.address = console_config.console_address.clone();
|
||||||
let console_shutdown_tx = start_http_server(&console_opt, state_manager.clone(), readiness.clone()).await?;
|
let console_shutdown_tx = start_http_server(&console_config, state_manager.clone(), readiness.clone()).await?;
|
||||||
Some(console_shutdown_tx)
|
Some(console_shutdown_tx)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -290,7 +289,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
|||||||
// init replication_pool
|
// init replication_pool
|
||||||
init_background_replication(store.clone()).await;
|
init_background_replication(store.clone()).await;
|
||||||
// Initialize KMS system if enabled
|
// Initialize KMS system if enabled
|
||||||
init_kms_system(&opt).await?;
|
init_kms_system(&config).await?;
|
||||||
|
|
||||||
// Initialize FTP system if enabled
|
// Initialize FTP system if enabled
|
||||||
#[cfg(feature = "ftps")]
|
#[cfg(feature = "ftps")]
|
||||||
@@ -333,7 +332,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
|||||||
let ftps_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>> = None;
|
let ftps_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>> = None;
|
||||||
|
|
||||||
// Initialize buffer profiling system
|
// Initialize buffer profiling system
|
||||||
init_buffer_profile_system(&opt);
|
init_buffer_profile_system(&config);
|
||||||
|
|
||||||
// Initialize event notifier
|
// Initialize event notifier
|
||||||
init_event_notifier().await;
|
init_event_notifier().await;
|
||||||
|
|||||||
+13
-13
@@ -60,11 +60,11 @@ use tracing::{Span, debug, error, info, instrument, warn};
|
|||||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||||
|
|
||||||
pub async fn start_http_server(
|
pub async fn start_http_server(
|
||||||
opt: &config::Opt,
|
config: &config::Config,
|
||||||
worker_state_manager: ServiceStateManager,
|
worker_state_manager: ServiceStateManager,
|
||||||
readiness: Arc<GlobalReadiness>,
|
readiness: Arc<GlobalReadiness>,
|
||||||
) -> Result<tokio::sync::broadcast::Sender<()>> {
|
) -> Result<tokio::sync::broadcast::Sender<()>> {
|
||||||
let server_addr = parse_and_resolve_address(opt.address.as_str()).map_err(Error::other)?;
|
let server_addr = parse_and_resolve_address(config.address.as_str()).map_err(Error::other)?;
|
||||||
let server_port = server_addr.port();
|
let server_port = server_addr.port();
|
||||||
|
|
||||||
// The listening address and port are obtained from the parameters
|
// The listening address and port are obtained from the parameters
|
||||||
@@ -150,7 +150,7 @@ pub async fn start_http_server(
|
|||||||
TcpListener::from_std(socket.into())?
|
TcpListener::from_std(socket.into())?
|
||||||
};
|
};
|
||||||
|
|
||||||
let tls_acceptor = setup_tls_acceptor(opt.tls_path.as_deref().unwrap_or_default()).await?;
|
let tls_acceptor = setup_tls_acceptor(config.tls_path.as_deref().unwrap_or_default()).await?;
|
||||||
let tls_enabled = tls_acceptor.is_some();
|
let tls_enabled = tls_acceptor.is_some();
|
||||||
let protocol = if tls_enabled { "https" } else { "http" };
|
let protocol = if tls_enabled { "https" } else { "http" };
|
||||||
// Obtain the listener address
|
// Obtain the listener address
|
||||||
@@ -173,7 +173,7 @@ pub async fn start_http_server(
|
|||||||
let api_endpoints = format!("{protocol}://{local_ip_str}:{server_port}");
|
let api_endpoints = format!("{protocol}://{local_ip_str}:{server_port}");
|
||||||
let localhost_endpoint = format!("{protocol}://127.0.0.1:{server_port}");
|
let localhost_endpoint = format!("{protocol}://127.0.0.1:{server_port}");
|
||||||
let now_time = jiff::Zoned::now().strftime("%Y-%m-%d %H:%M:%S").to_string();
|
let now_time = jiff::Zoned::now().strftime("%Y-%m-%d %H:%M:%S").to_string();
|
||||||
if opt.console_enable {
|
if config.console_enable {
|
||||||
admin::console::init_console_cfg(local_ip, server_port);
|
admin::console::init_console_cfg(local_ip, server_port);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
@@ -193,8 +193,8 @@ pub async fn start_http_server(
|
|||||||
info!(target: "rustfs::main::startup","RustFS API: {api_endpoints} {localhost_endpoint}");
|
info!(target: "rustfs::main::startup","RustFS API: {api_endpoints} {localhost_endpoint}");
|
||||||
println!("RustFS Http API: {api_endpoints} {localhost_endpoint}");
|
println!("RustFS Http API: {api_endpoints} {localhost_endpoint}");
|
||||||
println!("RustFS Start Time: {now_time}");
|
println!("RustFS Start Time: {now_time}");
|
||||||
if rustfs_credentials::DEFAULT_ACCESS_KEY.eq(&opt.access_key)
|
if rustfs_credentials::DEFAULT_ACCESS_KEY.eq(&config.access_key)
|
||||||
&& rustfs_credentials::DEFAULT_SECRET_KEY.eq(&opt.secret_key)
|
&& rustfs_credentials::DEFAULT_SECRET_KEY.eq(&config.secret_key)
|
||||||
{
|
{
|
||||||
warn!(
|
warn!(
|
||||||
"Detected default credentials '{}:{}', we recommend that you change these values with 'RUSTFS_ACCESS_KEY' and 'RUSTFS_SECRET_KEY' environment variables",
|
"Detected default credentials '{}:{}', we recommend that you change these values with 'RUSTFS_ACCESS_KEY' and 'RUSTFS_SECRET_KEY' environment variables",
|
||||||
@@ -212,20 +212,20 @@ pub async fn start_http_server(
|
|||||||
let store = storage::ecfs::FS::new();
|
let store = storage::ecfs::FS::new();
|
||||||
let mut b = S3ServiceBuilder::new(store.clone());
|
let mut b = S3ServiceBuilder::new(store.clone());
|
||||||
|
|
||||||
let access_key = opt.access_key.clone();
|
let access_key = config.access_key.clone();
|
||||||
let secret_key = opt.secret_key.clone();
|
let secret_key = config.secret_key.clone();
|
||||||
|
|
||||||
b.set_auth(IAMAuth::new(access_key, secret_key));
|
b.set_auth(IAMAuth::new(access_key, secret_key));
|
||||||
b.set_access(store.clone());
|
b.set_access(store.clone());
|
||||||
b.set_route(admin::make_admin_route(opt.console_enable)?);
|
b.set_route(admin::make_admin_route(config.console_enable)?);
|
||||||
|
|
||||||
// Virtual-hosted-style requests are only set up for S3 API when server domains are configured and console is disabled
|
// Virtual-hosted-style requests are only set up for S3 API when server domains are configured and console is disabled
|
||||||
if !opt.server_domains.is_empty() && !opt.console_enable {
|
if !config.server_domains.is_empty() && !config.console_enable {
|
||||||
MultiDomain::new(&opt.server_domains).map_err(Error::other)?; // validate domains
|
MultiDomain::new(&config.server_domains).map_err(Error::other)?; // validate domains
|
||||||
|
|
||||||
// add the default port number to the given server domains
|
// add the default port number to the given server domains
|
||||||
let mut domain_sets = std::collections::HashSet::new();
|
let mut domain_sets = std::collections::HashSet::new();
|
||||||
for domain in &opt.server_domains {
|
for domain in &config.server_domains {
|
||||||
domain_sets.insert(domain.to_string());
|
domain_sets.insert(domain.to_string());
|
||||||
if let Some((host, _)) = domain.split_once(':') {
|
if let Some((host, _)) = domain.split_once(':') {
|
||||||
domain_sets.insert(format!("{host}:{server_port}"));
|
domain_sets.insert(format!("{host}:{server_port}"));
|
||||||
@@ -256,7 +256,7 @@ pub async fn start_http_server(
|
|||||||
debug!("HTTP response compression is disabled");
|
debug!("HTTP response compression is disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_console = opt.console_enable;
|
let is_console = config.console_enable;
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// Note: CORS layer is removed from global middleware stack
|
// Note: CORS layer is removed from global middleware stack
|
||||||
// - S3 API CORS is handled by bucket-level CORS configuration in apply_cors_headers()
|
// - S3 API CORS is handled by bucket-level CORS configuration in apply_cors_headers()
|
||||||
|
|||||||
Reference in New Issue
Block a user