Browse Source

feat: support WEED_ environment variable overrides for security config

Match Go's Viper convention: prefix with WEED_, uppercase, replace dots
with underscores. Environment variables take precedence over values in
security.toml, and work even without a config file.

Supported variables:
  WEED_JWT_SIGNING_KEY, WEED_JWT_SIGNING_EXPIRES_AFTER_SECONDS,
  WEED_JWT_SIGNING_READ_KEY, WEED_JWT_SIGNING_READ_EXPIRES_AFTER_SECONDS,
  WEED_HTTPS_VOLUME_CERT, WEED_HTTPS_VOLUME_KEY, WEED_HTTPS_VOLUME_CA,
  WEED_GRPC_VOLUME_CERT, WEED_GRPC_VOLUME_KEY, WEED_GRPC_VOLUME_CA,
  WEED_GUARD_WHITE_LIST, WEED_ACCESS_UI
rust-volume-server
Chris Lu 2 days ago
parent
commit
4e79a3502f
  1. 103
      seaweed-volume/src/config.rs

103
seaweed-volume/src/config.rs

@ -809,11 +809,17 @@ pub struct SecurityConfig {
/// ```
pub fn parse_security_config(path: &str) -> SecurityConfig {
if path.is_empty() {
return SecurityConfig::default();
let mut cfg = SecurityConfig::default();
apply_env_overrides(&mut cfg);
return cfg;
}
let content = match std::fs::read_to_string(path) {
Ok(c) => c,
Err(_) => return SecurityConfig::default(),
Err(_) => {
let mut cfg = SecurityConfig::default();
apply_env_overrides(&mut cfg);
return cfg;
}
};
let mut cfg = SecurityConfig::default();
@ -912,9 +918,59 @@ pub fn parse_security_config(path: &str) -> SecurityConfig {
}
}
// Override with WEED_ environment variables (matches Go's Viper convention:
// prefix WEED_, uppercase, replace . with _).
// e.g. WEED_JWT_SIGNING_KEY overrides [jwt.signing] key
apply_env_overrides(&mut cfg);
cfg
}
/// Apply WEED_ environment variable overrides to a SecurityConfig.
/// Matches Go's Viper convention: WEED_ prefix, uppercase, dots replaced with underscores.
fn apply_env_overrides(cfg: &mut SecurityConfig) {
if let Ok(v) = std::env::var("WEED_JWT_SIGNING_KEY") {
cfg.jwt_signing_key = v.into_bytes();
}
if let Ok(v) = std::env::var("WEED_JWT_SIGNING_EXPIRES_AFTER_SECONDS") {
cfg.jwt_signing_expires = v.parse().unwrap_or(cfg.jwt_signing_expires);
}
if let Ok(v) = std::env::var("WEED_JWT_SIGNING_READ_KEY") {
cfg.jwt_read_signing_key = v.into_bytes();
}
if let Ok(v) = std::env::var("WEED_JWT_SIGNING_READ_EXPIRES_AFTER_SECONDS") {
cfg.jwt_read_signing_expires = v.parse().unwrap_or(cfg.jwt_read_signing_expires);
}
if let Ok(v) = std::env::var("WEED_HTTPS_VOLUME_CERT") {
cfg.https_cert_file = v;
}
if let Ok(v) = std::env::var("WEED_HTTPS_VOLUME_KEY") {
cfg.https_key_file = v;
}
if let Ok(v) = std::env::var("WEED_HTTPS_VOLUME_CA") {
cfg.https_ca_file = v;
}
if let Ok(v) = std::env::var("WEED_GRPC_VOLUME_CERT") {
cfg.grpc_cert_file = v;
}
if let Ok(v) = std::env::var("WEED_GRPC_VOLUME_KEY") {
cfg.grpc_key_file = v;
}
if let Ok(v) = std::env::var("WEED_GRPC_VOLUME_CA") {
cfg.grpc_ca_file = v;
}
if let Ok(v) = std::env::var("WEED_GUARD_WHITE_LIST") {
cfg.guard_white_list = v
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
}
if let Ok(v) = std::env::var("WEED_ACCESS_UI") {
cfg.access_ui = v == "true" || v == "1";
}
}
/// Detect the host's IP address.
/// Mirrors Go's `util.DetectedHostAddress()`.
fn detect_host_address() -> String {
@ -1160,4 +1216,47 @@ ui = true
""
);
}
#[test]
fn test_env_override_jwt_signing_key() {
// Set env, parse empty config, verify env wins
std::env::set_var("WEED_JWT_SIGNING_KEY", "env-secret");
let cfg = parse_security_config("");
assert_eq!(cfg.jwt_signing_key, b"env-secret");
std::env::remove_var("WEED_JWT_SIGNING_KEY");
}
#[test]
fn test_env_override_takes_precedence_over_file() {
let tmp = tempfile::NamedTempFile::new().unwrap();
std::fs::write(
tmp.path(),
r#"
[jwt.signing]
key = "file-secret"
"#,
)
.unwrap();
std::env::set_var("WEED_JWT_SIGNING_KEY", "env-secret");
let cfg = parse_security_config(tmp.path().to_str().unwrap());
assert_eq!(cfg.jwt_signing_key, b"env-secret");
std::env::remove_var("WEED_JWT_SIGNING_KEY");
}
#[test]
fn test_env_override_guard_white_list() {
std::env::set_var("WEED_GUARD_WHITE_LIST", "10.0.0.0/8, 192.168.1.0/24");
let cfg = parse_security_config("");
assert_eq!(cfg.guard_white_list, vec!["10.0.0.0/8", "192.168.1.0/24"]);
std::env::remove_var("WEED_GUARD_WHITE_LIST");
}
#[test]
fn test_env_override_access_ui() {
std::env::set_var("WEED_ACCESS_UI", "true");
let cfg = parse_security_config("");
assert!(cfg.access_ui);
std::env::remove_var("WEED_ACCESS_UI");
}
}
Loading…
Cancel
Save