From e66b5a5254d5cc123dd2beb14d277eceefcf179b Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Wed, 24 Apr 2019 10:54:46 +0200 Subject: [PATCH] Use account objects instead of an email field Defining an account solely by an email address is not the best strategy since the ACME protocol does not require it and also allows for more contacts information. Although this commit does not change the "one email" policy, it sets the bases so it could evolve in the future. --- CHANGELOG.md | 4 ++++ acmed/src/acme_proto/account.rs | 2 +- acmed/src/acme_proto/structs/account.rs | 5 +++-- acmed/src/certificate.rs | 7 ++++--- acmed/src/config.rs | 18 +++++++++++++++++- acmed/src/main_event_loop.rs | 2 +- acmed/src/storage.rs | 4 ++-- 7 files changed, 32 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f5ffba..98e8ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- An account object has been added in the configuration. + ### Changed +- In the configuration, the `email` certificate field has been replaced by the `account` field which matches an account object. - The `token` challenge hook variable has been renamed `file_name`. - The logs has been purged from many useless debug and trace entries. diff --git a/acmed/src/acme_proto/account.rs b/acmed/src/acme_proto/account.rs index c097ba7..5860172 100644 --- a/acmed/src/acme_proto/account.rs +++ b/acmed/src/acme_proto/account.rs @@ -37,7 +37,7 @@ impl AccountManager { storage::set_account_pub_key(cert, &pub_key)?; (priv_key, pub_key) }; - let account = Account::new(&[cert.email.to_owned()]); + let account = Account::new(&cert.account); let account = serde_json::to_string(&account)?; let data = encode_jwk(&priv_key, account.as_bytes(), &directory.new_account, nonce)?; let (acc_rep, account_url, nonce) = diff --git a/acmed/src/acme_proto/structs/account.rs b/acmed/src/acme_proto/structs/account.rs index 264a3c4..222507d 100644 --- a/acmed/src/acme_proto/structs/account.rs +++ b/acmed/src/acme_proto/structs/account.rs @@ -1,3 +1,4 @@ +use crate::config; use crate::error::Error; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -11,9 +12,9 @@ pub struct Account { } impl Account { - pub fn new(contact: &[String]) -> Self { + pub fn new(cnf_account: &config::Account) -> Self { Account { - contact: contact.iter().map(|v| format!("mailto:{}", v)).collect(), + contact: vec![format!("mailto:{}", cnf_account.email)], terms_of_service_agreed: true, only_return_existing: false, } diff --git a/acmed/src/certificate.rs b/acmed/src/certificate.rs index b134103..d17b9fa 100644 --- a/acmed/src/certificate.rs +++ b/acmed/src/certificate.rs @@ -1,4 +1,5 @@ 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}; @@ -40,10 +41,10 @@ impl fmt::Display for Algorithm { #[derive(Debug)] pub struct Certificate { + pub account: Account, pub domains: Vec, pub algo: Algorithm, pub kp_reuse: bool, - pub email: String, pub remote_url: String, pub challenge: Challenge, pub challenge_hooks: Vec, @@ -83,14 +84,14 @@ impl fmt::Display for Certificate { "Certificate information: Domains: {domains} Algorithm: {algo} -Contact: {email} +Account: {account} Private key reuse: {kp_reuse} Challenge: {challenge} Challenge hooks: {challenge_hooks} Post operation hooks: {post_operation_hooks}", domains = self.domains.join(", "), algo = self.algo, - email = self.email, + account = self.account.name, kp_reuse = self.kp_reuse, challenge = self.challenge, challenge_hooks = challenge_hooks, diff --git a/acmed/src/config.rs b/acmed/src/config.rs index 778cc08..a42c73c 100644 --- a/acmed/src/config.rs +++ b/acmed/src/config.rs @@ -14,6 +14,7 @@ pub struct Config { pub endpoint: Vec, pub hook: Vec, pub group: Vec, + pub account: Vec, pub certificate: Vec, } @@ -139,9 +140,15 @@ pub struct Group { pub hooks: Vec, } +#[derive(Clone, Debug, Deserialize)] +pub struct Account { + pub name: String, + pub email: String, +} + #[derive(Deserialize)] pub struct Certificate { - pub email: String, + pub account: String, pub endpoint: String, pub domains: Vec, pub challenge: String, @@ -160,6 +167,15 @@ pub struct Certificate { } impl Certificate { + pub fn get_account(&self, cnf: &Config) -> Result { + for account in cnf.account.iter() { + if account.name == self.account { + return Ok(account.clone()); + } + } + Err(format!("{}: account not found", self.account).into()) + } + pub fn get_algorithm(&self) -> Result { let algo = match &self.algorithm { Some(a) => &a, diff --git a/acmed/src/main_event_loop.rs b/acmed/src/main_event_loop.rs index f1c8989..3bdee55 100644 --- a/acmed/src/main_event_loop.rs +++ b/acmed/src/main_event_loop.rs @@ -17,10 +17,10 @@ impl MainEventLoop { let mut certs = Vec::new(); for crt in cnf.certificate.iter() { let cert = Certificate { + account: crt.get_account(&cnf)?, domains: crt.domains.to_owned(), algo: crt.get_algorithm()?, kp_reuse: crt.get_kp_reuse(), - email: crt.email.to_owned(), remote_url: crt.get_remote_url(&cnf)?, challenge: crt.get_challenge()?, challenge_hooks: crt.get_challenge_hooks(&cnf)?, diff --git a/acmed/src/storage.rs b/acmed/src/storage.rs index 970e91b..8b2cb59 100644 --- a/acmed/src/storage.rs +++ b/acmed/src/storage.rs @@ -43,8 +43,8 @@ fn get_file_full_path( }; let file_name = match file_type { FileType::AccountPrivateKey | FileType::AccountPublicKey => format!( - "{email}.{file_type}.{ext}", - email = cert.email, + "{account}.{file_type}.{ext}", + account = cert.account.name, file_type = file_type.to_string(), ext = "pem" ),