Browse Source

Add Unix style globing for config file inclusion

Close #6
pull/39/head
Rodolphe Breard 4 years ago
parent
commit
2f39e798d1
  1. 1
      CHANGELOG.md
  2. 1
      acme_common/Cargo.toml
  3. 6
      acme_common/src/error.rs
  4. 1
      acmed/Cargo.toml
  5. 57
      acmed/src/config.rs
  6. 2
      man/en/acmed.toml.5

1
CHANGELOG.md

@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The delay to renew a certificate before its expiration date can be specified in the configuration using the `renew_delay` parameter at either the certificate, endpoint and global level.
- It is now possible to specify IP identifiers (RFC 8738).
- The hook templates of type `challenge-*` have a new `identifier_tls_alpn` field which contains, if available, the identifier in a form that is suitable to the TLS ALPN challenge.
- Globing is now supported for configuration files inclusion.
### Changed
- In the certificate configuration, the `domains` field has been renamed `identifiers`.

1
acme_common/Cargo.toml

@ -22,6 +22,7 @@ attohttpc = { version = "0.15", default-features = false }
base64 = "0.12"
daemonize = "0.4"
env_logger = "0.7"
glob = "0.3"
handlebars = "3.0"
log = "0.4"
native-tls = "0.2"

6
acme_common/src/error.rs

@ -93,6 +93,12 @@ impl From<attohttpc::Error> for Error {
}
}
impl From<glob::PatternError> for Error {
fn from(error: glob::PatternError) -> Self {
format!("Pattern error: {}", error).into()
}
}
impl From<handlebars::TemplateRenderError> for Error {
fn from(error: handlebars::TemplateRenderError) -> Self {
format!("Template error: {}", error).into()

1
acmed/Cargo.toml

@ -20,6 +20,7 @@ openssl_dyn = ["acme_common/openssl_dyn", "attohttpc/tls"]
acme_common = { path = "../acme_common" }
attohttpc = { version = "0.15", default-features = false, features = ["charsets", "json"] }
clap = "2.32"
glob = "0.3"
handlebars = "3.0"
log = "0.4"
nom = "5.0"

57
acmed/src/config.rs

@ -3,6 +3,7 @@ use crate::duration::parse_duration;
use crate::hooks;
use crate::identifier::IdentifierType;
use acme_common::error::Error;
use glob::glob;
use log::info;
use serde::Deserialize;
use std::collections::HashMap;
@ -10,6 +11,7 @@ use std::fmt;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::result::Result;
use std::time::Duration;
macro_rules! set_cfg_attr {
@ -456,11 +458,13 @@ fn init_directories(config: &Config) -> Result<(), Error> {
Ok(())
}
fn get_cnf_path(from: &PathBuf, file: &str) -> PathBuf {
fn get_cnf_path(from: &PathBuf, file: &str) -> Result<Vec<PathBuf>, Error> {
let mut path = from.clone();
path.pop();
path.push(file);
path
let err = format!("{:?}: invalid UTF-8 path", path);
let raw_path = path.to_str().ok_or(err)?;
Ok(glob(raw_path)?.filter_map(Result::ok).collect())
}
fn read_cnf(path: &PathBuf) -> Result<Config, Error> {
@ -470,30 +474,31 @@ fn read_cnf(path: &PathBuf) -> Result<Config, Error> {
file.read_to_string(&mut contents)?;
let mut config: Config = toml::from_str(&contents)?;
for cnf_name in config.include.iter() {
let cnf_path = get_cnf_path(path, cnf_name);
let mut add_cnf = read_cnf(&cnf_path)?;
config.endpoint.append(&mut add_cnf.endpoint);
config.rate_limit.append(&mut add_cnf.rate_limit);
config.hook.append(&mut add_cnf.hook);
config.group.append(&mut add_cnf.group);
config.account.append(&mut add_cnf.account);
config.certificate.append(&mut add_cnf.certificate);
if config.global.is_none() {
config.global = add_cnf.global;
} else if let Some(new_glob) = add_cnf.global {
let mut tmp_glob = config.global.clone().unwrap();
set_cfg_attr!(tmp_glob.accounts_directory, new_glob.accounts_directory);
set_cfg_attr!(
tmp_glob.certificates_directory,
new_glob.certificates_directory
);
set_cfg_attr!(tmp_glob.cert_file_mode, new_glob.cert_file_mode);
set_cfg_attr!(tmp_glob.cert_file_user, new_glob.cert_file_user);
set_cfg_attr!(tmp_glob.cert_file_group, new_glob.cert_file_group);
set_cfg_attr!(tmp_glob.pk_file_mode, new_glob.pk_file_mode);
set_cfg_attr!(tmp_glob.pk_file_user, new_glob.pk_file_user);
set_cfg_attr!(tmp_glob.pk_file_group, new_glob.pk_file_group);
config.global = Some(tmp_glob);
for cnf_path in get_cnf_path(path, cnf_name)? {
let mut add_cnf = read_cnf(&cnf_path)?;
config.endpoint.append(&mut add_cnf.endpoint);
config.rate_limit.append(&mut add_cnf.rate_limit);
config.hook.append(&mut add_cnf.hook);
config.group.append(&mut add_cnf.group);
config.account.append(&mut add_cnf.account);
config.certificate.append(&mut add_cnf.certificate);
if config.global.is_none() {
config.global = add_cnf.global;
} else if let Some(new_glob) = add_cnf.global {
let mut tmp_glob = config.global.clone().unwrap();
set_cfg_attr!(tmp_glob.accounts_directory, new_glob.accounts_directory);
set_cfg_attr!(
tmp_glob.certificates_directory,
new_glob.certificates_directory
);
set_cfg_attr!(tmp_glob.cert_file_mode, new_glob.cert_file_mode);
set_cfg_attr!(tmp_glob.cert_file_user, new_glob.cert_file_user);
set_cfg_attr!(tmp_glob.cert_file_group, new_glob.cert_file_group);
set_cfg_attr!(tmp_glob.pk_file_mode, new_glob.pk_file_mode);
set_cfg_attr!(tmp_glob.pk_file_user, new_glob.pk_file_user);
set_cfg_attr!(tmp_glob.pk_file_group, new_glob.pk_file_group);
config.global = Some(tmp_glob);
}
}
}
Ok(config)

2
man/en/acmed.toml.5

@ -29,6 +29,8 @@ and
.Em C
and all three defines the same global option, the final value will be the one defined in file
.Em C .
.Pp
Unix style globing is supported.
.It Ic global
Table containing the global configuration options.
.Bl -tag

Loading…
Cancel
Save