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

110 lines
4.0 KiB
Django/Jinja

#!/usr/bin/env bash
# The home-server project produces a multi-purpose setup using Ansible.
# Copyright © 2018 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.
RSH=/usr/local/bin/{{DMZ}}
ETC_CHANGED_{{hostname}}=
ETC_CHANGED_{{DMZ}}=
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'"
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='cat >$1; chown exim $1; chmod 400 $1; 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"
systemctl -M {{DMZ}} reload exim.service
ETC_CHANGED_{{DMZ}}=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='cat >$1; chown prosody $1; chmod 400 $1; 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"
systemctl -M {{DMZ}} reload prosody.service
ETC_CHANGED_{{DMZ}}=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='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
systemctl -M {{DMZ}} reload haproxy.service
ETC_CHANGED_{{DMZ}}=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