From 76dc961f86cc884b815aa28a436add1c128085fa Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 8 Oct 2024 16:25:56 +0200 Subject: [LighttpdHttps] Add support for ACME --- scripts/install-https | 142 +++++++++++++++++++++++++++++++++++++++++++++----- scripts/system-backup | 2 + 2 files changed, 130 insertions(+), 14 deletions(-) (limited to 'scripts') diff --git a/scripts/install-https b/scripts/install-https index 0afeb58..e6daeea 100755 --- a/scripts/install-https +++ b/scripts/install-https @@ -4,6 +4,27 @@ declare -rg CERT_KEY_FILE="/etc/lighttpd/server.pem" declare -rg PUB_CERT_FILE="/etc/lighttpd/pub-cert.pem" declare -rg CHAIN_FILE="/etc/lighttpd/chain.pem" declare -rg REDIR_FLAG="/etc/lighttpd/redirect.flag" +declare -rg RELOAD_FLAG="/home/taskmanager/acme-reload" +declare -rg ACME_KEY="/home/taskmanager/certs/key.pem" +declare -rg ACME_FULLCHAIN="/home/taskmanager/certs/fullchain.pem" +declare -rg WWW="/srv/openslx/www" + +declare -rga acme_common=( + -w "$WWW" + --key-file "$ACME_KEY" + --fullchain-file "$ACME_FULLCHAIN" + --reloadcmd "touch '$RELOAD_FLAG'" +) + +declare -a tmpfiles= +trap 'rm -rf -- "${tmpfiles[@]}"' EXIT + +is_readable () +{ + [ -r "$1" ] && [ -f "$1" ] && return 0 + echo "Not a file, or not readable: $1" + return 1 +} op_disable () { @@ -17,19 +38,17 @@ op_test () [ $# -eq 2 ] || exit 1 local K=$1 local C=$2 - [ -r "$K" ] || exit 2 - [ -r "$C" ] || exit 3 + is_readable "$K" || exit 2 + is_readable "$C" || exit 3 # Encrypt something, then decrypt again and compare local TEST_IN=$(mktemp --tmpdir bwlp-XXXXXXXX) local TEST_OUT=$(mktemp --tmpdir bwlp-XXXXXXXX) - local TEST_DIFF=$(mktemp --tmpdir bwlp-XXXXXXXX) [ -z "$TEST_IN" ] && exit 4 [ -z "$TEST_OUT" ] && exit 5 - [ -z "$TEST_DIFF" ] && exit 6 + tmpfiles+=( "$TEST_IN" "$TEST_OUT" ) date > "$TEST_IN" - openssl smime -encrypt -binary -aes-256-cbc -in "$TEST_IN" -out "$TEST_OUT" -outform DER "$C" || exit 7 - openssl smime -decrypt -binary -in "$TEST_OUT" -inform DER -out "$TEST_DIFF" -inkey "$K" || exit 8 - diff -q "$TEST_IN" "$TEST_DIFF" || exit 9 + openssl smime -sign -in "$TEST_IN" -out "$TEST_OUT" -signer "$C" -inkey "$K" || exit 7 + openssl smime -verify -noverify -in "$TEST_OUT" -out /dev/null -signer "$C" || exit 8 exit 0 # No restart either way } @@ -39,8 +58,8 @@ op_import () local K=$1 local C=$2 local CHAIN=$3 - [ -r "$K" ] || exit 2 - [ -r "$C" ] || exit 3 + is_readable "$K" || exit 2 + is_readable "$C" || exit 3 rm -f -- "$CHAIN_FILE" # Create server.pem { @@ -55,11 +74,85 @@ op_import () cat "$K" } > "$CERT_KEY_FILE" chmod 0600 "$CERT_KEY_FILE" || exit 4 - rm -f -- "$C" "$K" post_setup_hook return 0 } +op_acme_issue () +{ + [ $# -lt 3 ] && exit 1 + local i + local provider="$1" + local mail="$2" + shift 2 + declare -a domains=() + set -x + for i; do + domains+=( -d "$i" ) + done + rm -f -- "$RELOAD_FLAG" + if [ -n "$ACME_WIPE" ]; then + rm -rf -- /home/taskmanager/.acme.sh/* + rm -rf -- /home/taskmanager/certs/* + touch /home/taskmanager/.acme.sh/account.conf + chown taskmanager:taskmanager /home/taskmanager/.acme.sh/account.conf + else + rm -rf -- /home/taskmanager/.acme.sh/???*.* + rm -rf -- /home/taskmanager/certs/* + fi + mkdir -p "$WWW/.well-known/acme-challenge" + chown taskmanager:taskmanager "$WWW/.well-known/acme-challenge" + chmod 0700 /home/taskmanager/certs + if [ -n "$ACME_KEY_ID" ] && [ -n "$ACME_HMAC_KEY" ]; then + sudo -u taskmanager -n ACCOUNT_EMAIL="$mail" \ + /opt/openslx/acme.sh --register-account --server "$provider" --eab-kid "$ACME_KEY_ID" --eab-hmac-key "$ACME_HMAC_KEY" + fi + tmpfiles+=( "$RELOAD_FLAG" ) + sudo -u taskmanager -n ACCOUNT_EMAIL="$mail" \ + /opt/openslx/acme.sh --server "$provider" --issue "${domains[@]}" "${acme_common[@]}" + i=$? + if [ -e "$RELOAD_FLAG" ]; then + # Renew must have happened + op_import "$ACME_KEY" "$ACME_FULLCHAIN" + return 0 + fi + # No reload in other case, exit + exit "$i" +} + +op_acme_renew () +{ + mkdir -p "$WWW/.well-known/acme-challenge" + chown taskmanager:taskmanager "$WWW/.well-known/acme-challenge" + rm -f -- "$RELOAD_FLAG" + tmpfiles+=( "$RELOAD_FLAG" ) + sudo -u taskmanager -n /opt/openslx/acme.sh --renew --domain "$1" "${acme_common[@]}" + i=$? + (( i == 2 )) && i=0 + if (( i != 0 )) || ! [ -e "$ACME_FULLCHAIN" ] || ! [ -e "$ACME_KEY" ] \ + || ! openssl x509 -checkend 600 -in "$ACME_FULLCHAIN"; then + sudo -u taskmanager -n /opt/openslx/acme.sh --renew --force --domain "$1" "${acme_common[@]}" + i=$? + fi + if [ -e "$RELOAD_FLAG" ]; then + # Renew must have happened + op_import "$ACME_KEY" "$ACME_FULLCHAIN" + return 0 + fi + # No reload in other case, exit + + exit "$i" +} + +op_acme_try_enable () +{ + [ -s "$ACME_KEY" ] || exit 1 + [ -s "$ACME_FULLCHAIN" ] || exit 2 + openssl x509 -checkend 600 -noout -in "$ACME_FULLCHAIN" || exit 3 + ( op_test "$ACME_KEY" "$ACME_FULLCHAIN" ) || exit 4 + op_import "$ACME_KEY" "$ACME_FULLCHAIN" +} + op_random () { [ -z "$1" ] && exit 1 @@ -85,6 +178,9 @@ setup_redirect () fi } +ACME_KEY_ID= +ACME_HMAC_KEY= +ACME_WIPE= RE_ONLY= REDIR= while true; do @@ -95,6 +191,17 @@ while true; do --redirect) REDIR=truh ;; + --acme-wipe) + ACME_WIPE=1 + ;; + --acme-key-id) + ACME_KEY_ID="$2" + shift + ;; + --acme-hmac-key) + ACME_HMAC_KEY="$2" + shift + ;; *) break ;; @@ -112,8 +219,14 @@ if [ -z "$RE_ONLY" ]; then case "$OP" in --random) op_random "$@" ;; --test) op_test "$@" ;; - --import) op_import "$@" ;; + --import) + tmpfiles+=( "$@" ) + op_import "$@" + ;; --disable) op_disable ;; + --acme-issue) op_acme_issue "$@" ;; + --acme-renew) op_acme_renew "$@" ;; + --acme-try-enable) op_acme_try_enable ;; *) echo "Invalid operation: $1" exit 1 @@ -122,8 +235,9 @@ if [ -z "$RE_ONLY" ]; then fi -sleep .5 -systemctl restart lighttpd +( + sleep .5 + systemctl restart lighttpd +) & exit 0 - diff --git a/scripts/system-backup b/scripts/system-backup index 52422bb..5cc7d7e 100755 --- a/scripts/system-backup +++ b/scripts/system-backup @@ -51,6 +51,8 @@ FILELIST=( "/etc/lighttpd/server.pem" "/etc/lighttpd/chain.pem" "/etc/lighttpd/pub-cert.pem" + "/home/taskmanager/.acme.sh" + "/home/taskmanager/certs" ) tar --ignore-failed-read -k -c -p -z -f "files.tgz" "${FILELIST[@]}" -- cgit v1.2.3-55-g7522