diff --git a/acme_common/Cargo.toml b/acme_common/Cargo.toml index 78661b3..a18d111 100644 --- a/acme_common/Cargo.toml +++ b/acme_common/Cargo.toml @@ -24,7 +24,6 @@ base64 = "0.13" daemonize = "0.4" env_logger = "0.8" glob = "0.3" -handlebars = "3.0" libc = "0.2" log = "0.4" native-tls = "0.2" @@ -33,6 +32,7 @@ openssl-sys = { version = "0.9", optional = true } punycode = "0.4" serde_json = "1.0" syslog = "5.0" +tinytemplate = "1.2" toml = "0.5" [target.'cfg(unix)'.dependencies] diff --git a/acme_common/src/error.rs b/acme_common/src/error.rs index 4e3dbab..fe3f8f3 100644 --- a/acme_common/src/error.rs +++ b/acme_common/src/error.rs @@ -105,8 +105,8 @@ impl From for Error { } } -impl From for Error { - fn from(error: handlebars::TemplateRenderError) -> Self { +impl From for Error { + fn from(error: tinytemplate::error::Error) -> Self { format!("template error: {}", error).into() } } diff --git a/acmed/Cargo.toml b/acmed/Cargo.toml index 7cca534..6ca8314 100644 --- a/acmed/Cargo.toml +++ b/acmed/Cargo.toml @@ -25,11 +25,11 @@ attohttpc = { version = "0.17", default-features = false, features = ["charsets" bincode = "1.3" clap = "2.32" glob = "0.3" -handlebars = "3.0" log = "0.4" nom = { version = "6.0", default-features = false, features = [] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +tinytemplate = "1.2" toml = "0.5" [target.'cfg(unix)'.dependencies] diff --git a/acmed/build.rs b/acmed/build.rs index 72db5d4..a43cc1c 100644 --- a/acmed/build.rs +++ b/acmed/build.rs @@ -117,7 +117,7 @@ fn set_default_values() { set_data_path_if_absent!("ACMED_DEFAULT_CERT_DIR", "certs"); set_env_var_if_absent!( "ACMED_DEFAULT_CERT_FORMAT", - "{{name}}_{{key_type}}.{{file_type}}.{{ext}}" + "{ name }_{ key_type }.{ file_type }.{ ext }" ); set_cfg_path_if_absent!("ACMED_DEFAULT_CONFIG_FILE", "acmed.toml"); set_runstate_path_if_absent!("ACMED_DEFAULT_PID_FILE", "acmed.pid"); diff --git a/acmed/config/default_hooks.toml b/acmed/config/default_hooks.toml index 804e50d..37e4ffb 100644 --- a/acmed/config/default_hooks.toml +++ b/acmed/config/default_hooks.toml @@ -12,7 +12,7 @@ # -# http-01 challenge in "/var/www/{{identifier}}/" +# http-01 challenge in "/var/www/{ identifier }/" # [[hook]] @@ -21,7 +21,7 @@ type = ["challenge-http-01"] cmd = "mkdir" args = [ "-m", "0755", - "-p", "{{#if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge" + "-p", "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge" ] allow_failure = true @@ -29,8 +29,8 @@ allow_failure = true name = "http-01-echo-echo" type = ["challenge-http-01"] cmd = "echo" -args = ["{{proof}}"] -stdout = "{{#if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge/{{file_name}}" +args = ["{ proof }"] +stdout = "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge/{ file_name }" [[hook]] name = "http-01-echo-chmod" @@ -38,7 +38,7 @@ type = ["challenge-http-01"] cmd = "chmod" args = [ "a+r", - "{{#if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge/{{file_name}}" + "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge/{ file_name }" ] allow_failure = true @@ -48,7 +48,7 @@ type = ["challenge-http-01-clean"] cmd = "rm" args = [ "-f", - "{{#if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge/{{file_name}}" + "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge/{ file_name }" ] allow_failure = true @@ -71,10 +71,10 @@ name = "tls-alpn-01-tacd-start-tcp" type = ["challenge-tls-alpn-01"] cmd = "tacd" args = [ - "--pid-file", "{{#if env.TACD_PID_ROOT}}{{env.TACD_PID_ROOT}}{{else}}/run{{/if}}/tacd_{{identifier}}.pid", - "--domain", "{{identifier_tls_alpn}}", - "--acme-ext", "{{proof}}", - "--listen", "{{#if env.TACD_HOST}}{{env.TACD_HOST}}{{else}}{{identifier}}{{/if}}:{{#if env.TACD_PORT}}{{env.TACD_PORT}}{{else}}5001{{/if}}" + "--pid-file", "{{ if env.TACD_PID_ROOT }}{ env.TACD_PID_ROOT }{{ else }}/run{{ endif }}/tacd_{ identifier }.pid", + "--domain", "{ identifier_tls_alpn }", + "--acme-ext", "{ proof }", + "--listen", "{{ if env.TACD_HOST }}{ env.TACD_HOST }{{ else }}{ identifier }{{ endif }}:{{ if env.TACD_PORT }}{ env.TACD_PORT }{{ else }}5001{{ endif }}" ] [[hook]] @@ -82,10 +82,10 @@ name = "tls-alpn-01-tacd-start-unix" type = ["challenge-tls-alpn-01"] cmd = "tacd" args = [ - "--pid-file", "{{#if env.TACD_PID_ROOT}}{{env.TACD_PID_ROOT}}{{else}}/run{{/if}}/tacd_{{identifier}}.pid", - "--domain", "{{identifier_tls_alpn}}", - "--acme-ext", "{{proof}}", - "--listen", "unix:{{#if env.TACD_SOCK_ROOT}}{{env.TACD_SOCK_ROOT}}{{else}}/run{{/if}}/tacd_{{identifier}}.sock" + "--pid-file", "{{ if env.TACD_PID_ROOT }}{ env.TACD_PID_ROOT }{{ else }}/run{{ endif }}/tacd_{ identifier }.pid", + "--domain", "{ identifier_tls_alpn }", + "--acme-ext", "{ proof }", + "--listen", "unix:{{ if env.TACD_SOCK_ROOT }}{ env.TACD_SOCK_ROOT }{{ else }}/run{{ endif }}/tacd_{ identifier }.sock" ] [[hook]] @@ -93,7 +93,7 @@ name = "tls-alpn-01-tacd-kill" type = ["challenge-tls-alpn-01-clean"] cmd = "pkill" args = [ - "-F", "{{#if env.TACD_PID_ROOT}}{{env.TACD_PID_ROOT}}{{else}}/run{{/if}}/tacd_{{identifier}}.pid", + "-F", "{{ if env.TACD_PID_ROOT }}{ env.TACD_PID_ROOT }{{ else }}/run{{ endif }}/tacd_{ identifier }.pid", ] allow_failure = true @@ -102,7 +102,7 @@ name = "tls-alpn-01-tacd-rm" type = ["challenge-tls-alpn-01-clean"] cmd = "rm" args = [ - "-f", "{{#if env.TACD_PID_ROOT}}{{env.TACD_PID_ROOT}}{{else}}/run{{/if}}/tacd_{{identifier}}.pid", + "-f", "{{ if env.TACD_PID_ROOT }}{ env.TACD_PID_ROOT }{{ else }}/run{{ endif }}/tacd_{ identifier }.pid", ] allow_failure = true @@ -125,7 +125,7 @@ type = ["file-pre-create", "file-pre-edit"] cmd = "git" args = [ "init", - "{{file_directory}}" + "{ file_directory }" ] [[hook]] @@ -133,8 +133,8 @@ name = "git-add" type = ["file-post-create", "file-post-edit"] cmd = "git" args = [ - "-C", "{{file_directory}}", - "add", "{{file_name}}" + "-C", "{ file_directory }", + "add", "{ file_name }" ] allow_failure = true @@ -143,12 +143,12 @@ name = "git-commit" type = ["file-post-create", "file-post-edit"] cmd = "git" args = [ - "-C", "{{file_directory}}", - "-c", "user.name='{{#if env.GIT_USERNAME}}{{env.GIT_USERNAME}}{{else}}ACMEd{{/if}}'", - "-c", "user.email='{{#if env.GIT_EMAIL}}{{env.GIT_EMAIL}}{{else}}acmed@localhost{{/if}}'", + "-C", "{ file_directory }", + "-c", "user.name='{{ if env.GIT_USERNAME }}{ env.GIT_USERNAME }{{ else }}ACMEd{{ endif }}'", + "-c", "user.email='{{ if env.GIT_EMAIL }}{ env.GIT_EMAIL }{{ else }}acmed@localhost{{ endif }}'", "commit", - "-m", "{{file_name}}", - "--only", "{{file_name}}" + "-m", "{ file_name }", + "--only", "{ file_name }" ] allow_failure = true diff --git a/acmed/src/hooks.rs b/acmed/src/hooks.rs index eaca640..7f18935 100644 --- a/acmed/src/hooks.rs +++ b/acmed/src/hooks.rs @@ -1,7 +1,7 @@ pub use crate::config::HookType; use crate::logs::HasLogger; +use crate::template::render_template; use acme_common::error::Error; -use handlebars::Handlebars; use serde::Serialize; use std::collections::hash_map::Iter; use std::collections::{HashMap, HashSet}; @@ -102,10 +102,10 @@ impl fmt::Display for Hook { } macro_rules! get_hook_output { - ($logger: expr, $out: expr, $reg: ident, $data: expr, $hook_name: expr, $out_name: expr) => {{ + ($logger: expr, $out: expr, $data: expr, $hook_name: expr, $out_name: expr) => {{ match $out { Some(path) => { - let path = $reg.render_template(path, $data)?; + let path = render_template(path, $data)?; $logger.trace(&format!( "hook \"{}\": {}: {}", $hook_name, $out_name, &path @@ -124,12 +124,11 @@ where T: Clone + HookEnvData + Serialize, { logger.debug(&format!("calling hook \"{}\"", hook.name)); - let reg = Handlebars::new(); let mut v = vec![]; let args = match &hook.args { Some(lst) => { for fmt in lst.iter() { - let s = reg.render_template(fmt, &data)?; + let s = render_template(fmt, &data)?; v.push(s); } v.as_slice() @@ -144,7 +143,6 @@ where .stdout(get_hook_output!( logger, &hook.stdout, - reg, &data, &hook.name, "stdout" @@ -152,7 +150,6 @@ where .stderr(get_hook_output!( logger, &hook.stderr, - reg, &data, &hook.name, "stderr" @@ -164,7 +161,7 @@ where .spawn()?; match &hook.stdin { HookStdin::Str(s) => { - let data_in = reg.render_template(&s, &data)?; + let data_in = render_template(&s, &data)?; logger.trace(&format!( "hook \"{}\": string stdin: {}", hook.name, &data_in @@ -173,7 +170,7 @@ where stdin.write_all(data_in.as_bytes())?; } HookStdin::File(f) => { - let file_name = reg.render_template(&f, &data)?; + let file_name = render_template(&f, &data)?; logger.trace(&format!( "hook \"{}\": file stdin: {}", hook.name, &file_name diff --git a/acmed/src/main.rs b/acmed/src/main.rs index a06bea3..eebe8fc 100644 --- a/acmed/src/main.rs +++ b/acmed/src/main.rs @@ -20,6 +20,7 @@ mod jws; mod logs; mod main_event_loop; mod storage; +mod template; pub const APP_NAME: &str = "ACMEd"; pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/acmed/src/storage.rs b/acmed/src/storage.rs index 9a7e5ba..bc7930f 100644 --- a/acmed/src/storage.rs +++ b/acmed/src/storage.rs @@ -1,9 +1,9 @@ use crate::hooks::{self, FileStorageHookData, Hook, HookEnvData, HookType}; use crate::logs::HasLogger; +use crate::template::render_template; use acme_common::b64_encode; use acme_common::crypto::{KeyPair, X509Certificate}; use acme_common::error::Error; -use handlebars::Handlebars; use serde::Serialize; use std::collections::HashMap; use std::fmt; @@ -110,8 +110,7 @@ fn get_file_full_path( 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)? + render_template(&fm.crt_name_format, &fmt_data)? } }; let mut path = PathBuf::from(&base_path); diff --git a/acmed/src/template.rs b/acmed/src/template.rs new file mode 100644 index 0000000..412b63f --- /dev/null +++ b/acmed/src/template.rs @@ -0,0 +1,12 @@ +use acme_common::error::Error; +use serde::Serialize; +use tinytemplate::TinyTemplate; + +pub fn render_template(template: &str, data: &T) -> Result +where + T: Serialize, +{ + let mut reg = TinyTemplate::new(); + reg.add_template("reg", template)?; + Ok(reg.render("reg", data)?) +} diff --git a/man/en/acmed.toml.5 b/man/en/acmed.toml.5 index abb7460..72ef57a 100644 --- a/man/en/acmed.toml.5 +++ b/man/en/acmed.toml.5 @@ -118,17 +118,17 @@ Name of the endpoint to use. 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 . +.Em TinyTemplate . See the .Sx STANDARDS section for a link to the -.Em Handlebars +.Em TinyTemplate 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}} . +.Dq { name }_{ key_type }.{ file_type }.{ ext } . Possible variables are: .Bl -tag .It Ic ext Ar string @@ -401,11 +401,11 @@ and are considered as template strings whereas .Em cmd is not. The template syntax is -.Em Handlebars . +.Em TinyTemplate . See the .Sx STANDARDS section for a link to the -.Em Handlebars +.Em TinyTemplate specifications. .Pp The available types and the associated template variable are described below. @@ -577,10 +577,10 @@ and environment variables. .It Pa http-01-echo This hook is designed to solve the http-01 challenge. For this purpose, it will write the proof into -.Pa {{env.HTTP_ROOT}}/{{identifier}}/.well-known/acme-challenge/{{file_name}} . +.Pa { env.HTTP_ROOT }/{ identifier }/.well-known/acme-challenge/{ file_name } . .Pp The web server must be configured so the file -.Pa http://{{identifier}}/.well-known/acme-challenge/{{file_name}} +.Pa http://{ identifier }/.well-known/acme-challenge/{ file_name } can be accessed from the CA. .Pp If @@ -605,7 +605,7 @@ environment variable (default is 5001). .Pp .Xr tacd 8 will store its pid into -.Pa {{TACD_PID_ROOT}}/tacd_{{identifier}}.pid . +.Pa { TACD_PID_ROOT }/tacd_{ identifier }.pid . If .Ev TACD_PID_ROOT is not specified, it will be set to @@ -621,7 +621,7 @@ option. .Pp .Xr tacd 8 will listen on the unix socket -.Pa {{env.TACD_SOCK_ROOT}}/tacd_{{identifier}}.sock . +.Pa { env.TACD_SOCK_ROOT }/tacd_{ identifier }.sock . If .Ev TACD_SOCK_ROOT is not specified, it will be set to @@ -629,7 +629,7 @@ is not specified, it will be set to .Pp .Xr tacd 8 will store its pid into -.Pa {{TACD_PID_ROOT}}/tacd_{{identifier}}.pid . +.Pa { TACD_PID_ROOT }/tacd_{ identifier }.pid . If .Ev TACD_PID_ROOT is not specified, it will be set to @@ -726,15 +726,15 @@ type = ["challenge-http-01"] cmd = "mkdir" args = [ "-m", "0755", - "-p", "{{%if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge" + "-p", "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge" ] [[hook]] name = "http-01-echo-echo" type = ["challenge-http-01"] cmd = "echo" -args = ["{{proof}}"] -stdout = "{{%if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge/{{file_name}}" +args = ["{ proof }"] +stdout = "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge/{ file_name }" [[hook]] name = "http-01-echo-chmod" @@ -742,7 +742,7 @@ type = ["challenge-http-01-clean"] cmd = "chmod" args = [ "a+r", - "{{%if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge/{{file_name}}" + "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge/{ file_name }" ] [[hook]] @@ -751,7 +751,7 @@ type = ["challenge-http-01-clean"] cmd = "rm" args = [ "-f", - "{{%if env.HTTP_ROOT}}{{env.HTTP_ROOT}}{{else}}/var/www{{/if}}/{{identifier}}/.well-known/acme-challenge/{{file_name}}" + "{{ if env.HTTP_ROOT }}{ env.HTTP_ROOT }{{ else }}/var/www{{ endif }}/{ identifier }/.well-known/acme-challenge/{ file_name }" ] .Ed .Pp @@ -784,12 +784,12 @@ args = [ "-f", "noreply.certs@example.net", "contact@example.net" ] -stdin_str = """Subject: Certificate renewal {{#if is_success}}succeeded{{else}}failed{{/if}} for {{identifiers.[0]}} +stdin_str = """Subject: Certificate renewal {{ if is_success }}succeeded{{ else }}failed{{ endif }} for { identifiers.0 } -The following certificate has {{#unless is_success}}*not* {{/unless}}been renewed. -identifiers: {{#each identifiers}}{{#if @index}}, {{/if}}{{this}}{{/each}} -key type: {{key_type}} -status: {{status}}""" +The following certificate has {{ if not is_success }}*not* {{ endif }}been renewed. +identifiers: {{ for ident in identifiers}}{{ if @index }}, {{ endif }}{ ident }{{ endfor}} +key type: { key_type } +status: { status }""" .Ed .Sh SEE ALSO .Xr acmed 8 , @@ -805,9 +805,9 @@ status: {{status}}""" .Re .It .Rs -.%A Yehuda Katz -.%T Handlebars -.%U https://handlebarsjs.com/ +.%A Brook Heisler +.%T TinyTemplate +.%U https://docs.rs/tinytemplate/latest/tinytemplate/syntax/index.html .Re .It .Rs