Browse Source

Add the file_name_format config directive

pull/41/head
Rodolphe Breard 4 years ago
parent
commit
b7d848adef
  1. 3
      CHANGELOG.md
  2. 28
      acmed/src/config.rs
  3. 2
      acmed/src/main.rs
  4. 2
      acmed/src/main_event_loop.rs
  5. 26
      acmed/src/storage.rs
  6. 50
      man/en/acmed.toml.5

3
CHANGELOG.md

@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
- The names of both the certificate file and the associated private key can now be configured.
### Fixed ### Fixed
- Configuration files cannot be loaded more than one time, which prevents infinite recursion. - Configuration files cannot be loaded more than one time, which prevents infinite recursion.

28
acmed/src/config.rs

@ -182,6 +182,7 @@ pub struct GlobalOptions {
pub certificates_directory: Option<String>, pub certificates_directory: Option<String>,
#[serde(default)] #[serde(default)]
pub env: HashMap<String, String>, pub env: HashMap<String, String>,
pub file_name_format: Option<String>,
pub pk_file_group: Option<String>, pub pk_file_group: Option<String>,
pub pk_file_mode: Option<u32>, pub pk_file_mode: Option<u32>,
pub pk_file_user: Option<String>, pub pk_file_user: Option<String>,
@ -196,11 +197,19 @@ impl GlobalOptions {
None => Ok(Duration::new(crate::DEFAULT_CERT_RENEW_DELAY, 0)), None => Ok(Duration::new(crate::DEFAULT_CERT_RENEW_DELAY, 0)),
} }
} }
pub fn get_crt_name_format(&self) -> String {
match &self.file_name_format {
Some(n) => n.to_string(),
None => crate::DEFAULT_CERT_FORMAT.to_string(),
}
}
} }
#[derive(Clone, Deserialize)] #[derive(Clone, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Endpoint { pub struct Endpoint {
pub file_name_format: Option<String>,
pub name: String, pub name: String,
#[serde(default)] #[serde(default)]
pub rate_limits: Vec<String>, pub rate_limits: Vec<String>,
@ -221,6 +230,16 @@ impl Endpoint {
} }
} }
pub fn get_crt_name_format(&self, cnf: &Config) -> String {
match &self.file_name_format {
Some(n) => n.to_string(),
None => match &cnf.global {
Some(g) => g.get_crt_name_format(),
None => crate::DEFAULT_CERT_FORMAT.to_string(),
},
}
}
fn to_generic( fn to_generic(
&self, &self,
cnf: &Config, cnf: &Config,
@ -468,10 +487,13 @@ impl Certificate {
Ok(name) Ok(name)
} }
pub fn get_crt_name_format(&self) -> String {
pub fn get_crt_name_format(&self, cnf: &Config) -> Result<String, Error> {
match &self.file_name_format { match &self.file_name_format {
Some(n) => n.to_string(),
None => crate::DEFAULT_CERT_FORMAT.to_string(),
Some(n) => Ok(n.to_string()),
None => {
let ep = self.do_get_endpoint(cnf)?;
Ok(ep.get_crt_name_format(cnf))
}
} }
} }

2
acmed/src/main.rs

@ -27,7 +27,7 @@ pub const DEFAULT_PID_FILE: &str = "/var/run/acmed.pid";
pub const DEFAULT_CONFIG_FILE: &str = "/etc/acmed/acmed.toml"; pub const DEFAULT_CONFIG_FILE: &str = "/etc/acmed/acmed.toml";
pub const DEFAULT_ACCOUNTS_DIR: &str = "/etc/acmed/accounts"; pub const DEFAULT_ACCOUNTS_DIR: &str = "/etc/acmed/accounts";
pub const DEFAULT_CERT_DIR: &str = "/etc/acmed/certs"; pub const DEFAULT_CERT_DIR: &str = "/etc/acmed/certs";
pub const DEFAULT_CERT_FORMAT: &str = "{{name}}_{{algo}}.{{file_type}}.{{ext}}";
pub const DEFAULT_CERT_FORMAT: &str = "{{name}}_{{key_type}}.{{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;

2
acmed/src/main_event_loop.rs

@ -101,7 +101,7 @@ impl MainEventLoop {
account_directory: cnf.get_account_dir(), account_directory: cnf.get_account_dir(),
account_name: crt.account.clone(), account_name: crt.account.clone(),
crt_name: crt_name.clone(), crt_name: crt_name.clone(),
crt_name_format: crt.get_crt_name_format(),
crt_name_format: crt.get_crt_name_format(&cnf)?,
crt_directory: crt.get_crt_dir(&cnf), crt_directory: crt.get_crt_dir(&cnf),
crt_key_type: key_type.to_string(), crt_key_type: key_type.to_string(),
cert_file_mode: cnf.get_cert_file_mode(), cert_file_mode: cnf.get_cert_file_mode(),

26
acmed/src/storage.rs

@ -3,6 +3,8 @@ use crate::logs::HasLogger;
use acme_common::b64_encode; use acme_common::b64_encode;
use acme_common::crypto::{KeyPair, X509Certificate}; use acme_common::crypto::{KeyPair, X509Certificate};
use acme_common::error::Error; use acme_common::error::Error;
use handlebars::Handlebars;
use serde::Serialize;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
@ -77,6 +79,14 @@ impl fmt::Display for FileType {
} }
} }
#[derive(Clone, Serialize)]
pub struct CertFileFormat {
pub ext: String,
pub file_type: String,
pub key_type: String,
pub name: String,
}
fn get_file_full_path( fn get_file_full_path(
fm: &FileManager, fm: &FileManager,
file_type: FileType, file_type: FileType,
@ -94,14 +104,14 @@ fn get_file_full_path(
ext = "bin" ext = "bin"
), ),
FileType::PrivateKey | FileType::Certificate => { FileType::PrivateKey | FileType::Certificate => {
// TODO: use fm.crt_name_format instead of a string literal
format!(
"{name}_{algo}.{file_type}.{ext}",
name = fm.crt_name,
algo = fm.crt_key_type,
file_type = file_type.to_string(),
ext = "pem"
)
let fmt_data = CertFileFormat {
key_type: fm.crt_key_type.to_string(),
ext: "pem".into(),
file_type: file_type.to_string(),
name: fm.crt_name.to_owned(),
};
let reg = Handlebars::new();
reg.render_template(&fm.crt_name_format, &fmt_data)?
} }
}; };
let mut path = PathBuf::from(&base_path); let mut path = PathBuf::from(&base_path);

50
man/en/acmed.toml.5

@ -27,7 +27,13 @@ Array of tables describing describing the account holder's contact information.
.It Ic mailto Ar string .It Ic mailto Ar string
A mailto URI as defined by A mailto URI as defined by
.Em RFC 6068 . .Em RFC 6068 .
This URI cannot contains neither "hfields" nor more than one "addr-spec" in the "to" component.
This URI cannot contains neither
.Dq hfields
nor more than one
.Dq addr-spec
in the
.Dq to
component.
.El .El
.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.
@ -110,6 +116,36 @@ Path to the directory where certificates and their associated private keys are s
Name of the endpoint to use. Name of the endpoint to use.
.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.
.It Ic file_name_format Ar string
Template used to build the file's name. The template syntax is
.Em Handlebars .
See the
.Sx STANDARDS
section for a link to the
.Em Handlebars
specifications. If not specified, the value defined in the
.Em endpoint
element, and then the
.Em global
element, is used. Default is
.Dq {{name}}_{{key_type}}.{{file_type}}.{{ext}} .
Possible variables are:
.Bl -tag
.It Ic ext Ar string
File extension. Currently, only
.Dq pem
is supported.
.It Ic file_type Ar string
Contains
.Dq pk
for the private key file and
.Dq crt
for the certificate file.
.It Ic key_type Ar string
The certificate's private key type.
.It Ic name Ar string
The certificate's name.
.El
.It Ic hooks Ar array .It Ic hooks Ar array
Names of hooks that will be called when requesting a new certificate. The hooks are guaranteed to be called sequentially in the declaration order. Names of hooks that will be called when requesting a new certificate. The hooks are guaranteed to be called sequentially in the declaration order.
.It Ic identifiers Ar array .It Ic identifiers Ar array
@ -204,6 +240,12 @@ Array of table where each element defines a Certificate Authority
.Pq CA .Pq CA
which may be used to request certificates. which may be used to request certificates.
.Bl -tag .Bl -tag
.It Cm file_name_format Ar string
Template used to build the file's name. For detailed documentation, see the
.Em file_name_format
directive located in the
.Em certificate
element.
.It Cm name Ar string .It Cm name Ar string
The name the endpoint is registered under. Must be unique. The name the endpoint is registered under. Must be unique.
.It Cm rate_limits Ar array .It Cm rate_limits Ar array
@ -241,6 +283,12 @@ for more details.
Specify the directory where the certificates and their associated private keys are stored. Specify the directory where the certificates and their associated private keys are stored.
.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.
.It Ic file_name_format Ar string
Template used to build the file's name. For detailed documentation, see the
.Em file_name_format
directive located in the
.Em certificate
element.
.It Cm pk_file_group Ar group_name|group_id Ft string .It Cm pk_file_group Ar group_name|group_id Ft string
Specify the group who will own newly-created private-key files. See Specify the group who will own newly-created private-key files. See
.Xr chown 2 .Xr chown 2

Loading…
Cancel
Save