From a0d8944682e77ad61f70c3985c30d3ecfaac1b39 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Thu, 25 Apr 2019 23:23:59 +0200 Subject: [PATCH] Move common items to a dedicated lib In a near future, ACMEd will be composed of several binaries which will use some common functions and structures. --- acme_common/Cargo.toml | 25 +++++ acme_common/src/error.rs | 87 ++++++++++++++++ acmed/src/keygen.rs => acme_common/src/gen.rs | 0 acme_common/src/lib.rs | 6 ++ acmed/Cargo.toml | 2 +- acmed/src/acme_proto.rs | 6 +- acmed/src/acme_proto/account.rs | 2 +- acmed/src/acme_proto/certificate.rs | 15 +-- acmed/src/acme_proto/http.rs | 4 +- acmed/src/acme_proto/jws.rs | 10 +- acmed/src/acme_proto/jws/algorithms.rs | 7 +- acmed/src/acme_proto/structs.rs | 2 + acmed/src/acme_proto/structs/account.rs | 2 +- acmed/src/acme_proto/structs/authorization.rs | 4 +- acmed/src/acme_proto/structs/directory.rs | 2 +- acmed/src/{ => acme_proto/structs}/error.rs | 99 ++----------------- acmed/src/acme_proto/structs/order.rs | 2 +- acmed/src/certificate.rs | 2 +- acmed/src/config.rs | 2 +- acmed/src/hooks.rs | 2 +- acmed/src/logs.rs | 2 +- acmed/src/main.rs | 2 - acmed/src/main_event_loop.rs | 2 +- acmed/src/storage.rs | 4 +- 24 files changed, 160 insertions(+), 131 deletions(-) create mode 100644 acme_common/Cargo.toml create mode 100644 acme_common/src/error.rs rename acmed/src/keygen.rs => acme_common/src/gen.rs (100%) create mode 100644 acme_common/src/lib.rs rename acmed/src/{ => acme_proto/structs}/error.rs (78%) diff --git a/acme_common/Cargo.toml b/acme_common/Cargo.toml new file mode 100644 index 0000000..586a504 --- /dev/null +++ b/acme_common/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "acme_common" +version = "0.1.0" +authors = ["Rodolphe Breard "] +edition = "2018" +repository = "https://github.com/breard-r/libreauth" +readme = "../README.md" +license = "MIT OR Apache-2.0" +include = ["src/**/*", "Cargo.toml", "Licence_*.txt"] + +[lib] +name = "acme_common" + +[dependencies] +base64 = "0.10" +handlebars = "2.0.0-beta.1" +http_req = "0.4" +openssl = "0.10" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +syslog = "4.0" +toml = "0.5" + +[target.'cfg(unix)'.dependencies] +nix = "0.13" diff --git a/acme_common/src/error.rs b/acme_common/src/error.rs new file mode 100644 index 0000000..3d8c355 --- /dev/null +++ b/acme_common/src/error.rs @@ -0,0 +1,87 @@ +use std::fmt; + +#[derive(Debug)] +pub struct Error { + pub message: String, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.message) + } +} + +impl From<&str> for Error { + fn from(error: &str) -> Self { + Error { + message: error.to_string(), + } + } +} + +impl From for Error { + fn from(error: String) -> Self { + error.as_str().into() + } +} + +impl From<&String> for Error { + fn from(error: &String) -> Self { + error.as_str().into() + } +} + +impl From for Error { + fn from(error: std::io::Error) -> Self { + format!("IO error: {}", error).into() + } +} + +impl From for Error { + fn from(error: std::string::FromUtf8Error) -> Self { + format!("UTF-8 error: {}", error).into() + } +} + +impl From for Error { + fn from(error: syslog::Error) -> Self { + format!("syslog error: {}", error).into() + } +} + +impl From for Error { + fn from(error: toml::de::Error) -> Self { + format!("IO error: {}", error).into() + } +} + +impl From for Error { + fn from(error: serde_json::error::Error) -> Self { + format!("IO error: {}", error).into() + } +} + +impl From for Error { + fn from(error: handlebars::TemplateRenderError) -> Self { + format!("Template error: {}", error).into() + } +} + +impl From for Error { + fn from(error: openssl::error::ErrorStack) -> Self { + format!("{}", error).into() + } +} + +impl From for Error { + fn from(error: http_req::error::Error) -> Self { + format!("HTTP error: {}", error).into() + } +} + +#[cfg(unix)] +impl From for Error { + fn from(error: nix::Error) -> Self { + format!("{}", error).into() + } +} diff --git a/acmed/src/keygen.rs b/acme_common/src/gen.rs similarity index 100% rename from acmed/src/keygen.rs rename to acme_common/src/gen.rs diff --git a/acme_common/src/lib.rs b/acme_common/src/lib.rs new file mode 100644 index 0000000..cb5e209 --- /dev/null +++ b/acme_common/src/lib.rs @@ -0,0 +1,6 @@ +pub mod error; +pub mod gen; + +pub fn b64_encode>(input: &T) -> String { + base64::encode_config(input, base64::URL_SAFE_NO_PAD) +} diff --git a/acmed/Cargo.toml b/acmed/Cargo.toml index 0080c92..691981a 100644 --- a/acmed/Cargo.toml +++ b/acmed/Cargo.toml @@ -12,7 +12,7 @@ include = ["src/**/*", "Cargo.toml", "LICENSE-*.txt"] build = "build.rs" [dependencies] -base64 = "0.10" +acme_common = { path = "../acme_common" } clap = "2.32" daemonize = "0.4" env_logger = "0.6" diff --git a/acmed/src/acme_proto.rs b/acmed/src/acme_proto.rs index 4f3cf95..3b1648d 100644 --- a/acmed/src/acme_proto.rs +++ b/acmed/src/acme_proto.rs @@ -4,8 +4,8 @@ use crate::acme_proto::structs::{ Authorization, AuthorizationStatus, NewOrder, Order, OrderStatus, }; use crate::certificate::Certificate; -use crate::error::Error; use crate::storage; +use acme_common::error::Error; use log::info; use std::fmt; @@ -156,7 +156,3 @@ pub fn request_certificate(cert: &Certificate) -> Result<(), Error> { info!("Certificate renewed for {}", cert.domains.join(", ")); Ok(()) } - -pub fn b64_encode>(input: &T) -> String { - base64::encode_config(input, base64::URL_SAFE_NO_PAD) -} diff --git a/acmed/src/acme_proto/account.rs b/acmed/src/acme_proto/account.rs index 1799268..3011f74 100644 --- a/acmed/src/acme_proto/account.rs +++ b/acmed/src/acme_proto/account.rs @@ -3,8 +3,8 @@ use crate::acme_proto::jws::algorithms::SignatureAlgorithm; use crate::acme_proto::jws::encode_jwk; use crate::acme_proto::structs::{Account, AccountResponse, Directory}; use crate::certificate::Certificate; -use crate::error::Error; use crate::storage; +use acme_common::error::Error; use openssl::pkey::{PKey, Private, Public}; use std::str::FromStr; diff --git a/acmed/src/acme_proto/certificate.rs b/acmed/src/acme_proto/certificate.rs index 226d181..4a84d78 100644 --- a/acmed/src/acme_proto/certificate.rs +++ b/acmed/src/acme_proto/certificate.rs @@ -1,6 +1,7 @@ use crate::certificate::{Algorithm, Certificate}; -use crate::error::Error; -use crate::{keygen, storage}; +use crate::storage; +use acme_common::error::Error; +use acme_common::{b64_encode, gen}; use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private, Public}; use openssl::stack::Stack; @@ -10,10 +11,10 @@ use serde_json::json; fn gen_key_pair(cert: &Certificate) -> Result<(PKey, PKey), Error> { let (priv_key, pub_key) = match cert.algo { - Algorithm::Rsa2048 => keygen::rsa2048(), - Algorithm::Rsa4096 => keygen::rsa4096(), - Algorithm::EcdsaP256 => keygen::p256(), - Algorithm::EcdsaP384 => keygen::p384(), + Algorithm::Rsa2048 => gen::rsa2048(), + Algorithm::Rsa4096 => gen::rsa4096(), + Algorithm::EcdsaP256 => gen::p256(), + Algorithm::EcdsaP384 => gen::p384(), }?; storage::set_priv_key(cert, &priv_key)?; Ok((priv_key, pub_key)) @@ -52,7 +53,7 @@ pub fn generate_csr( builder.sign(priv_key, MessageDigest::sha256())?; let csr = builder.build(); let csr = csr.to_der()?; - let csr = super::b64_encode(&csr); + let csr = b64_encode(&csr); let csr = json!({ "csr": csr }); Ok(csr.to_string()) } diff --git a/acmed/src/acme_proto/http.rs b/acmed/src/acme_proto/http.rs index 6ccc889..d0ca4de 100644 --- a/acmed/src/acme_proto/http.rs +++ b/acmed/src/acme_proto/http.rs @@ -1,5 +1,5 @@ -use crate::acme_proto::structs::Directory; -use crate::error::{AcmeError, Error, HttpApiError}; +use crate::acme_proto::structs::{AcmeError, Directory, HttpApiError}; +use acme_common::error::Error; use http_req::request::{Method, Request}; use http_req::response::Response; use http_req::uri::Uri; diff --git a/acmed/src/acme_proto/jws.rs b/acmed/src/acme_proto/jws.rs index d907eb6..70805b2 100644 --- a/acmed/src/acme_proto/jws.rs +++ b/acmed/src/acme_proto/jws.rs @@ -1,6 +1,6 @@ -use crate::acme_proto::b64_encode; use crate::acme_proto::jws::algorithms::{EdDsaVariant, SignatureAlgorithm}; -use crate::error::Error; +use acme_common::b64_encode; +use acme_common::error::Error; use openssl::ecdsa::EcdsaSig; use openssl::pkey::{PKey, Private}; use openssl::sha::sha256; @@ -113,7 +113,7 @@ mod tests { #[test] fn test_default_jwk() { - let (priv_key, _) = crate::keygen::p256().unwrap(); + let (priv_key, _) = acme_common::gen::p256().unwrap(); let payload = "Dummy payload 1"; let payload_b64 = "RHVtbXkgcGF5bG9hZCAx"; let s = encode_jwk(&priv_key, payload.as_bytes(), "", ""); @@ -127,7 +127,7 @@ mod tests { #[test] fn test_default_nopad_jwk() { - let (priv_key, _) = crate::keygen::p256().unwrap(); + let (priv_key, _) = acme_common::gen::p256().unwrap(); let payload = "Dummy payload"; let payload_b64 = "RHVtbXkgcGF5bG9hZA"; let payload_b64_pad = "RHVtbXkgcGF5bG9hZA=="; @@ -143,7 +143,7 @@ mod tests { #[test] fn test_default_kid() { - let (priv_key, _) = crate::keygen::p256().unwrap(); + let (priv_key, _) = acme_common::gen::p256().unwrap(); let payload = "Dummy payload 1"; let payload_b64 = "RHVtbXkgcGF5bG9hZCAx"; let key_id = "0x2a"; diff --git a/acmed/src/acme_proto/jws/algorithms.rs b/acmed/src/acme_proto/jws/algorithms.rs index 6c84784..48d4a73 100644 --- a/acmed/src/acme_proto/jws/algorithms.rs +++ b/acmed/src/acme_proto/jws/algorithms.rs @@ -1,7 +1,6 @@ use super::jwk::{EdDsaEd25519Jwk, Es256Jwk, Jwk}; -use crate::acme_proto::b64_encode; -use crate::error::Error; -use crate::keygen; +use acme_common::error::Error; +use acme_common::{b64_encode, gen}; use openssl::bn::{BigNum, BigNumContext}; use openssl::ec::EcGroup; use openssl::nid::Nid; @@ -117,7 +116,7 @@ impl SignatureAlgorithm { pub fn gen_key_pair(&self) -> Result<(PKey, PKey), Error> { match self { - SignatureAlgorithm::Es256 => keygen::p256(), + SignatureAlgorithm::Es256 => gen::p256(), SignatureAlgorithm::EdDsa(EdDsaVariant::Ed25519) => Err("Not implemented".into()), } } diff --git a/acmed/src/acme_proto/structs.rs b/acmed/src/acme_proto/structs.rs index df2488d..425c850 100644 --- a/acmed/src/acme_proto/structs.rs +++ b/acmed/src/acme_proto/structs.rs @@ -15,10 +15,12 @@ macro_rules! deserialize_from_str { mod account; mod authorization; mod directory; +mod error; mod order; pub use account::{Account, AccountDeactivation, AccountResponse, AccountUpdate}; pub use authorization::{Authorization, AuthorizationStatus, Challenge}; pub use deserialize_from_str; pub use directory::Directory; +pub use error::{AcmeError, HttpApiError}; pub use order::{Identifier, IdentifierType, NewOrder, Order, OrderStatus}; diff --git a/acmed/src/acme_proto/structs/account.rs b/acmed/src/acme_proto/structs/account.rs index cc14f29..841e7a9 100644 --- a/acmed/src/acme_proto/structs/account.rs +++ b/acmed/src/acme_proto/structs/account.rs @@ -1,5 +1,5 @@ use crate::certificate::Certificate; -use crate::error::Error; +use acme_common::error::Error; use serde::{Deserialize, Serialize}; use std::str::FromStr; diff --git a/acmed/src/acme_proto/structs/authorization.rs b/acmed/src/acme_proto/structs/authorization.rs index 94de436..cc6173b 100644 --- a/acmed/src/acme_proto/structs/authorization.rs +++ b/acmed/src/acme_proto/structs/authorization.rs @@ -1,7 +1,7 @@ -use crate::acme_proto::b64_encode; use crate::acme_proto::jws::algorithms::SignatureAlgorithm; use crate::acme_proto::structs::Identifier; -use crate::error::Error; +use acme_common::b64_encode; +use acme_common::error::Error; use openssl::pkey::{PKey, Private}; use openssl::sha::sha256; use serde::Deserialize; diff --git a/acmed/src/acme_proto/structs/directory.rs b/acmed/src/acme_proto/structs/directory.rs index 6751f07..6634249 100644 --- a/acmed/src/acme_proto/structs/directory.rs +++ b/acmed/src/acme_proto/structs/directory.rs @@ -1,4 +1,4 @@ -use crate::error::Error; +use acme_common::error::Error; use serde::Deserialize; use std::str::FromStr; diff --git a/acmed/src/error.rs b/acmed/src/acme_proto/structs/error.rs similarity index 78% rename from acmed/src/error.rs rename to acmed/src/acme_proto/structs/error.rs index 91fe5e1..fafd24c 100644 --- a/acmed/src/error.rs +++ b/acmed/src/acme_proto/structs/error.rs @@ -1,99 +1,8 @@ +use acme_common::error::Error; use serde::Deserialize; use std::fmt; use std::str::FromStr; -#[derive(Debug)] -pub struct Error { - pub message: String, -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.message) - } -} - -impl From<&str> for Error { - fn from(error: &str) -> Self { - Error { - message: error.to_string(), - } - } -} - -impl From for Error { - fn from(error: String) -> Self { - error.as_str().into() - } -} - -impl From<&String> for Error { - fn from(error: &String) -> Self { - error.as_str().into() - } -} - -impl From for Error { - fn from(error: AcmeError) -> Self { - error.to_string().into() - } -} - -impl From for Error { - fn from(error: std::io::Error) -> Self { - format!("IO error: {}", error).into() - } -} - -impl From for Error { - fn from(error: std::string::FromUtf8Error) -> Self { - format!("UTF-8 error: {}", error).into() - } -} - -impl From for Error { - fn from(error: syslog::Error) -> Self { - format!("syslog error: {}", error).into() - } -} - -impl From for Error { - fn from(error: toml::de::Error) -> Self { - format!("IO error: {}", error).into() - } -} - -impl From for Error { - fn from(error: serde_json::error::Error) -> Self { - format!("IO error: {}", error).into() - } -} - -impl From for Error { - fn from(error: handlebars::TemplateRenderError) -> Self { - format!("Template error: {}", error).into() - } -} - -impl From for Error { - fn from(error: openssl::error::ErrorStack) -> Self { - format!("{}", error).into() - } -} - -impl From for Error { - fn from(error: http_req::error::Error) -> Self { - format!("HTTP error: {}", error).into() - } -} - -#[cfg(unix)] -impl From for Error { - fn from(error: nix::Error) -> Self { - format!("{}", error).into() - } -} - #[derive(PartialEq)] pub enum AcmeError { AccountDoesNotExist, @@ -208,6 +117,12 @@ impl From for AcmeError { } } +impl From for Error { + fn from(error: AcmeError) -> Self { + error.to_string().into() + } +} + #[derive(Deserialize)] pub struct HttpApiError { #[serde(rename = "type")] diff --git a/acmed/src/acme_proto/structs/order.rs b/acmed/src/acme_proto/structs/order.rs index ee7c3a9..50ef7ec 100644 --- a/acmed/src/acme_proto/structs/order.rs +++ b/acmed/src/acme_proto/structs/order.rs @@ -1,4 +1,4 @@ -use crate::error::Error; +use acme_common::error::Error; use serde::{Deserialize, Serialize}; use std::fmt; use std::str::FromStr; diff --git a/acmed/src/certificate.rs b/acmed/src/certificate.rs index 055d0d6..19a013f 100644 --- a/acmed/src/certificate.rs +++ b/acmed/src/certificate.rs @@ -1,8 +1,8 @@ use crate::acme_proto::Challenge; use crate::config::Account; -use crate::error::Error; use crate::hooks::{self, ChallengeHookData, Hook, PostOperationHookData}; use crate::storage::{certificate_files_exists, get_certificate}; +use acme_common::error::Error; use log::debug; use std::fmt; use time::{strptime, Duration}; diff --git a/acmed/src/config.rs b/acmed/src/config.rs index d28b6f4..c6e9d22 100644 --- a/acmed/src/config.rs +++ b/acmed/src/config.rs @@ -1,7 +1,7 @@ use crate::acme_proto::Challenge; use crate::certificate::Algorithm; -use crate::error::Error; use crate::hooks; +use acme_common::error::Error; use log::info; use serde::Deserialize; use std::fs::{self, File}; diff --git a/acmed/src/hooks.rs b/acmed/src/hooks.rs index 6fac147..120f0d2 100644 --- a/acmed/src/hooks.rs +++ b/acmed/src/hooks.rs @@ -1,4 +1,4 @@ -use crate::error::Error; +use acme_common::error::Error; use handlebars::Handlebars; use log::debug; use serde::Serialize; diff --git a/acmed/src/logs.rs b/acmed/src/logs.rs index ef7210f..1f07dc3 100644 --- a/acmed/src/logs.rs +++ b/acmed/src/logs.rs @@ -1,4 +1,4 @@ -use crate::error::Error; +use acme_common::error::Error; use env_logger::Builder; use log::LevelFilter; use syslog::Facility; diff --git a/acmed/src/main.rs b/acmed/src/main.rs index 11af373..c271311 100644 --- a/acmed/src/main.rs +++ b/acmed/src/main.rs @@ -6,9 +6,7 @@ use log::{error, LevelFilter}; mod acme_proto; mod certificate; mod config; -mod error; mod hooks; -mod keygen; mod logs; mod main_event_loop; mod storage; diff --git a/acmed/src/main_event_loop.rs b/acmed/src/main_event_loop.rs index 7ddd01a..2cad4ff 100644 --- a/acmed/src/main_event_loop.rs +++ b/acmed/src/main_event_loop.rs @@ -1,7 +1,7 @@ use crate::acme_proto::request_certificate; use crate::certificate::Certificate; use crate::config; -use crate::error::Error; +use acme_common::error::Error; use log::{debug, warn}; use std::thread; use std::time::Duration; diff --git a/acmed/src/storage.rs b/acmed/src/storage.rs index 20fea3f..a4dc170 100644 --- a/acmed/src/storage.rs +++ b/acmed/src/storage.rs @@ -1,7 +1,7 @@ -use crate::acme_proto::b64_encode; use crate::certificate::Certificate; -use crate::error::Error; use crate::hooks::{self, FileStorageHookData}; +use acme_common::b64_encode; +use acme_common::error::Error; use log::trace; use openssl::pkey::{PKey, Private, Public}; use openssl::x509::X509;