Browse Source

Merge 68e25ff0d6 into 324c968e20

pull/173/merge
famfo 3 months ago
committed by GitHub
parent
commit
5b723ba77c
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      acmed/src/certificate.rs
  2. 16
      acmed/src/config.rs
  3. 21
      acmed/src/hooks.rs
  4. 8
      acmed/src/storage.rs
  5. 4
      man/en/acmed.toml.5

13
acmed/src/certificate.rs

@ -164,7 +164,7 @@ impl Certificate {
HookType::ChallengeTlsAlpn01Clean, HookType::ChallengeTlsAlpn01Clean,
), ),
}; };
hooks::call(self, &self.hooks, &hook_data, hook_type.0).await?;
hooks::call(self, &self.hooks, &hook_data, None, hook_type.0).await?;
Ok((hook_data, hook_type.1)) Ok((hook_data, hook_type.1))
} }
@ -173,7 +173,7 @@ impl Certificate {
data: &ChallengeHookData, data: &ChallengeHookData,
hook_type: HookType, hook_type: HookType,
) -> Result<(), Error> { ) -> Result<(), Error> {
hooks::call(self, &self.hooks, data, hook_type).await
hooks::call(self, &self.hooks, data, None, hook_type).await
} }
pub async fn call_post_operation_hooks( pub async fn call_post_operation_hooks(
@ -196,7 +196,14 @@ impl Certificate {
env: HashMap::new(), env: HashMap::new(),
}; };
hook_data.set_env(&self.env); hook_data.set_env(&self.env);
hooks::call(self, &self.hooks, &hook_data, HookType::PostOperation).await?;
hooks::call(
self,
&self.hooks,
&hook_data,
Some(is_success),
HookType::PostOperation,
)
.await?;
Ok(()) Ok(())
} }
} }

16
acmed/src/config.rs

@ -95,6 +95,15 @@ impl Config {
pub fn get_hook(&self, name: &str) -> Result<Vec<hooks::Hook>, Error> { pub fn get_hook(&self, name: &str) -> Result<Vec<hooks::Hook>, Error> {
for hook in self.hook.iter() { for hook in self.hook.iter() {
if name == hook.name { if name == hook.name {
if !hook.hook_type.contains(&HookType::PostOperation)
&& hook.run_after_failure.is_some()
{
return Err(format!(
"{}: run_after_failure can only be used with post-operation hooks", hook.name
)
.into());
}
let h = hooks::Hook { let h = hooks::Hook {
name: hook.name.to_owned(), name: hook.name.to_owned(),
hook_type: hook.hook_type.iter().map(|e| e.to_owned()).collect(), hook_type: hook.hook_type.iter().map(|e| e.to_owned()).collect(),
@ -106,6 +115,7 @@ impl Config {
allow_failure: hook allow_failure: hook
.allow_failure .allow_failure
.unwrap_or(crate::DEFAULT_HOOK_ALLOW_FAILURE), .unwrap_or(crate::DEFAULT_HOOK_ALLOW_FAILURE),
run_after_failure: hook.run_after_failure.unwrap_or(true),
}; };
return Ok(vec![h]); return Ok(vec![h]);
} }
@ -326,6 +336,7 @@ pub struct Hook {
pub stdout: Option<String>, pub stdout: Option<String>,
#[serde(rename = "type")] #[serde(rename = "type")]
pub hook_type: Vec<HookType>, pub hook_type: Vec<HookType>,
pub run_after_failure: Option<bool>,
} }
#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize)] #[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize)]
@ -376,7 +387,10 @@ impl ExternalAccount {
| JwsSignatureAlgorithm::Hs384 | JwsSignatureAlgorithm::Hs384
| JwsSignatureAlgorithm::Hs512 => {} | JwsSignatureAlgorithm::Hs512 => {}
_ => { _ => {
return Err(format!("{signature_algorithm}: invalid signature algorithm for external account binding").into());
return Err(format!(
"{signature_algorithm}: invalid signature algorithm for external account binding"
)
.into());
} }
}; };
Ok(crate::account::ExternalAccount { Ok(crate::account::ExternalAccount {

21
acmed/src/hooks.rs

@ -97,6 +97,7 @@ pub struct Hook {
pub stdout: Option<String>, pub stdout: Option<String>,
pub stderr: Option<String>, pub stderr: Option<String>,
pub allow_failure: bool, pub allow_failure: bool,
pub run_after_failure: bool,
} }
impl fmt::Display for Hook { impl fmt::Display for Hook {
@ -119,11 +120,26 @@ macro_rules! get_hook_output {
}}; }};
} }
async fn call_single<L, T>(logger: &L, data: &T, hook: &Hook) -> Result<(), Error>
async fn call_single<L, T>(
logger: &L,
data: &T,
is_success: Option<bool>,
hook: &Hook,
) -> Result<(), Error>
where where
L: HasLogger, L: HasLogger,
T: Clone + HookEnvData + Serialize, T: Clone + HookEnvData + Serialize,
{ {
if let Some(success) = is_success {
if !success && !hook.run_after_failure {
logger.debug(&format!(
"skipping hook \"{}\" due to previous failure",
hook.name
));
return Ok(());
}
}
logger.debug(&format!("calling hook \"{}\"", hook.name)); logger.debug(&format!("calling hook \"{}\"", hook.name));
let mut v = vec![]; let mut v = vec![];
let args = match &hook.args { let args = match &hook.args {
@ -200,6 +216,7 @@ pub async fn call<L, T>(
logger: &L, logger: &L,
hooks: &[Hook], hooks: &[Hook],
data: &T, data: &T,
is_success: Option<bool>,
hook_type: HookType, hook_type: HookType,
) -> Result<(), Error> ) -> Result<(), Error>
where where
@ -207,7 +224,7 @@ where
T: Clone + HookEnvData + Serialize, T: Clone + HookEnvData + Serialize,
{ {
for hook in hooks.iter().filter(|h| h.hook_type.contains(&hook_type)) { for hook in hooks.iter().filter(|h| h.hook_type.contains(&hook_type)) {
call_single(logger, data, hook)
call_single(logger, data, is_success, hook)
.await .await
.map_err(|e| e.prefix(&hook.name))?; .map_err(|e| e.prefix(&hook.name))?;
} }

8
acmed/src/storage.rs

@ -203,9 +203,9 @@ async fn write_file(fm: &FileManager, file_type: FileType, data: &[u8]) -> Resul
let is_new = !path.is_file(); let is_new = !path.is_file();
if is_new { if is_new {
hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePreCreate).await?;
hooks::call(fm, &fm.hooks, &hook_data, None, HookType::FilePreCreate).await?;
} else { } else {
hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePreEdit).await?;
hooks::call(fm, &fm.hooks, &hook_data, None, HookType::FilePreEdit).await?;
} }
fm.trace(&format!("writing file {path:?}")); fm.trace(&format!("writing file {path:?}"));
@ -235,9 +235,9 @@ async fn write_file(fm: &FileManager, file_type: FileType, data: &[u8]) -> Resul
} }
if is_new { if is_new {
hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePostCreate).await?;
hooks::call(fm, &fm.hooks, &hook_data, None, HookType::FilePostCreate).await?;
} else { } else {
hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePostEdit).await?;
hooks::call(fm, &fm.hooks, &hook_data, None, HookType::FilePostEdit).await?;
} }
Ok(()) Ok(())
} }

4
man/en/acmed.toml.5

@ -355,6 +355,10 @@ String that will be written into the command's standard input. Mutually exclusiv
.Em stdin . .Em stdin .
.It Ic stdout Ar string .It Ic stdout Ar string
Path to the file where the command's standard output if written. Path to the file where the command's standard output if written.
.It Cm run_after_failure Ar boolean
Option only applicable to hooks of type
.Em post-operation .
Specifies whether to run the hook after issuing a certificate failed. Default is true.
.It Cm type Ar array .It Cm type Ar array
Array of strings. Possible types are: Array of strings. Possible types are:
.Bl -dash -compact .Bl -dash -compact

Loading…
Cancel
Save