refactor: unify credential env constants and deploy env usage (#2821)

Co-authored-by: Henry Guo <marshawcoco@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: loverustfs <hello@rustfs.com>
Co-authored-by: 安正超 <anzhengchao@gmail.com>
This commit is contained in:
houseme
2026-05-06 12:30:29 +08:00
committed by GitHub
parent 090d60e00a
commit 3dd0692917
11 changed files with 153 additions and 57 deletions
+55 -11
View File
@@ -20,27 +20,59 @@
use super::Opt;
use crate::apply_external_env_compat;
use rustfs_config::{
DEFAULT_CONSOLE_ADDRESS, DEFAULT_CONSOLE_ENABLE, ENV_RUSTFS_ROOT_PASSWORD, ENV_RUSTFS_ROOT_USER, RUSTFS_REGION,
DEFAULT_CONSOLE_ADDRESS, DEFAULT_CONSOLE_ENABLE, ENV_RUSTFS_ACCESS_KEY, ENV_RUSTFS_SECRET_KEY, RUSTFS_REGION,
};
use rustfs_credentials::{DEFAULT_ACCESS_KEY, DEFAULT_SECRET_KEY, Masked};
use std::collections::HashSet;
use std::sync::{Mutex, OnceLock};
pub(crate) const LEGACY_ENV_RUSTFS_ROOT_USER: &str = "RUSTFS_ROOT_USER";
pub(crate) const LEGACY_ENV_RUSTFS_ROOT_PASSWORD: &str = "RUSTFS_ROOT_PASSWORD";
static LEGACY_CREDENTIAL_WARNED_KEYS: OnceLock<Mutex<HashSet<String>>> = OnceLock::new();
fn warn_legacy_credential_env_once(legacy_key: &str, canonical_key: &str) {
let warned = LEGACY_CREDENTIAL_WARNED_KEYS.get_or_init(|| Mutex::new(HashSet::new()));
let mut warned = match warned.lock() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(),
};
if warned.insert(legacy_key.to_string()) {
tracing::warn!(
"Environment variable {} is deprecated and will be removed at GA; use {} instead",
legacy_key,
canonical_key
);
}
}
/// Helper function to resolve credentials from multiple sources with precedence:
/// 1. Inline value (if provided)
/// 2. File value (if provided, read the content of the file)
/// 3. Environment variable (if set)
/// 4. Default value (if none of the above are provided)
/// 3. Canonical environment variable (if set)
/// 4. Legacy environment aliases (if set)
/// 5. Default value (if none of the above are provided)
pub(crate) fn resolve_credential<T: AsRef<std::path::Path>>(
inline_value: Option<String>,
file_value: Option<T>,
env_key: &str,
legacy_env_keys: &[&str],
default_value: &str,
) -> std::io::Result<String> {
let value = inline_value
.map(Ok)
.or_else(|| file_value.map(std::fs::read_to_string))
.or_else(|| rustfs_utils::get_env_opt_str(env_key).map(Ok))
.transpose()?
.unwrap_or_else(|| default_value.to_string());
let value = if let Some(value) = inline_value {
value
} else if let Some(path) = file_value {
std::fs::read_to_string(path)?
} else if let Some(value) = rustfs_utils::get_env_opt_str(env_key) {
value
} else if let Some((legacy_key, value)) = legacy_env_keys
.iter()
.find_map(|legacy_key| rustfs_utils::get_env_opt_str(legacy_key).map(|value| (*legacy_key, value)))
{
warn_legacy_credential_env_once(legacy_key, env_key);
value
} else {
default_value.to_string()
};
Ok(value.trim().to_string())
}
@@ -169,8 +201,20 @@ impl Config {
buffer_profile,
} = opt;
let access_key = resolve_credential(access_key, access_key_file.as_ref(), ENV_RUSTFS_ROOT_USER, DEFAULT_ACCESS_KEY)?;
let secret_key = resolve_credential(secret_key, secret_key_file.as_ref(), ENV_RUSTFS_ROOT_PASSWORD, DEFAULT_SECRET_KEY)?;
let access_key = resolve_credential(
access_key,
access_key_file.as_ref(),
ENV_RUSTFS_ACCESS_KEY,
&[LEGACY_ENV_RUSTFS_ROOT_USER],
DEFAULT_ACCESS_KEY,
)?;
let secret_key = resolve_credential(
secret_key,
secret_key_file.as_ref(),
ENV_RUSTFS_SECRET_KEY,
&[LEGACY_ENV_RUSTFS_ROOT_PASSWORD],
DEFAULT_SECRET_KEY,
)?;
// Region is optional, but if not set, we should default to "us-east-1" for signing compatibility with AWS S3 clients
let region = region.or_else(|| Some(RUSTFS_REGION.to_string()));
+18 -1
View File
@@ -174,7 +174,24 @@ mod tests {
#[test]
#[serial]
fn test_root_envs_are_used_for_bootstrap_credentials() {
fn test_access_key_envs_are_used_for_bootstrap_credentials() {
temp_env::with_vars(
[
("RUSTFS_VOLUMES", Some("/compat/vol1")),
("RUSTFS_ACCESS_KEY", Some("canonical-access")),
("RUSTFS_SECRET_KEY", Some("canonical-secret")),
],
|| {
let config = Config::from_opt(Opt::parse_from(["rustfs"])).expect("config should parse");
assert_eq!(config.access_key, "canonical-access");
assert_eq!(config.secret_key, "canonical-secret");
},
);
}
#[test]
#[serial]
fn test_root_envs_fallback_for_bootstrap_credentials() {
temp_env::with_vars(
[
("RUSTFS_VOLUMES", Some("/compat/vol1")),
+4 -3
View File
@@ -18,12 +18,12 @@
//! that can be accessed globally without needing the full Config struct.
use super::Config;
use crate::config::config_struct::resolve_credential;
use crate::config::config_struct::{LEGACY_ENV_RUSTFS_ROOT_USER, resolve_credential};
use rustfs_config::{
DEFAULT_ADDRESS, DEFAULT_BUFFER_PROFILE, DEFAULT_CONSOLE_ADDRESS, DEFAULT_CONSOLE_ENABLE, DEFAULT_KMS_BACKEND,
DEFAULT_KMS_ENABLE, DEFAULT_OBS_ENDPOINT, ENV_RUSTFS_ACCESS_KEY, ENV_RUSTFS_ACCESS_KEY_FILE, ENV_RUSTFS_ADDRESS,
ENV_RUSTFS_BUFFER_PROFILE, ENV_RUSTFS_CONSOLE_ADDRESS, ENV_RUSTFS_CONSOLE_ENABLE, ENV_RUSTFS_KMS_BACKEND,
ENV_RUSTFS_KMS_ENABLE, ENV_RUSTFS_OBS_ENDPOINT, ENV_RUSTFS_REGION, ENV_RUSTFS_ROOT_USER, ENV_RUSTFS_TLS_PATH, RUSTFS_REGION,
ENV_RUSTFS_KMS_ENABLE, ENV_RUSTFS_OBS_ENDPOINT, ENV_RUSTFS_REGION, ENV_RUSTFS_TLS_PATH, RUSTFS_REGION,
};
use rustfs_credentials::DEFAULT_ACCESS_KEY;
use rustfs_utils::{get_env_bool, get_env_opt_str, get_env_str};
@@ -83,7 +83,8 @@ impl ConfigSnapshot {
let access_key = resolve_credential(
get_env_opt_str(ENV_RUSTFS_ACCESS_KEY),
get_env_opt_str(ENV_RUSTFS_ACCESS_KEY_FILE),
ENV_RUSTFS_ROOT_USER,
ENV_RUSTFS_ACCESS_KEY,
&[LEGACY_ENV_RUSTFS_ROOT_USER],
DEFAULT_ACCESS_KEY,
)
.unwrap_or_else(|_| DEFAULT_ACCESS_KEY.to_string());