diff --git a/CHANGELOG.md b/CHANGELOG.md index cb64171..7940fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added +- Hooks now have the optional `allow_failure` field. + + ## [0.5.0] - 2019-05-09 ### Added diff --git a/acmed/config/default_hooks.toml b/acmed/config/default_hooks.toml index 42b9f49..e52d723 100644 --- a/acmed/config/default_hooks.toml +++ b/acmed/config/default_hooks.toml @@ -23,6 +23,7 @@ args = [ "-m", "0755", "-p", "{{#if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{domain}}/.well-known/acme-challenge" ] +allow_failure = true [[hook]] name = "http-01-echo-echo" @@ -39,6 +40,7 @@ args = [ "a+r", "{{#if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{domain}}/.well-known/acme-challenge/{{file_name}}" ] +allow_failure = true [[hook]] name = "http-01-echo-clean" @@ -48,6 +50,7 @@ args = [ "-f", "{{#if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{domain}}/.well-known/acme-challenge/{{file_name}}" ] +allow_failure = true [[group]] name = "http-01-echo" @@ -92,6 +95,7 @@ cmd = "pkill" args = [ "-F", "{{#if env.TACD_PID_ROOT}}{{env.TACD_PID_ROOT}}{{else}}/run{{/if}}/tacd_{{domain}}.pid", ] +allow_failure = true [[hook]] name = "tls-alpn-01-tacd-rm" @@ -100,6 +104,7 @@ cmd = "rm" args = [ "-f", "{{#if env.TACD_PID_ROOT}}{{env.TACD_PID_ROOT}}{{else}}/run{{/if}}/tacd_{{domain}}.pid", ] +allow_failure = true [[group]] name = "tls-alpn-01-tacd-tcp" diff --git a/acmed/src/config.rs b/acmed/src/config.rs index 3fbbdf3..8e88c42 100644 --- a/acmed/src/config.rs +++ b/acmed/src/config.rs @@ -58,6 +58,9 @@ impl Config { stdin: hook.stdin.to_owned(), stdout: hook.stdout.to_owned(), stderr: hook.stderr.to_owned(), + allow_failure: hook + .allow_failure + .unwrap_or(crate::DEFAULT_HOOK_ALLOW_FAILURE), }; return Ok(vec![h]); } @@ -158,6 +161,7 @@ pub struct Hook { pub stdin: Option, pub stdout: Option, pub stderr: Option, + pub allow_failure: Option, } #[derive(Clone, Debug, Eq, PartialEq, Deserialize)] diff --git a/acmed/src/hooks.rs b/acmed/src/hooks.rs index 576a3b4..0d860c6 100644 --- a/acmed/src/hooks.rs +++ b/acmed/src/hooks.rs @@ -84,6 +84,7 @@ pub struct Hook { pub stdin: Option, pub stdout: Option, pub stderr: Option, + pub allow_failure: bool, } impl fmt::Display for Hook { @@ -142,8 +143,15 @@ where } // TODO: add a timeout let status = cmd.wait()?; + if !status.success() && !hook.allow_failure { + let msg = match status.code() { + Some(code) => format!("Hook {}: unrecoverable failure: code {}", hook.name, code), + None => format!("Hook {}: unrecoverable failure", hook.name), + }; + return Err(msg.into()); + } match status.code() { - Some(code) => debug!("Hook {}: exited with code {}", hook.name, code), + Some(code) => debug!("Hook {}: exited: code {}", hook.name, code), None => debug!("Hook {}: exited", hook.name), }; Ok(()) diff --git a/acmed/src/main.rs b/acmed/src/main.rs index fbe9498..1d2a190 100644 --- a/acmed/src/main.rs +++ b/acmed/src/main.rs @@ -29,6 +29,7 @@ pub const DEFAULT_POOL_NB_TRIES: usize = 20; pub const DEFAULT_POOL_WAIT_SEC: u64 = 5; pub const DEFAULT_HTTP_FAIL_NB_RETRY: usize = 10; pub const DEFAULT_HTTP_FAIL_WAIT_SEC: u64 = 1; +pub const DEFAULT_HOOK_ALLOW_FAILURE: bool = false; fn main() { let matches = App::new(APP_NAME) diff --git a/man/en/acmed.toml.5 b/man/en/acmed.toml.5 index ef9d36c..1503809 100644 --- a/man/en/acmed.toml.5 +++ b/man/en/acmed.toml.5 @@ -81,6 +81,8 @@ Array of table where each element defines a command that will be launched at a d .Sx WRITING A HOOK for more details. .Bl -tag +.It Cm allow_failure Ar boolean +Defines if an error return value for this hook is allowed or not. If not allowed, a failure in this hook will fail the whole certificate request process. Default is false. .It Cm name Ar string The name the hook is registered under. Must be unique. .It Cm hook_type Ar array