From 117a19f9856a87cf19485856c1e066daaf38ad82 Mon Sep 17 00:00:00 2001 From: Rodolphe Breard Date: Tue, 25 Jun 2019 16:02:33 +0200 Subject: [PATCH] Create account key pair at startup If several certificates uses the same account and this account doesn't exists yet, they will both try to create it, resulting in a race condition. This commit solves the problem by creating the account key pair at startup. Account creation on the endpoint is not subject to a race condition since the request does not differ from the one used to retrieve the account id. Fix #3 --- acmed/src/acme_proto.rs | 2 +- acmed/src/acme_proto/account.rs | 29 ++++++++++++++++++----------- acmed/src/main_event_loop.rs | 2 ++ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/acmed/src/acme_proto.rs b/acmed/src/acme_proto.rs index 4494733..6e98341 100644 --- a/acmed/src/acme_proto.rs +++ b/acmed/src/acme_proto.rs @@ -10,7 +10,7 @@ use acme_common::error::Error; use serde_json::json; use std::fmt; -mod account; +pub mod account; mod certificate; mod http; pub mod structs; diff --git a/acmed/src/acme_proto/account.rs b/acmed/src/acme_proto/account.rs index 04a9213..4068264 100644 --- a/acmed/src/acme_proto/account.rs +++ b/acmed/src/acme_proto/account.rs @@ -22,17 +22,7 @@ impl AccountManager { root_certs: &[String], ) -> Result<(Self, String), Error> { // TODO: store the key id (account url) - let key_pair = if storage::account_files_exists(cert) { - // TODO: check if the keys are suitable for the specified signature algorithm - // and, if not, initiate a key rollover. - storage::get_account_keypair(cert)? - } else { - // TODO: allow to change the signature algo - let sign_alg = SignatureAlgorithm::from_str(crate::DEFAULT_JWS_SIGN_ALGO)?; - let key_pair = sign_alg.gen_key_pair()?; - storage::set_account_keypair(cert, &key_pair)?; - key_pair - }; + let key_pair = storage::get_account_keypair(cert)?; let account = Account::new(cert); let account = serde_json::to_string(&account)?; let data_builder = @@ -53,3 +43,20 @@ impl AccountManager { Ok((ac, nonce)) } } + +pub fn init_account(cert: &Certificate) -> Result<(), Error> { + if !storage::account_files_exists(cert) { + // TODO: allow to change the signature algo + let sign_alg = SignatureAlgorithm::from_str(crate::DEFAULT_JWS_SIGN_ALGO)?; + let key_pair = sign_alg.gen_key_pair()?; + storage::set_account_keypair(cert, &key_pair)?; + let msg = format!("Account {} created.", &cert.account.name); + cert.info(&msg) + } else { + // TODO: check if the keys are suitable for the specified signature algorithm + // and, if not, initiate a key rollover. + let msg = format!("Account {} already exists.", &cert.account.name); + cert.debug(&msg) + } + Ok(()) +} diff --git a/acmed/src/main_event_loop.rs b/acmed/src/main_event_loop.rs index 2b948e1..db90fab 100644 --- a/acmed/src/main_event_loop.rs +++ b/acmed/src/main_event_loop.rs @@ -1,3 +1,4 @@ +use crate::acme_proto::account::init_account; use crate::acme_proto::request_certificate; use crate::certificate::Certificate; use crate::config; @@ -67,6 +68,7 @@ impl MainEventLoop { env: crt.env.to_owned(), id: i + 1, }; + init_account(&cert)?; certs.push(cert); }