From 21d6eb268af0ccb89aefc480f6efb4d780f8788c Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 20 Oct 2024 12:02:21 +0300 Subject: [PATCH] config from args + more args --- src/main.rs | 139 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 41 deletions(-) diff --git a/src/main.rs b/src/main.rs index 31b17d8..90281d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,26 @@ struct Args { /// files encoding #[arg(short = 'c', long)] encoding: Option, + + /// keys subdir + #[arg(long, default_value = "keys")] + keys_dir: String, + + /// config subdir + #[arg(long, default_value = "config")] + config_dir: String, + + /// valid days + #[arg(long, default_value = "30650")] + days: u32, + + /// openssl binary + #[arg(long, default_value = "openssl")] + openssl: String, + + /// template file + #[arg(long, default_value = "template.ovpn")] + template_file: String, } struct VarsFile { @@ -43,7 +63,7 @@ struct VarsFile { encoding: String, } -struct Config { +struct AppConfig { encoding: String, req_days: u32, keys_subdir: String, @@ -53,9 +73,13 @@ struct Config { openssl_cnf_env: String, ca_filename: String, default_email_domain: String, + openssl: String, + base_directory: String, + email: String, + name: String, } -impl Default for Config { +impl Default for AppConfig { fn default() -> Self { Self { encoding: "cp866".into(), @@ -67,6 +91,51 @@ impl Default for Config { openssl_cnf_env: "KEY_CONFIG".into(), ca_filename: "ca.crt".into(), default_email_domain: "example.com".into(), + openssl: "openssl".into(), + base_directory: ".".into(), + email: "name@example.com".into(), + name: "user".into(), + } + } +} + +impl From<&Args> for AppConfig { + fn from(args: &Args) -> Self { + let defaults = Self::default(); + + let base_directory = args + .directory + .as_ref() + .unwrap_or(&defaults.base_directory) + .clone(); + let email = args.email.clone().unwrap_or(format!( + "{}@{}", + &args.name, + defaults.default_email_domain.clone() + )); + let encoding = if let Some(enc) = args.encoding.clone() { + enc.to_string() + } else { + defaults.encoding.clone() + }; + let name = args.name.clone(); + let openssl = args.openssl.clone(); + let template_file = args.template_file.clone(); + let req_days = args.days; + let keys_subdir = args.keys_dir.clone(); + let config_subdir = args.config_dir.clone(); + + Self { + base_directory, + email, + encoding, + name, + openssl, + template_file, + req_days, + keys_subdir, + config_subdir, + ..defaults } } } @@ -168,6 +237,14 @@ impl VarsFile { } } + async fn from_config(config: &AppConfig) -> Result { + Self::from_dir( + PathBuf::from(&config.base_directory), + config.encoding.clone(), + ) + .await + } + async fn parse(&mut self) -> Result<()> { let mut result = BTreeMap::new(); let lines = read_file_by_lines(&self.filepath, &self.encoding).await?; @@ -222,26 +299,22 @@ struct Certs { config_file: PathBuf, template_file: PathBuf, openssl_cnf: PathBuf, + openssl: String, vars: BTreeMap, } impl Certs { - fn new( - name: String, - email: String, - dir: PathBuf, - vars: BTreeMap, - cfg: &Config, - ) -> Self { - let base_dir = dir; + fn new(cfg: &AppConfig, vars: BTreeMap) -> Self { + let base_dir = PathBuf::from(&cfg.base_directory); let keys_dir = base_dir.clone().join(cfg.keys_subdir.clone()); let config_dir = base_dir.clone().join(cfg.config_subdir.clone()); let mut vars = vars; + let name = cfg.name.clone(); vars.insert("KEY_CN".into(), name.clone()); vars.insert("KEY_NAME".into(), name.clone()); - vars.insert("KEY_EMAIL".into(), email); + vars.insert("KEY_EMAIL".into(), cfg.email.clone()); Self { base_dir: base_dir.clone(), @@ -257,6 +330,7 @@ impl Certs { std::env::var(cfg.openssl_cnf_env.clone()) .unwrap_or(cfg.openssl_default_cnf.clone()), ), + openssl: cfg.openssl.clone(), vars, } } @@ -289,17 +363,17 @@ impl Certs { )); } - let status = Command::new("openssl") - .args(&[ + let status = Command::new(&self.openssl) + .args([ "req", "-nodes", "-new", "-keyout", - &self.key_file.to_str().unwrap(), + self.key_file.to_str().unwrap(), "-out", - &self.req_file.to_str().unwrap(), + self.req_file.to_str().unwrap(), "-config", - &self.openssl_cnf.to_str().unwrap(), + self.openssl_cnf.to_str().unwrap(), "-batch", ]) .current_dir(&self.base_dir) @@ -325,17 +399,17 @@ impl Certs { )); } - let status = Command::new("openssl") - .args(&[ + let status = Command::new(&self.openssl) + .args([ "ca", "-days", format!("{}", self.req_days).as_str(), "-out", - &self.cert_file.to_str().unwrap(), + self.cert_file.to_str().unwrap(), "-in", - &self.req_file.to_str().unwrap(), + self.req_file.to_str().unwrap(), "-config", - &self.openssl_cnf.to_str().unwrap(), + self.openssl_cnf.to_str().unwrap(), "-batch", ]) .current_dir(&self.base_dir) @@ -389,31 +463,14 @@ impl Certs { #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { let args = Args::parse(); - let default_directory = ".".to_string(); - let directory = args.directory.as_ref().unwrap_or(&default_directory); - let mut config = Config::default(); - let email = args.email.clone().unwrap_or(format!( - "{}@{}", - &args.name, - config.default_email_domain.clone() - )); - if let Some(encoding) = args.encoding.clone() { - config.encoding = encoding.to_string(); - } - - let mut vars = VarsFile::from_dir(PathBuf::from(directory), config.encoding.clone()).await?; + let config = AppConfig::from(&args); + let mut vars = VarsFile::from_config(&config).await?; vars.parse().await?; println!("found vars: {}", vars.filepath.to_str().expect("fff")); println!("loaded: {:#?}", &vars.vars); - let certs = Certs::new( - args.name, - email, - directory.into(), - vars.vars.unwrap(), - &config, - ); + let certs = Certs::new(&config, vars.vars.unwrap()); let created = certs.build_client_config().await?; let result_file = certs.config_file.to_str().unwrap();