From 25e5738568b2a021de3a79af3282b2b5feaee9e8 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Mon, 12 Feb 2024 10:42:17 +0100 Subject: [PATCH 1/2] [fix-secrets-695] take into account rpc secret from file for cli commands (fix #695) --- src/garage/main.rs | 23 +++++++++++++++-------- src/garage/secrets.rs | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/garage/main.rs b/src/garage/main.rs index 5c92dae4..1a6a6e32 100644 --- a/src/garage/main.rs +++ b/src/garage/main.rs @@ -174,7 +174,9 @@ async fn main() { } async fn cli_command(opt: Opt) -> Result<(), Error> { - let config = if opt.secrets.rpc_secret.is_none() || opt.rpc_host.is_none() { + let config = if (opt.secrets.rpc_secret.is_none() && opt.secrets.rpc_secret_file.is_none()) + || opt.rpc_host.is_none() + { Some(garage_util::config::read_config(opt.config_file.clone()) .err_context(format!("Unable to read configuration file {}. Configuration file is needed because -h or -s is not provided on the command line.", opt.config_file.to_string_lossy()))?) } else { @@ -182,14 +184,19 @@ async fn cli_command(opt: Opt) -> Result<(), Error> { }; // Find and parse network RPC secret - let net_key_hex_str = opt - .secrets - .rpc_secret - .as_ref() - .or_else(|| config.as_ref().and_then(|c| c.rpc_secret.as_ref())) - .ok_or("No RPC secret provided")?; + let mut rpc_secret = config.as_ref().and_then(|c| c.rpc_secret.clone()); + secrets::fill_secret( + &mut rpc_secret, + &config.as_ref().and_then(|c| c.rpc_secret_file.clone()), + &opt.secrets.rpc_secret, + &opt.secrets.rpc_secret_file, + "rpc_secret", + true, + )?; + + let net_key_hex_str = rpc_secret.ok_or("No RPC secret provided")?; let network_key = NetworkKey::from_slice( - &hex::decode(net_key_hex_str).err_context("Invalid RPC secret key (bad hex)")?[..], + &hex::decode(&net_key_hex_str).err_context("Invalid RPC secret key (bad hex)")?[..], ) .ok_or("Invalid RPC secret provided (wrong length)")?; diff --git a/src/garage/secrets.rs b/src/garage/secrets.rs index 8c89a262..a2c64cef 100644 --- a/src/garage/secrets.rs +++ b/src/garage/secrets.rs @@ -83,7 +83,7 @@ pub fn fill_secrets(mut config: Config, secrets: Secrets) -> Result, config_secret_file: &Option, cli_secret: &Option, From bf283c99240787c7ffeba8ff3222283ee9fc61aa Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Mon, 12 Feb 2024 11:35:57 +0100 Subject: [PATCH 2/2] [fix-secrets-695] config: replace String by PathBuf for *_file --- src/garage/secrets.rs | 20 +++++++++++--------- src/util/config.rs | 6 +++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/garage/secrets.rs b/src/garage/secrets.rs index a2c64cef..c3d704aa 100644 --- a/src/garage/secrets.rs +++ b/src/garage/secrets.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use structopt::StructOpt; use garage_util::config::Config; @@ -23,7 +25,7 @@ pub struct Secrets { /// RPC secret network key, used to replace rpc_secret in config.toml and rpc-secret /// when running the daemon or doing admin operations #[structopt(long = "rpc-secret-file", env = "GARAGE_RPC_SECRET_FILE")] - pub rpc_secret_file: Option, + pub rpc_secret_file: Option, /// Admin API authentication token, replaces admin.admin_token in config.toml when /// running the Garage daemon @@ -33,7 +35,7 @@ pub struct Secrets { /// Admin API authentication token file path, replaces admin.admin_token in config.toml /// and admin-token when running the Garage daemon #[structopt(long = "admin-token-file", env = "GARAGE_ADMIN_TOKEN_FILE")] - pub admin_token_file: Option, + pub admin_token_file: Option, /// Metrics API authentication token, replaces admin.metrics_token in config.toml when /// running the Garage daemon @@ -43,7 +45,7 @@ pub struct Secrets { /// Metrics API authentication token file path, replaces admin.metrics_token in config.toml /// and metrics-token when running the Garage daemon #[structopt(long = "metrics-token-file", env = "GARAGE_METRICS_TOKEN_FILE")] - pub metrics_token_file: Option, + pub metrics_token_file: Option, } /// Single function to fill all secrets in the Config struct from their correct source (value @@ -85,9 +87,9 @@ pub fn fill_secrets(mut config: Config, secrets: Secrets) -> Result, - config_secret_file: &Option, + config_secret_file: &Option, cli_secret: &Option, - cli_secret_file: &Option, + cli_secret_file: &Option, name: &'static str, allow_world_readable: bool, ) -> Result<(), Error> { @@ -117,14 +119,14 @@ pub(crate) fn fill_secret( Ok(()) } -fn read_secret_file(file_path: &String, allow_world_readable: bool) -> Result { +fn read_secret_file(file_path: &PathBuf, allow_world_readable: bool) -> Result { if !allow_world_readable { #[cfg(unix)] { use std::os::unix::fs::MetadataExt; let metadata = std::fs::metadata(file_path)?; if metadata.mode() & 0o077 != 0 { - return Err(format!("File {} is world-readable! (mode: 0{:o}, expected 0600)\nRefusing to start until this is fixed, or environment variable GARAGE_ALLOW_WORLD_READABLE_SECRETS is set to true.", file_path, metadata.mode()).into()); + return Err(format!("File {} is world-readable! (mode: 0{:o}, expected 0600)\nRefusing to start until this is fixed, or environment variable GARAGE_ALLOW_WORLD_READABLE_SECRETS is set to true.", file_path.display(), metadata.mode()).into()); } } } @@ -260,7 +262,7 @@ mod tests { let config = fill_secrets( config, Secrets { - rpc_secret_file: Some(path_secret2.display().to_string()), + rpc_secret_file: Some(path_secret2.clone()), ..Default::default() }, )?; @@ -271,7 +273,7 @@ mod tests { config, Secrets { rpc_secret: Some("baz".into()), - rpc_secret_file: Some(path_secret2.display().to_string()), + rpc_secret_file: Some(path_secret2.clone()), ..Default::default() } ) diff --git a/src/util/config.rs b/src/util/config.rs index 65c0b5c0..a9a72110 100644 --- a/src/util/config.rs +++ b/src/util/config.rs @@ -52,7 +52,7 @@ pub struct Config { /// RPC secret key: 32 bytes hex encoded pub rpc_secret: Option, /// Optional file where RPC secret key is read from - pub rpc_secret_file: Option, + pub rpc_secret_file: Option, /// Address to bind for RPC pub rpc_bind_addr: SocketAddr, /// Public IP address of this node @@ -166,12 +166,12 @@ pub struct AdminConfig { /// Bearer token to use to scrape metrics pub metrics_token: Option, /// File to read metrics token from - pub metrics_token_file: Option, + pub metrics_token_file: Option, /// Bearer token to use to access Admin API endpoints pub admin_token: Option, /// File to read admin token from - pub admin_token_file: Option, + pub admin_token_file: Option, /// OTLP server to where to export traces pub trace_sink: Option,