Browse Source

Move the account key type and signing algorithm

Those options are tied with the account and should therefore be defined
in the associated section, not in the endpoint section.
pull/39/head
Rodolphe Breard 4 years ago
parent
commit
a0f4928a73
  1. 35
      acmed/src/account.rs
  2. 26
      acmed/src/acme_proto/account.rs
  3. 2
      acmed/src/certificate.rs
  4. 29
      acmed/src/config.rs
  5. 20
      acmed/src/endpoint.rs
  6. 1
      acmed/src/main.rs
  7. 2
      acmed/src/main_event_loop.rs
  8. 50
      man/en/acmed.toml.5

35
acmed/src/account.rs

@ -0,0 +1,35 @@
use acme_common::crypto::{JwsSignatureAlgorithm, KeyType};
use acme_common::error::Error;
use std::str::FromStr;
#[derive(Clone, Debug)]
pub struct Account {
pub name: String,
pub email: String,
pub key_type: KeyType,
pub signature_algorithm: JwsSignatureAlgorithm,
}
impl Account {
pub fn new(
name: &str,
email: &str,
key_type: &Option<String>,
signature_algorithm: &Option<String>,
) -> Result<Self, Error> {
let key_type = match key_type {
Some(kt) => KeyType::from_str(&kt)?,
None => crate::DEFAULT_ACCOUNT_KEY_TYPE,
};
let signature_algorithm = match signature_algorithm {
Some(sa) => JwsSignatureAlgorithm::from_str(&sa)?,
None => key_type.get_default_signature_alg(),
};
Ok(crate::account::Account {
name: name.to_string(),
email: email.to_string(),
key_type,
signature_algorithm,
})
}
}

26
acmed/src/acme_proto/account.rs

@ -22,7 +22,7 @@ impl AccountManager {
) -> Result<Self, Error> {
// TODO: store the key id (account url)
let key_pair = storage::get_account_keypair(cert)?;
let signature_algorithm = endpoint.signature_algorithm;
let signature_algorithm = cert.account.signature_algorithm;
let kp_ref = &key_pair;
let account = Account::new(cert, endpoint);
let account = serde_json::to_string(&account)?;
@ -42,20 +42,28 @@ impl AccountManager {
}
}
pub fn init_account(cert: &Certificate, endpoint: &Endpoint) -> Result<(), Error> {
pub fn init_account(cert: &Certificate) -> Result<(), Error> {
if !storage::account_files_exists(cert) {
let key_pair = gen_keypair(endpoint.key_type)?;
cert.info(&format!(
"Account {} does not exists. Creating it.",
&cert.account.name
));
let key_pair = gen_keypair(cert.account.key_type)?;
storage::set_account_keypair(cert, &key_pair)?;
cert.info(&format!("Account {} created", &cert.account.name));
cert.debug(&format!("Account {} created.", &cert.account.name));
} else {
let key_pair = storage::get_account_keypair(cert)?;
if key_pair.key_type != endpoint.key_type {
cert.debug(&format!("Account {} has a key pair of type {} while {} was expected. Creating a new {} key pair.", &cert.account.name, key_pair.key_type, endpoint.key_type, endpoint.key_type));
// TODO: Do a propper key rollover?
let key_pair = gen_keypair(endpoint.key_type)?;
if key_pair.key_type != cert.account.key_type {
cert.info(&format!("Account {name} has a key pair of type {kt_has} while {kt_want} was expected. Creating a new {kt_want} key pair.", name=&cert.account.name, kt_has=key_pair.key_type, kt_want=cert.account.key_type));
// TODO: Do a propper key rollover
let key_pair = gen_keypair(cert.account.key_type)?;
storage::set_account_keypair(cert, &key_pair)?;
cert.debug(&format!(
"Account {} updated with a new {} key pair.",
&cert.account.name, cert.account.key_type
));
} else {
cert.debug(&format!("Account {} already exists", &cert.account.name));
cert.debug(&format!("Account {} already exists.", &cert.account.name));
}
}
Ok(())

2
acmed/src/certificate.rs

@ -1,5 +1,5 @@
use crate::account::Account;
use crate::acme_proto::Challenge;
use crate::config::Account;
use crate::hooks::{self, ChallengeHookData, Hook, HookEnvData, HookType, PostOperationHookData};
use crate::identifier::{Identifier, IdentifierType};
use crate::storage::{certificate_files_exists, get_certificate};

29
acmed/src/config.rs

@ -195,8 +195,6 @@ pub struct Endpoint {
pub tos_agreed: bool,
#[serde(default)]
pub rate_limits: Vec<String>,
pub key_type: Option<String>,
pub signature_algorithm: Option<String>,
pub renew_delay: Option<String>,
}
@ -217,14 +215,7 @@ impl Endpoint {
let (nb, timeframe) = cnf.get_rate_limit(&rl_name)?;
limits.push((nb, timeframe));
}
crate::endpoint::Endpoint::new(
&self.name,
&self.url,
self.tos_agreed,
&limits,
&self.key_type,
&self.signature_algorithm,
)
crate::endpoint::Endpoint::new(&self.name, &self.url, self.tos_agreed, &limits)
}
}
@ -285,6 +276,19 @@ pub struct Group {
pub struct Account {
pub name: String,
pub email: String,
pub key_type: Option<String>,
pub signature_algorithm: Option<String>,
}
impl Account {
pub fn to_generic(&self) -> Result<crate::account::Account, Error> {
crate::account::Account::new(
&self.name,
&self.email,
&self.key_type,
&self.signature_algorithm,
)
}
}
#[derive(Deserialize)]
@ -306,10 +310,11 @@ pub struct Certificate {
}
impl Certificate {
pub fn get_account(&self, cnf: &Config) -> Result<Account, Error> {
pub fn get_account(&self, cnf: &Config) -> Result<crate::account::Account, Error> {
for account in cnf.account.iter() {
if account.name == self.account {
return Ok(account.clone());
let acc = account.to_generic()?;
return Ok(acc);
}
}
Err(format!("{}: account not found", self.account).into())

20
acmed/src/endpoint.rs

@ -1,9 +1,7 @@
use crate::acme_proto::structs::Directory;
use crate::duration::parse_duration;
use acme_common::crypto::{JwsSignatureAlgorithm, KeyType};
use acme_common::error::Error;
use std::cmp;
use std::str::FromStr;
use std::thread;
use std::time::{Duration, Instant};
@ -15,8 +13,6 @@ pub struct Endpoint {
pub nonce: Option<String>,
pub rl: RateLimit,
pub dir: Directory,
pub key_type: KeyType,
pub signature_algorithm: JwsSignatureAlgorithm,
}
impl Endpoint {
@ -25,25 +21,13 @@ impl Endpoint {
url: &str,
tos_agreed: bool,
limits: &[(usize, String)],
key_type: &Option<String>,
signature_algorithm: &Option<String>,
) -> Result<Self, Error> {
let rl = RateLimit::new(limits)?;
let key_type = match key_type {
Some(kt) => KeyType::from_str(&kt)?,
None => crate::DEFAULT_ACCOUNT_KEY_TYPE,
};
let signature_algorithm = match signature_algorithm {
Some(sa) => JwsSignatureAlgorithm::from_str(&sa)?,
None => key_type.get_default_signature_alg(),
};
let _ = key_type.check_alg_compatibility(&signature_algorithm)?;
Ok(Self {
name: name.to_string(),
url: url.to_string(),
tos_agreed,
nonce: None,
rl,
rl: RateLimit::new(limits)?,
dir: Directory {
meta: None,
new_nonce: String::new(),
@ -53,8 +37,6 @@ impl Endpoint {
revoke_cert: String::new(),
key_change: String::new(),
},
key_type,
signature_algorithm,
})
}
}

1
acmed/src/main.rs

@ -3,6 +3,7 @@ use acme_common::{clean_pid_file, crypto, init_server};
use clap::{App, Arg};
use log::error;
mod account;
mod acme_proto;
mod certificate;
mod config;

2
acmed/src/main_event_loop.rs

@ -65,10 +65,10 @@ impl MainEventLoop {
id: i + 1,
renew_delay: crt.get_renew_delay(&cnf)?,
};
init_account(&cert, &endpoint)?;
endpoints
.entry(endpoint_name)
.or_insert_with(|| Arc::new(RwLock::new(endpoint)));
init_account(&cert)?;
certs.push(cert);
}

50
man/en/acmed.toml.5

@ -95,29 +95,6 @@ Set whether or not the user agrees to the Terms Of Service
.Pq TOS .
.It Cm url Ar string
The endpoint's directory URL.
.It Cm key_type Ar string
Name of the asymmetric cryptography algorithm used to generate the client account's key pair. Possible values are :
.Bl -dash -compact
.It
rsa2048
.It
rsa4096
.It
ecdsa_p256
.Aq default
.It
ecdsa_p384
.El
.It Cm signature_algorithm Ar string
Name of the signature algorithm used to sign the messages sent to the endpoint. The default value is derived from the key type. Possible values are:
.Bl -dash -compact
.It
RS256
.It
ES256
.It
ES384
.El
.It Cm renew_delay Ar string
Period of time between the certificate renewal and its expiration date. The format is described in the
.Sx TIME PERIODS
@ -182,12 +159,37 @@ The name the group is registered under. This name is considered as a hook name.
Array containing the names of the hooks that are grouped. The hooks are guaranteed to be called sequentially in the declaration order.
.El
.It Ic account
Array of table representing an account on one or several CA.
Array of table representing an account on one or several endpoint.
.Bl -tag
.It Ic name Ar string
The name the account is registered under. Must be unique.
.It Ic email Ar string
The email address used to contact the account's holder.
.It Cm key_type Ar string
Name of the asymmetric cryptography algorithm used to generate the key pair. Possible values are :
.Bl -dash -compact
.It
rsa2048
.It
rsa4096
.It
ecdsa_p256
.Aq default
.It
ecdsa_p384
.El
.It Cm signature_algorithm Ar string
Name of the signature algorithm used to sign the messages sent to the endpoint as defined in
.Em RFC 7518 .
The default value is derived from the key type. Possible values are:
.Bl -dash -compact
.It
RS256
.It
ES256
.It
ES384
.El
.El
.It Ic certificate
Array of table representing a certificate that will be requested to a CA.

Loading…
Cancel
Save