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. - 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). - 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. - 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 ### Changed
- In the certificate configuration, the `domains` field has been renamed `identifiers`. - 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" base64 = "0.12"
daemonize = "0.4" daemonize = "0.4"
env_logger = "0.7" env_logger = "0.7"
glob = "0.3"
handlebars = "3.0" handlebars = "3.0"
log = "0.4" log = "0.4"
native-tls = "0.2" 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 { impl From<handlebars::TemplateRenderError> for Error {
fn from(error: handlebars::TemplateRenderError) -> Self { fn from(error: handlebars::TemplateRenderError) -> Self {
format!("Template error: {}", error).into() 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" } acme_common = { path = "../acme_common" }
attohttpc = { version = "0.15", default-features = false, features = ["charsets", "json"] } attohttpc = { version = "0.15", default-features = false, features = ["charsets", "json"] }
clap = "2.32" clap = "2.32"
glob = "0.3"
handlebars = "3.0" handlebars = "3.0"
log = "0.4" log = "0.4"
nom = "5.0" nom = "5.0"

57
acmed/src/config.rs

@ -3,6 +3,7 @@ use crate::duration::parse_duration;
use crate::hooks; use crate::hooks;
use crate::identifier::IdentifierType; use crate::identifier::IdentifierType;
use acme_common::error::Error; use acme_common::error::Error;
use glob::glob;
use log::info; use log::info;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
@ -10,6 +11,7 @@ use std::fmt;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::prelude::*; use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::result::Result;
use std::time::Duration; use std::time::Duration;
macro_rules! set_cfg_attr { macro_rules! set_cfg_attr {
@ -456,11 +458,13 @@ fn init_directories(config: &Config) -> Result<(), Error> {
Ok(()) 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(); let mut path = from.clone();
path.pop(); path.pop();
path.push(file); 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> { 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)?; file.read_to_string(&mut contents)?;
let mut config: Config = toml::from_str(&contents)?; let mut config: Config = toml::from_str(&contents)?;
for cnf_name in config.include.iter() { 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) Ok(config)

2
man/en/acmed.toml.5

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

Loading…
Cancel
Save