use serde::{Deserialize, Serialize}; use rust_util::util_file; use rust_util::XResult; use std::fs; use std::fs::File; use std::io::Read; use acme_lib::DirectoryUrl; const CERT_NAME: &str = "cert.pem"; const KEY_NAME: &str = "key.pem"; #[derive(Debug, Clone, Copy)] pub enum AcmeAlgo { Ec256, Ec384, Rsa(u32), } impl Default for AcmeAlgo { fn default() -> Self { Self::Ec384 } } impl AcmeAlgo { pub fn parse_or_default(s: &str) -> AcmeAlgo { Self::parse(s).unwrap_or_else(|_| Default::default()) } pub fn parse(s: &str) -> XResult { match s { "ec256" => Ok(AcmeAlgo::Ec256), "ec384" => Ok(AcmeAlgo::Ec384), "rsa2048" => Ok(AcmeAlgo::Rsa(2048)), "rsa3072" => Ok(AcmeAlgo::Rsa(3072)), "rsa4096" => Ok(AcmeAlgo::Rsa(4096)), _ => simple_error!("Unknown algo: {}", s), } } } #[derive(Debug, Clone, Copy)] pub enum AcmeMode { Prod, Test, } impl Default for AcmeMode { fn default() -> Self { Self::Prod } } impl AcmeMode { pub fn parse_or_default(s: &str) -> AcmeMode { Self::parse(s).unwrap_or_else(|_| Default::default()) } pub fn parse(s: &str) -> XResult { match s { "prod" => Ok(AcmeMode::Prod), "test" => Ok(AcmeMode::Test), _ => simple_error!("Unknown mode: {}", s), } } pub fn directory_url(&self) -> DirectoryUrl { match self { AcmeMode::Prod => DirectoryUrl::LetsEncrypt, AcmeMode::Test => DirectoryUrl::LetsEncryptStaging, } } } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AcmeConfig { pub email: String, pub dir: String, pub auth_timeout: Option, pub csr_timeout: Option, pub concurrent: Option, // ? } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CertConfigItem { pub path: String, pub algo: Option, pub dns_names: Option>, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CertConfig { pub cert_items: Vec, } impl AcmeConfig { pub fn get_auth_timeout(&self) -> u64 { self.auth_timeout.unwrap_or(5_000) } pub fn get_csr_timeout(&self) -> u64 { self.csr_timeout.unwrap_or(5_000) } pub fn get_concurrent(&self) -> u32 { self.concurrent.unwrap_or(0) } } impl CertConfigItem { pub fn fill_dns_names(&mut self) -> XResult<()> { // TODO Ok(()) } } pub fn load_acme_config(file: Option<&str>, load_default: bool) -> XResult { if let Some(file) = file { let s = opt_result!(util_file::read_file_content(file), "Read file: {}, failed: {}", file); return Ok(opt_result!(deser_hjson::from_str(&s), "Parse acme config file: {}, failed: {}", file)); } if load_default { let default_config = util_file::read_config(None, &[ "~/acme_config.json".to_string(), "/etc/acme_config.json".to_string(), ]); if let Some(default_config) = default_config { let s = opt_result!(fs::read_to_string(default_config.clone()), "Read file: {:?}, failed: {}", default_config); return Ok(opt_result!(deser_hjson::from_str(&s), "Parse acme config file: {:?}, failed: {}", default_config)); } } simple_error!("Acme config file not found!") }