From 456c0a70c551b529aed0844d2ce3c19208814ea6 Mon Sep 17 00:00:00 2001 From: dvdsk Date: Sat, 3 Jun 2023 01:10:06 +0200 Subject: [PATCH 1/4] move path resolution before renewal --- Cargo.lock | 25 +++- main/Cargo.toml | 1 + main/src/cert/format.rs | 3 - main/src/cert/io.rs | 61 +--------- main/src/cert/load.rs | 86 ++------------ main/src/cert/store.rs | 93 +++------------ main/src/config.rs | 105 ++++++++++++---- main/src/config/args.rs | 19 ++- main/src/config/paths.rs | 217 ++++++++++++++++++++++++++++++++++ main/src/main.rs | 2 +- main/tests/behaviour.rs | 14 +-- main/tests/diagnostics.rs | 8 +- main/tests/format.rs | 4 +- main/tests/shared/gen_cert.rs | 1 + main/tests/shared/mod.rs | 4 +- 15 files changed, 381 insertions(+), 262 deletions(-) create mode 100644 main/src/config/paths.rs diff --git a/Cargo.lock b/Cargo.lock index 690f292..cc1e9f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1438,7 +1438,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "renewc" -version = "0.2.4" +version = "0.2.5" dependencies = [ "async-trait", "axum", @@ -1463,6 +1463,7 @@ dependencies = [ "rand", "rcgen", "shared_memory", + "strum", "tempfile", "time", "tokio", @@ -1792,6 +1793,28 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + [[package]] name = "syn" version = "1.0.109" diff --git a/main/Cargo.toml b/main/Cargo.toml index e7c23fd..10e2f95 100644 --- a/main/Cargo.toml +++ b/main/Cargo.toml @@ -43,6 +43,7 @@ yasna = "0.5" async-trait = "0.1" data-encoding = "2.4" pem = "2" +strum = { version = "0.24.1", features = ["derive"] } [dev-dependencies] libc = "0.2" diff --git a/main/src/cert/format.rs b/main/src/cert/format.rs index 61d953e..a787809 100644 --- a/main/src/cert/format.rs +++ b/main/src/cert/format.rs @@ -120,7 +120,4 @@ mod tests { let pem: Pem = der.to_pem(Label::Certificate); assert_eq!(pem.into_bytes(), ROOT_CA); } - - #[test] - fn parse_chain() {} } diff --git a/main/src/cert/io.rs b/main/src/cert/io.rs index e0dfa17..94337ac 100644 --- a/main/src/cert/io.rs +++ b/main/src/cert/io.rs @@ -1,30 +1,9 @@ use std::fs; use std::io::ErrorKind; -use std::path::{Path, PathBuf}; +use std::path::Path; use color_eyre::eyre::{self, Context}; use color_eyre::Help; -use tracing::instrument; - -#[instrument(level = "debug", ret)] -pub(crate) fn derive_path(cert_path: &Path, name: &str, ty: &str, extension: &str) -> PathBuf { - let mut path = dir(cert_path); - path.set_file_name(format!("{name}_{ty}")); - path.set_extension(extension); - path -} - -pub(super) fn dir(cert_path: &Path) -> PathBuf { - let dir = if cert_path.is_file() { - cert_path - .parent() - .expect("is never none if parent was a file") - } else { - cert_path - }; - - dir.to_path_buf() -} pub(super) fn read_any_file(path: &Path) -> eyre::Result>> { match fs::read(path) { @@ -39,41 +18,3 @@ pub(super) fn read_any_file(path: &Path) -> eyre::Result>> { Ok(bytes) => Ok(Some(bytes)), } } - -pub(super) fn name(domains: &[impl AsRef]) -> eyre::Result { - let shortest = domains - .iter() - .map(AsRef::as_ref) - .min_by_key(|d| d.len()) - .unwrap(); - let last_dot = shortest - .rfind('.') - .ok_or_else(|| eyre::eyre!("shortest domain has no top level domain [org/net/com etc]"))?; - let (name, _extension) = shortest.split_at(last_dot); - if let Some(last_dot) = name.rfind('.') { - let (_subdomains, name) = name.split_at(last_dot + 1); - Ok(name.to_string()) - } else { - Ok(name.to_string()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn extract_name() { - let domains = [ - "example.org", - "subdomain.example.org", - "subsubdomain.subdomain.example.org", - "another.example.org", - "even_more.example.org", - "a.nm.org", - "subdomain.nm.org", - ]; - - assert_eq!(name(&domains).unwrap(), "nm"); - } -} diff --git a/main/src/cert/load.rs b/main/src/cert/load.rs index df82d3d..e75eda2 100644 --- a/main/src/cert/load.rs +++ b/main/src/cert/load.rs @@ -1,6 +1,6 @@ use std::io::ErrorKind; -use crate::config::{Output, OutputConfig}; +use crate::config::{Encoding, OutputConfig}; use crate::Config; use color_eyre::eyre::{self, Context}; use color_eyre::Help; @@ -9,38 +9,7 @@ use tracing::instrument; use super::format::{Der, Label, PemItem}; use super::{MaybeSigned, Signed}; -use super::io::{derive_path, name, read_any_file}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Encoding { - PEM, - DER, - #[cfg(feature = "derchain")] - PKCS12, -} - -impl Encoding { - pub(crate) fn extension(self) -> &'static str { - match self { - Encoding::PEM => "pem", - Encoding::DER => "der", - #[cfg(feature = "derchain")] - Encoding::PKCS12 => "pkcs12", - } - } -} - -impl From<&Output> for Encoding { - fn from(output: &Output) -> Self { - match output { - Output::Pem - | Output::PemSeperateKey - | Output::PemSeperateChain - | Output::PemAllSeperate => Encoding::PEM, - Output::Der => Encoding::DER, - } - } -} +use super::io::read_any_file; // TODO: remove Option, report errors upstream as warnings <03-05-23, dvdsk> #[instrument(level = "debug", skip(config), ret)] @@ -75,27 +44,17 @@ pub fn from_disk(config: &Config) -> eyre::Result>> #[instrument(level = "debug", skip(config), err)] fn load_seperate_chain(config: &Config) -> eyre::Result> { let OutputConfig { - output, - certificate_path, - chain_path, - .. + output, chain_path, .. } = &config.output_config; - let encoding = Encoding::from(output); - let path = match chain_path { - None => derive_path( - certificate_path, - &name(&config.domains)?, - "chain", - encoding.extension(), - ), - Some(path) => path.clone(), - }; + let encoding = Encoding::from(output); match encoding { Encoding::DER => { let mut chain = Vec::new(); for i in 0.. { - let path = path.with_file_name(format!("{i}_chain.der")); + let path = chain_path + .as_path() + .with_file_name(format!("{i}_chain.der")); let bytes = match std::fs::read(&path) { Ok(bytes) => bytes, Err(e) if e.kind() == ErrorKind::NotFound => break, @@ -110,7 +69,7 @@ fn load_seperate_chain(config: &Config) -> eyre::Result> { } Encoding::PEM => { - let Some(bytes) = read_any_file(&path)? else { + let Some(bytes) = read_any_file(chain_path.as_path())? else { return Ok(Vec::new()); }; P::chain_from_pem(bytes) @@ -122,23 +81,12 @@ fn load_seperate_chain(config: &Config) -> eyre::Result> { fn load_seperate_private_key(config: &Config) -> eyre::Result> { let OutputConfig { output, - certificate_path, key_path, .. } = &config.output_config; let encoding = Encoding::from(output); - let path = match key_path { - None => derive_path( - certificate_path, - &name(&config.domains)?, - "key", - encoding.extension(), - ), - Some(path) => path.clone(), - }; - - let Some(bytes) = read_any_file(&path)? else { + let Some(bytes) = read_any_file(&key_path.as_path())? else { return Ok(None); }; @@ -152,25 +100,15 @@ fn load_seperate_private_key(config: &Config) -> eyre::Result