Browse Source

Refactor the certificate key type management

The previous system used a duplicated enum
(`acmed::certificate::Algorithm`) and an imprecise identifier name
(algorithm) for both the certificate configuration and post operation
hook variable. The first one has been replaced by the
`acme_common::crypto::KeyType` enum and the second renames `key_type`.
pull/39/head
Rodolphe Breard 4 years ago
parent
commit
52fe2c60ba
  1. 2
      CHANGELOG.md
  2. 1
      acme_common/src/crypto.rs
  3. 12
      acmed/src/acme_proto/certificate.rs
  4. 38
      acmed/src/certificate.rs
  5. 16
      acmed/src/config.rs
  6. 2
      acmed/src/hooks.rs
  7. 11
      acmed/src/main.rs
  8. 2
      acmed/src/main_event_loop.rs
  9. 2
      acmed/src/storage.rs
  10. 8
      man/en/acmed.toml.5

2
CHANGELOG.md

@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- In the certificate configuration, the `domains` field has been renamed `identifiers`. - In the certificate configuration, the `domains` field has been renamed `identifiers`.
- The `algorithm` certificate configuration field has been renamed `key_type`.
- The `algorithm` hook template variable has been renamed `key_type`.
- The `domain` hook template variable has been renamed `identifier`. - The `domain` hook template variable has been renamed `identifier`.
- The default hooks have been updated. - The default hooks have been updated.

1
acme_common/src/crypto.rs

@ -8,7 +8,6 @@ mod openssl_certificate;
mod openssl_hash; mod openssl_hash;
mod openssl_keys; mod openssl_keys;
pub const DEFAULT_ALGO: &str = "rsa2048";
pub const TLS_LIB_NAME: &str = env!("ACMED_TLS_LIB_NAME"); pub const TLS_LIB_NAME: &str = env!("ACMED_TLS_LIB_NAME");
pub const TLS_LIB_VERSION: &str = env!("ACMED_TLS_LIB_VERSION"); pub const TLS_LIB_VERSION: &str = env!("ACMED_TLS_LIB_VERSION");

12
acmed/src/acme_proto/certificate.rs

@ -1,16 +1,10 @@
use crate::certificate::{Algorithm, Certificate};
use crate::certificate::Certificate;
use crate::storage; use crate::storage;
use acme_common::crypto::{gen_keypair, KeyPair, KeyType};
use acme_common::crypto::{gen_keypair, KeyPair};
use acme_common::error::Error; use acme_common::error::Error;
fn gen_key_pair(cert: &Certificate) -> Result<KeyPair, Error> { fn gen_key_pair(cert: &Certificate) -> Result<KeyPair, Error> {
let key_type = match cert.algo {
Algorithm::Rsa2048 => KeyType::Rsa2048,
Algorithm::Rsa4096 => KeyType::Rsa4096,
Algorithm::EcdsaP256 => KeyType::EcdsaP256,
Algorithm::EcdsaP384 => KeyType::EcdsaP384,
};
let key_pair = gen_keypair(key_type)?;
let key_pair = gen_keypair(cert.key_type)?;
storage::set_keypair(cert, &key_pair)?; storage::set_keypair(cert, &key_pair)?;
Ok(key_pair) Ok(key_pair)
} }

38
acmed/src/certificate.rs

@ -3,50 +3,18 @@ use crate::acme_proto::Challenge;
use crate::hooks::{self, ChallengeHookData, Hook, HookEnvData, HookType, PostOperationHookData}; use crate::hooks::{self, ChallengeHookData, Hook, HookEnvData, HookType, PostOperationHookData};
use crate::identifier::{Identifier, IdentifierType}; use crate::identifier::{Identifier, IdentifierType};
use crate::storage::{certificate_files_exists, get_certificate}; use crate::storage::{certificate_files_exists, get_certificate};
use acme_common::crypto::{HashFunction, X509Certificate};
use acme_common::crypto::{HashFunction, KeyType, X509Certificate};
use acme_common::error::Error; use acme_common::error::Error;
use log::{debug, info, trace, warn}; use log::{debug, info, trace, warn};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fmt; use std::fmt;
use std::time::Duration; use std::time::Duration;
#[derive(Clone, Debug)]
pub enum Algorithm {
Rsa2048,
Rsa4096,
EcdsaP256,
EcdsaP384,
}
impl Algorithm {
pub fn from_str(s: &str) -> Result<Self, Error> {
match s.to_lowercase().as_str() {
"rsa2048" => Ok(Algorithm::Rsa2048),
"rsa4096" => Ok(Algorithm::Rsa4096),
"ecdsa_p256" => Ok(Algorithm::EcdsaP256),
"ecdsa_p384" => Ok(Algorithm::EcdsaP384),
_ => Err(format!("{}: unknown algorithm.", s).into()),
}
}
}
impl fmt::Display for Algorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = match self {
Algorithm::Rsa2048 => "rsa2048",
Algorithm::Rsa4096 => "rsa4096",
Algorithm::EcdsaP256 => "ecdsa-p256",
Algorithm::EcdsaP384 => "ecdsa-p384",
};
write!(f, "{}", s)
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Certificate { pub struct Certificate {
pub account: Account, pub account: Account,
pub identifiers: Vec<Identifier>, pub identifiers: Vec<Identifier>,
pub algo: Algorithm,
pub key_type: KeyType,
pub csr_digest: HashFunction, pub csr_digest: HashFunction,
pub kp_reuse: bool, pub kp_reuse: bool,
pub endpoint_name: String, pub endpoint_name: String,
@ -221,7 +189,7 @@ impl Certificate {
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let mut hook_data = PostOperationHookData { let mut hook_data = PostOperationHookData {
identifiers, identifiers,
algorithm: self.algo.to_string(),
key_type: self.key_type.to_string(),
status: status.to_string(), status: status.to_string(),
is_success, is_success,
env: HashMap::new(), env: HashMap::new(),

16
acmed/src/config.rs

@ -1,8 +1,7 @@
use crate::certificate::Algorithm;
use crate::duration::parse_duration; use crate::duration::parse_duration;
use crate::hooks; use crate::hooks;
use crate::identifier::IdentifierType; use crate::identifier::IdentifierType;
use acme_common::crypto::HashFunction;
use acme_common::crypto::{HashFunction, KeyType};
use acme_common::error::Error; use acme_common::error::Error;
use glob::glob; use glob::glob;
use log::info; use log::info;
@ -298,7 +297,7 @@ pub struct Certificate {
pub account: String, pub account: String,
pub endpoint: String, pub endpoint: String,
pub identifiers: Vec<Identifier>, pub identifiers: Vec<Identifier>,
pub algorithm: Option<String>,
pub key_type: Option<String>,
pub csr_digest: Option<String>, pub csr_digest: Option<String>,
pub kp_reuse: Option<bool>, pub kp_reuse: Option<bool>,
pub directory: Option<String>, pub directory: Option<String>,
@ -322,12 +321,11 @@ impl Certificate {
Err(format!("{}: account not found", self.account).into()) Err(format!("{}: account not found", self.account).into())
} }
pub fn get_algorithm(&self) -> Result<Algorithm, Error> {
let algo = match &self.algorithm {
Some(a) => &a,
None => acme_common::crypto::DEFAULT_ALGO,
};
Algorithm::from_str(algo)
pub fn get_key_type(&self) -> Result<KeyType, Error> {
match &self.key_type {
Some(a) => a.parse(),
None => Ok(crate::DEFAULT_CERT_KEY_TYPE),
}
} }
pub fn get_csr_digest(&self) -> Result<HashFunction, Error> { pub fn get_csr_digest(&self) -> Result<HashFunction, Error> {

2
acmed/src/hooks.rs

@ -44,7 +44,7 @@ macro_rules! imple_hook_data_env {
#[derive(Clone, Serialize)] #[derive(Clone, Serialize)]
pub struct PostOperationHookData { pub struct PostOperationHookData {
pub identifiers: Vec<String>, pub identifiers: Vec<String>,
pub algorithm: String,
pub key_type: String,
pub status: String, pub status: String,
pub is_success: bool, pub is_success: bool,
pub env: HashMap<String, String>, pub env: HashMap<String, String>,

11
acmed/src/main.rs

@ -1,7 +1,7 @@
use crate::main_event_loop::MainEventLoop; use crate::main_event_loop::MainEventLoop;
use acme_common::crypto::HashFunction;
use acme_common::crypto::{HashFunction, KeyType, TLS_LIB_NAME, TLS_LIB_VERSION};
use acme_common::logs::{set_log_system, DEFAULT_LOG_LEVEL}; use acme_common::logs::{set_log_system, DEFAULT_LOG_LEVEL};
use acme_common::{clean_pid_file, crypto, init_server};
use acme_common::{clean_pid_file, init_server};
use clap::{App, Arg}; use clap::{App, Arg};
use log::error; use log::error;
@ -28,12 +28,13 @@ pub const DEFAULT_CERT_FORMAT: &str = "{{name}}_{{algo}}.{{file_type}}.{{ext}}";
pub const DEFAULT_SLEEP_TIME: u64 = 3600; pub const DEFAULT_SLEEP_TIME: u64 = 3600;
pub const DEFAULT_POOL_TIME: u64 = 5000; pub const DEFAULT_POOL_TIME: u64 = 5000;
pub const DEFAULT_CSR_DIGEST: HashFunction = HashFunction::Sha256; pub const DEFAULT_CSR_DIGEST: HashFunction = HashFunction::Sha256;
pub const DEFAULT_CERT_KEY_TYPE: KeyType = KeyType::Rsa2048;
pub const DEFAULT_CERT_FILE_MODE: u32 = 0o644; pub const DEFAULT_CERT_FILE_MODE: u32 = 0o644;
pub const DEFAULT_CERT_RENEW_DELAY: u64 = 1_814_400; // 1_814_400 is 3 weeks (3 * 7 * 24 * 60 * 60) pub const DEFAULT_CERT_RENEW_DELAY: u64 = 1_814_400; // 1_814_400 is 3 weeks (3 * 7 * 24 * 60 * 60)
pub const DEFAULT_PK_FILE_MODE: u32 = 0o600; pub const DEFAULT_PK_FILE_MODE: u32 = 0o600;
pub const DEFAULT_ACCOUNT_FILE_MODE: u32 = 0o600; pub const DEFAULT_ACCOUNT_FILE_MODE: u32 = 0o600;
pub const DEFAULT_KP_REUSE: bool = false; pub const DEFAULT_KP_REUSE: bool = false;
pub const DEFAULT_ACCOUNT_KEY_TYPE: crypto::KeyType = crypto::KeyType::EcdsaP256;
pub const DEFAULT_ACCOUNT_KEY_TYPE: KeyType = KeyType::EcdsaP256;
pub const DEFAULT_POOL_NB_TRIES: usize = 20; pub const DEFAULT_POOL_NB_TRIES: usize = 20;
pub const DEFAULT_POOL_WAIT_SEC: u64 = 5; pub const DEFAULT_POOL_WAIT_SEC: u64 = 5;
pub const DEFAULT_HTTP_FAIL_NB_RETRY: usize = 10; pub const DEFAULT_HTTP_FAIL_NB_RETRY: usize = 10;
@ -47,8 +48,8 @@ fn main() {
"{} {}\n\nCompiled with:\n {} {}\n {} {}", "{} {}\n\nCompiled with:\n {} {}\n {} {}",
APP_VERSION, APP_VERSION,
env!("ACMED_TARGET"), env!("ACMED_TARGET"),
crypto::TLS_LIB_NAME,
crypto::TLS_LIB_VERSION,
TLS_LIB_NAME,
TLS_LIB_VERSION,
env!("ACMED_HTTP_LIB_NAME"), env!("ACMED_HTTP_LIB_NAME"),
env!("ACMED_HTTP_LIB_VERSION") env!("ACMED_HTTP_LIB_VERSION")
); );

2
acmed/src/main_event_loop.rs

@ -47,7 +47,7 @@ impl MainEventLoop {
let cert = Certificate { let cert = Certificate {
account: crt.get_account(&cnf)?, account: crt.get_account(&cnf)?,
identifiers: crt.get_identifiers()?, identifiers: crt.get_identifiers()?,
algo: crt.get_algorithm()?,
key_type: crt.get_key_type()?,
csr_digest: crt.get_csr_digest()?, csr_digest: crt.get_csr_digest()?,
kp_reuse: crt.get_kp_reuse(), kp_reuse: crt.get_kp_reuse(),
endpoint_name: endpoint_name.clone(), endpoint_name: endpoint_name.clone(),

2
acmed/src/storage.rs

@ -53,7 +53,7 @@ fn get_file_full_path(
format!( format!(
"{name}_{algo}.{file_type}.{ext}", "{name}_{algo}.{file_type}.{ext}",
name = cert.crt_name, name = cert.crt_name,
algo = cert.algo.to_string(),
algo = cert.key_type.to_string(),
file_type = file_type.to_string(), file_type = file_type.to_string(),
ext = "pem" ext = "pem"
) )

8
man/en/acmed.toml.5

@ -226,7 +226,7 @@ The IP address.
.It Ic env Ar table .It Ic env Ar table
Table of environment variables that will be accessible from hooks. Table of environment variables that will be accessible from hooks.
.El .El
.It Ic algorithm Ar string
.It Ic key_type Ar string
Name of the asymmetric cryptography algorithm used to generate the certificate's key pair. Possible values are : Name of the asymmetric cryptography algorithm used to generate the certificate's key pair. Possible values are :
.Bl -dash -compact .Bl -dash -compact
.It .It
@ -437,8 +437,8 @@ type.
.It Ic post-operation .It Ic post-operation
Invoked at the end of the certificate request process. The available template variables are: Invoked at the end of the certificate request process. The available template variables are:
.Bl -tag -compact .Bl -tag -compact
.It Cm algorithm Ar string
Name of the algorithm used in the certificate.
.It Cm key_type Ar string
Name of the asymmetric cryptography algorithm used to generate the certificate's key pair.
.It Cm identifiers Ar string .It Cm identifiers Ar string
Array containing the identifiers included in the requested certificate. Array containing the identifiers included in the requested certificate.
.It Cm env Ar array .It Cm env Ar array
@ -670,7 +670,7 @@ stdin_str = """Subject: Certificate renewal {{#if is_success}}succeeded{{else}}f
The following certificate has {{#unless is_success}}*not* {{/unless}}been renewed. The following certificate has {{#unless is_success}}*not* {{/unless}}been renewed.
identifiers: {{#each identifiers}}{{#if @index}}, {{/if}}{{this}}{{/each}} identifiers: {{#each identifiers}}{{#if @index}}, {{/if}}{{this}}{{/each}}
algorithm: {{algorithm}}
key type: {{key_type}}
status: {{status}}""" status: {{status}}"""
.Ed .Ed
.Sh SEE ALSO .Sh SEE ALSO

Loading…
Cancel
Save