home-server/roles/acme_back/templates/hook.sh.j2

113 lines
4.4 KiB
Django/Jinja
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
# The home-server project produces a multi-purpose setup using Ansible.
# Copyright © 20182023 Y. Gablin, under the GPL-3.0-or-later license.
# Full licensing information in the LICENSE file, or gnu.org/licences/gpl-3.0.txt if the file is missing.
#
# NOTE: on 1st run, DMZ software is NOT YET INSTALLED!
set -e
RSH=/usr/local/bin/{{DMZ}}
ETC_CHANGED_{{hostname | regex_replace('-', '_')}}=
ETC_CHANGED_{{DMZ | regex_replace('-', '_')}}=
etckeeper_hook() {
if [ -n "$ETC_CHANGED_{{hostname}}" ]; then
etc_stop_local 'ACME update'
fi
if [ -n "$ETC_CHANGED_{{DMZ}}" ]; then
$RSH "etc_stop_local 'ACME update' || true"
fi
}
trap etckeeper_hook EXIT
deploy_challenge() {
local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
printf '%s' "$TOKEN_VALUE" >"$WELLKNOWN/$TOKEN_FILENAME"
}
clean_challenge() {
local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
rm -f "$WELLKNOWN/$TOKEN_FILENAME"
}
# $1: force|test; $2: KEYFILE; $3: CERTFILE; $4: FULLCHAINFILE; $5: CHAINFILE; $6: TIMESTAMP
deploy_exim() {
if [ "$1" == test ] \
&& $RSH 'test -f /etc/mail/exim.pem && test -f /etc/mail/exim.crt' \
&& $RSH 'find /etc/mail/exim.{pem,crt} -mmin -$((1+($(date +%s)-${1})/60)) -printf . | grep -q ..' ${6%.*}; then
return 0
fi
local copy='[ -d /etc/mail ] || mkdir -p /etc/mail; cat >$1; if id exim 2>/dev/null; then chown exim $1; chmod 400 $1; else chmod 444 $1; fi; touch -t $(date +%Y%m%d%H%M -d @$2) $1'
$RSH "$copy" /etc/mail/exim.pem $6 <"$2"
$RSH "$copy" /etc/mail/exim.crt $6 <"$4"
$RSH 'systemctl reload exim.service || true'
ETC_CHANGED_{{DMZ | regex_replace('-', '_')}}=1
}
# $1: force|test; $2: KEYFILE; $3: CERTFILE; $4: FULLCHAINFILE; $5: CHAINFILE; $6: TIMESTAMP
deploy_prosody() {
if [ "$1" == test ] \
&& $RSH 'test -f /etc/prosody/certs/{{net_soa}}.key && test -f /etc/prosody/certs/{{net_soa}}.crt' \
&& $RSH 'find /etc/prosody/certs/{{net_soa}}.{key,crt} -mmin -$((1+($(date +%s)-${1})/60)) -printf . | grep -q ..' ${6%.*}; then
return 0
fi
local copy='[ -d /etc/prosody/certs ] || mkdir -p /etc/prosody/certs; cat >$1; if id prosody 2>/dev/null; then chown prosody $1; chmod 400 $1; else chmod 444 $1; fi; touch -t $(date +%Y%m%d%H%M -d @$2) $1'
$RSH "$copy" /etc/prosody/certs/{{net_soa}}.key $6 <"$2"
$RSH "$copy" /etc/prosody/certs/{{net_soa}}.crt $6 <"$4"
$RSH 'systemctl reload prosody.service || true'
ETC_CHANGED_{{DMZ | regex_replace('-', '_')}}=1
}
# $1: force|test; $2: KEYFILE; $3: CERTFILE; $4: FULLCHAINFILE; $5: CHAINFILE; $6: TIMESTAMP
deploy_haproxy() {
if [ "$1" == test ] \
&& $RSH 'test -f /etc/haproxy/tls.pem' \
&& $RSH 'find /etc/haproxy/tls.pem -mmin -$((1+($(date +%s)-${1})/60)) -printf . | grep -q .' ${6%.*}; then
return 0
fi
local copy='[ -d /etc/haproxy ] || mkdir -p /etc/haproxy; cat >$1; chmod 400 $1; touch -t $(date +%Y%m%d%H%M -d @$2) $1'
cat "$4" "$2" | $RSH "$copy" /etc/haproxy/tls.pem $6
$RSH 'systemctl reload haproxy.service || true'
ETC_CHANGED_{{DMZ | regex_replace('-', '_')}}=1
}
deploy_cert() {
local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}"
deploy_exim force "$KEYFILE" "$CERTFILE" "$FULLCHAINFILE" "$CHAINFILE" "$TIMESTAMP"
deploy_prosody force "$KEYFILE" "$CERTFILE" "$FULLCHAINFILE" "$CHAINFILE" "$TIMESTAMP"
deploy_haproxy force "$KEYFILE" "$CERTFILE" "$FULLCHAINFILE" "$CHAINFILE" "$TIMESTAMP"
}
unchanged_cert() {
local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="$(find "$2" -printf '%T@')"
deploy_exim test "$KEYFILE" "$CERTFILE" "$FULLCHAINFILE" "$CHAINFILE" "$TIMESTAMP"
deploy_prosody test "$KEYFILE" "$CERTFILE" "$FULLCHAINFILE" "$CHAINFILE" "$TIMESTAMP"
deploy_haproxy test "$KEYFILE" "$CERTFILE" "$FULLCHAINFILE" "$CHAINFILE" "$TIMESTAMP"
}
invalid_challenge() {
local DOMAIN="${1}" RESPONSE="${2}"
printf 'Failed ACME challenge for DOMAIN=%s: RESPONSE=%s\n' "$DOMAIN" "$RESPONSE" >&2
}
request_failure() {
local STATUSCODE="${1}" REASON="${2}" REQTYPE="${3}"
printf 'Failed %s request for ACME: STATUSCODE=%s (%s)\n' "$REQTYPE" "$STATUSCODE" "$REASON" >&2
}
exit_hook() {
return 0
}
HANDLER="$1"; shift
if [[ "${HANDLER}" =~ ^(deploy_challenge|clean_challenge|deploy_cert|unchanged_cert|invalid_challenge|request_failure|exit_hook)$ ]]; then
"$HANDLER" "$@"
fi