From 465f56adc210be28ae0c6e34c54d1c55c09db6fc Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Sat, 22 Oct 2022 21:38:44 +0800 Subject: [PATCH 1/7] acme: not creating state_dir in Makefile Since state_dir can be customized, it should be create dynamically, which it already does. Signed-off-by: Glen Huang --- net/acme-common/Makefile | 1 - net/acme-common/files/acme.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/net/acme-common/Makefile b/net/acme-common/Makefile index 4e69702be70a41..b4ff360a8dad8c 100644 --- a/net/acme-common/Makefile +++ b/net/acme-common/Makefile @@ -34,7 +34,6 @@ define Package/acme-common/conffiles endef define Package/acme-common/install - $(INSTALL_DIR) $(1)/etc/acme $(INSTALL_DIR) $(1)/etc/config $(INSTALL_CONF) ./files/acme.config $(1)/etc/config/acme $(INSTALL_DIR) $(1)/usr/bin diff --git a/net/acme-common/files/acme.sh b/net/acme-common/files/acme.sh index 5663dddee4cb52..8972c4f0ef0fed 100644 --- a/net/acme-common/files/acme.sh +++ b/net/acme-common/files/acme.sh @@ -8,7 +8,7 @@ # # Authors: Toke Høiland-Jørgensen -export state_dir='/etc/acme' +export state_dir=/etc/acme export account_email= export debug=0 export challenge_dir='/var/run/acme/challenge' From cbc06f45b9c02263f901ef7c4214d0e489cec822 Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Sat, 22 Oct 2022 21:42:10 +0800 Subject: [PATCH 2/7] acme: make package create dir /etc/ssl/acme Since the dir is a standardized one, it should not be created dynamically Signed-off-by: Glen Huang --- net/acme-common/Makefile | 1 + net/acme-common/files/acme.sh | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/net/acme-common/Makefile b/net/acme-common/Makefile index b4ff360a8dad8c..997c31e31336d0 100644 --- a/net/acme-common/Makefile +++ b/net/acme-common/Makefile @@ -34,6 +34,7 @@ define Package/acme-common/conffiles endef define Package/acme-common/install + $(INSTALL_DIR) $(1)/etc/ssl/acme $(INSTALL_DIR) $(1)/etc/config $(INSTALL_CONF) ./files/acme.config $(1)/etc/config/acme $(INSTALL_DIR) $(1)/usr/bin diff --git a/net/acme-common/files/acme.sh b/net/acme-common/files/acme.sh index 8972c4f0ef0fed..1ed32af7e1a322 100644 --- a/net/acme-common/files/acme.sh +++ b/net/acme-common/files/acme.sh @@ -131,7 +131,6 @@ get) config_load acme config_foreach load_globals acme - mkdir -p /etc/ssl/acme trap cleanup EXIT config_foreach get_cert cert ;; From 035cc09e7f2b3619adce079ee266ad354f32e53b Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Sat, 22 Oct 2022 21:46:51 +0800 Subject: [PATCH 3/7] acme: prevent concurrent running of acme get Issuing certificates concurrently should not be supported. Signed-off-by: Glen Huang --- net/acme-common/files/acme.sh | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/net/acme-common/files/acme.sh b/net/acme-common/files/acme.sh index 1ed32af7e1a322..141a2a2cf6e041 100644 --- a/net/acme-common/files/acme.sh +++ b/net/acme-common/files/acme.sh @@ -11,7 +11,7 @@ export state_dir=/etc/acme export account_email= export debug=0 -export challenge_dir='/var/run/acme/challenge' +export run_dir=/var/run/acme NFT_HANDLE= HOOK=/usr/lib/acme/hook LOG_TAG=acme @@ -23,6 +23,9 @@ LOG_TAG=acme cleanup() { log debug "cleaning up" + if [ -e $run_dir/lock ]; then + rm $run_dir/lock + fi if [ "$NFT_HANDLE" ]; then # $NFT_HANDLE contains the string 'handle XX' so pass it unquoted to nft nft delete rule inet fw4 input $NFT_HANDLE @@ -60,7 +63,7 @@ load_options() { config_get webroot "$section" webroot export webroot if [ "$webroot" ]; then - log warn "Option \"webroot\" is deprecated, please remove it and change your web server's config so it serves ACME challenge requests from /var/run/acme/challenge." + log warn "Option \"webroot\" is deprecated, please remove it and change your web server's config so it serves ACME challenge requests from $run_dir/challenge." fi } @@ -112,6 +115,15 @@ load_globals() { return 1 } +cmd_get() { + trap cleanup EXIT + + config_load acme + config_foreach load_globals acme + + config_foreach get_cert cert +} + usage() { cat < [arguments] @@ -128,11 +140,14 @@ fi case $1 in get) - config_load acme - config_foreach load_globals acme - - trap cleanup EXIT - config_foreach get_cert cert + mkdir -p $run_dir + { + if ! flock -n 200; then + log err "Another ACME instance is already running." + exit 1 + fi + cmd_get "$@" + } 200>$run_dir/lock ;; *) usage From 7f04710579ef9466bc429403624fed71f112d6c9 Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Sat, 22 Oct 2022 22:17:08 +0800 Subject: [PATCH 4/7] amce: use procd to restart services Directly calling `/etc/init.d/ reload` in a hotplug script can inadvertently start a stopped service. Signed-off-by: Glen Huang --- net/acme-acmesh/files/hook.sh | 37 +++++++++++++++------------- net/acme-common/Makefile | 2 ++ net/acme-common/files/acme-notify.sh | 17 +++++++++++++ net/haproxy/files/acme.hotplug | 4 --- net/haproxy/files/haproxy.init | 4 +++ net/nginx/Makefile | 3 --- net/nginx/files/acme.hotplug | 3 --- net/nginx/files/nginx.init | 5 ++++ 8 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 net/acme-common/files/acme-notify.sh delete mode 100644 net/nginx/files/acme.hotplug diff --git a/net/acme-acmesh/files/hook.sh b/net/acme-acmesh/files/hook.sh index cd92cec9d63308..bbe23b4a1fcc5a 100644 --- a/net/acme-acmesh/files/hook.sh +++ b/net/acme-acmesh/files/hook.sh @@ -4,6 +4,7 @@ ACME=/usr/lib/acme/client/acme.sh LOG_TAG=acme-acmesh # webroot option deprecated, use the hardcoded value directly in the next major version WEBROOT=${webroot:-/var/run/acme/challenge} +NOTIFY=/usr/lib/acme/notify # shellcheck source=net/acme/files/functions.sh . /usr/lib/acme/functions.sh @@ -12,9 +13,7 @@ WEBROOT=${webroot:-/var/run/acme/challenge} export CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt export NO_TIMESTAMP=1 -cmd="$1" - -case $cmd in +case $1 in get) set -- [ "$debug" = 1 ] && set -- "$@" --debug @@ -38,20 +37,25 @@ get) staging_moved=1 else set -- "$@" --renew --home "$state_dir" -d "$main_domain" - log info "$*" - trap 'ACTION=renewed-failed hotplug-call acme;exit 1' INT - "$ACME" "$@" + log info "$ACME $*" + trap '$NOTIFY renew-failed;exit 1' INT + $ACME "$@" status=$? trap - INT case $status in - 0) ;; # renewed ok, handled by acme.sh hook, ignore. - 2) ;; # renew skipped, ignore. + 0) + $NOTIFY renewed + exit;; + 2) + # renew skipped, ignore. + exit + ;; *) - ACTION=renew-failed hotplug-call acme + $NOTIFY renew-failed + exit 1 ;; esac - return 0 fi fi @@ -92,11 +96,11 @@ get) set -- "$@" --issue --home "$state_dir" - log info "$*" - trap 'ACTION=issue-failed hotplug-call acme;exit 1' INT + log info "$ACME $*" + trap '$NOTIFY issue-failed;exit 1' INT "$ACME" "$@" \ - --pre-hook 'ACTION=prepare hotplug-call acme' \ - --renew-hook 'ACTION=renewed hotplug-call acme' + --pre-hook "$NOTIFY prepare" \ + --renew-hook "$NOTIFY renewed" status=$? trap - INT @@ -106,7 +110,7 @@ get) ln -s "$domain_dir/$main_domain.key" /etc/ssl/acme ln -s "$domain_dir/fullchain.cer" "/etc/ssl/acme/$main_domain.fullchain.cer" ln -s "$domain_dir/ca.cer" "/etc/ssl/acme/$main_domain.chain.cer" - ACTION=issued hotplug-call acme + $NOTIFY issued ;; *) if [ "$staging_moved" = 1 ]; then @@ -117,8 +121,7 @@ get) mv "$domain_dir" "$failed_dir" log err "State moved to $failed_dir" fi - ACTION=issue-failed hotplug-call acme - return 0 + $NOTIFY issue-failed ;; esac ;; diff --git a/net/acme-common/Makefile b/net/acme-common/Makefile index 997c31e31336d0..a279641c222344 100644 --- a/net/acme-common/Makefile +++ b/net/acme-common/Makefile @@ -41,10 +41,12 @@ define Package/acme-common/install $(INSTALL_BIN) ./files/acme.sh $(1)/usr/bin/acme $(INSTALL_DIR) $(1)/usr/lib/acme $(INSTALL_DATA) ./files/functions.sh $(1)/usr/lib/acme + $(INSTALL_BIN) ./files/acme-notify.sh $(1)/usr/lib/acme/notify $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/acme.init $(1)/etc/init.d/acme $(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_DATA) ./files/acme.uci-defaults $(1)/etc/uci-defaults/acme + $(INSTALL_DIR) $(1)/etc/hotplug.d/acme endef define Package/acme/postinst diff --git a/net/acme-common/files/acme-notify.sh b/net/acme-common/files/acme-notify.sh new file mode 100644 index 00000000000000..4f06f9412e1a8d --- /dev/null +++ b/net/acme-common/files/acme-notify.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -u + +event="$1" + +# Call hotplug first, giving scripts a chance to modify certificates before +# reloadaing the services +ACTION=$event hotplug-call acme + +case $event in +renewed) + ubus call service event '{"type":"acme.renew","data":{}}' + ;; +issued) + ubus call service event '{"type":"acme.issue","data":{}}' + ;; +esac diff --git a/net/haproxy/files/acme.hotplug b/net/haproxy/files/acme.hotplug index 5a4dc5cdd37eda..726d2b216b434d 100644 --- a/net/haproxy/files/acme.hotplug +++ b/net/haproxy/files/acme.hotplug @@ -6,7 +6,3 @@ issued|renewed) >"/etc/ssl/acme/$main_domain.combined.cer" ;; esac - -if [ "$ACTION" = renewed ]; then - /etc/init.d/haproxy reload -fi diff --git a/net/haproxy/files/haproxy.init b/net/haproxy/files/haproxy.init index 01d80d781b3149..51c0ebb659c994 100644 --- a/net/haproxy/files/haproxy.init +++ b/net/haproxy/files/haproxy.init @@ -18,6 +18,10 @@ start_service() { procd_close_instance } +service_triggers() { + procd_add_raw_trigger acme.renew 5000 /etc/init.d/haproxy reload +} + extra_command "check" "Check haproxy config" check() { $HAPROXY_BIN -c -q -V -f $HAPROXY_CONFIG diff --git a/net/nginx/Makefile b/net/nginx/Makefile index 41436aa39676a5..0cb8c65b0e2618 100644 --- a/net/nginx/Makefile +++ b/net/nginx/Makefile @@ -376,9 +376,6 @@ ifeq ($(CONFIG_NGINX_NAXSI),y) endif $(if $(CONFIG_NGINX_NAXSI),$($(INSTALL_BIN) $(PKG_BUILD_DIR)/nginx-naxsi/naxsi_config/naxsi_core.rules $(1)/etc/nginx)) $(if $(CONFIG_NGINX_NAXSI),$(chmod 0640 $(1)/etc/nginx/naxsi_core.rules)) - - $(INSTALL_DIR) $(1)/etc/hotplug.d/acme - $(INSTALL_DATA) ./files/acme.hotplug $(1)/etc/hotplug.d/acme/00-nginx endef Package/nginx-all-module/install = $(Package/nginx-ssl/install) diff --git a/net/nginx/files/acme.hotplug b/net/nginx/files/acme.hotplug deleted file mode 100644 index 74f1448d764605..00000000000000 --- a/net/nginx/files/acme.hotplug +++ /dev/null @@ -1,3 +0,0 @@ -if [ "$ACTION" = renewed ]; then - /etc/init.d/nginx reload -fi diff --git a/net/nginx/files/nginx.init b/net/nginx/files/nginx.init index 300a8c657f15a2..632a3f10a7ec6e 100644 --- a/net/nginx/files/nginx.init +++ b/net/nginx/files/nginx.init @@ -66,6 +66,11 @@ reload_service() { } +service_triggers() { + procd_add_raw_trigger acme.renew 5000 /etc/init.d/nginx reload +} + + extra_command "relog" "Reopen log files (without reloading)" relog() { [ -d /var/log/nginx ] || mkdir -p /var/log/nginx From 9d2d8787cafdfb49339766a00ced422fa75cb883 Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Mon, 24 Oct 2022 10:21:45 +0800 Subject: [PATCH 5/7] acme: fix staging option Legacy use_staging option was not respected, and the example config still use the legacy name. Signed-off-by: Glen Huang --- net/acme-common/files/acme.config | 4 ++-- net/acme-common/files/acme.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/acme-common/files/acme.config b/net/acme-common/files/acme.config index 12bffd60f7a885..d72547a6ed17c4 100644 --- a/net/acme-common/files/acme.config +++ b/net/acme-common/files/acme.config @@ -5,7 +5,7 @@ config acme config cert 'example_wildcard' option enabled 0 - option use_staging 1 + option staging 1 list domains example.org list domains sub.example.org list domains *.sub.example.org @@ -17,6 +17,6 @@ config cert 'example_wildcard' config cert 'example' option enabled 0 - option use_staging 1 + option staging 1 list domains example.org list domains sub.example.org diff --git a/net/acme-common/files/acme.sh b/net/acme-common/files/acme.sh index 141a2a2cf6e041..24601a5025fbe2 100644 --- a/net/acme-common/files/acme.sh +++ b/net/acme-common/files/acme.sh @@ -36,7 +36,7 @@ load_options() { section=$1 # compatibility for old option name - config_get_bool use_staging "$section" staging + config_get_bool staging "$section" use_staging if [ -z "$staging" ]; then config_get_bool staging "$section" staging 0 fi From 4e369cf78065b04b81fe6579a8137bd38041b075 Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Mon, 24 Oct 2022 10:35:47 +0800 Subject: [PATCH 6/7] acme: add dns_wait option acme.sh by default use public DNS resolvers to check if TXT record was correctly added when using DNS-01. This can be undesirable in a private environment where the DNS server is not publicly accessible. This option allows bypassing such check and simply waiting for a specific length of time for the TXT record to take effect. Signed-off-by: Glen Huang --- net/acme-acmesh/files/hook.sh | 3 +++ net/acme-common/files/acme.sh | 2 ++ 2 files changed, 5 insertions(+) diff --git a/net/acme-acmesh/files/hook.sh b/net/acme-acmesh/files/hook.sh index bbe23b4a1fcc5a..e736dc5996414e 100644 --- a/net/acme-acmesh/files/hook.sh +++ b/net/acme-acmesh/files/hook.sh @@ -87,6 +87,9 @@ get) elif [ "$calias" ]; then set -- "$@" --challenge-alias "$calias" fi + if [ "$dns_wait" ]; then + set -- "$@" --dnssleep "$dns_wait" + fi elif [ "$standalone" = 1 ]; then set -- "$@" --standalone --listen-v6 else diff --git a/net/acme-common/files/acme.sh b/net/acme-common/files/acme.sh index 24601a5025fbe2..bcf3d84518061a 100644 --- a/net/acme-common/files/acme.sh +++ b/net/acme-common/files/acme.sh @@ -59,6 +59,8 @@ load_options() { export days config_get standalone "$section" standalone 0 export standalone + config_get dns_wait "$section" dns_wait + export dns_wait config_get webroot "$section" webroot export webroot From 230c2d5fc423c28eb9fa8e3fa5a2bd3e626de87e Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Sat, 22 Oct 2022 22:25:55 +0800 Subject: [PATCH 7/7] acme: update changed packages' versions Signed-off-by: Glen Huang --- net/acme-common/Makefile | 2 +- net/nginx/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/acme-common/Makefile b/net/acme-common/Makefile index a279641c222344..268df5c68023fc 100644 --- a/net/acme-common/Makefile +++ b/net/acme-common/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=acme-common -PKG_VERSION:=1.0.0 +PKG_VERSION:=1.0.1 PKG_MAINTAINER:=Toke Høiland-Jørgensen PKG_LICENSE:=GPL-3.0-only diff --git a/net/nginx/Makefile b/net/nginx/Makefile index 0cb8c65b0e2618..438ee852577110 100644 --- a/net/nginx/Makefile +++ b/net/nginx/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nginx PKG_VERSION:=1.21.3 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=nginx-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://nginx.org/download/