110 lines
3.4 KiB
Bash
110 lines
3.4 KiB
Bash
#!/bin/sh -e
|
|
|
|
ACME_TINY_CERT_REQUEST_DIR="/var/acme-tiny/cert-requests"
|
|
ACME_TINY_ACCOUNT_KEY="/var/acme-tiny/account.key"
|
|
ACME_CHALLENGE_DIR="/srv/www/sites/acme/public/.well-known/acme-challenge"
|
|
|
|
REALM="${__object_id}"
|
|
EXTRA_DOMAINS=""
|
|
if [ -f "${__object}/parameter/extra-domain" ]; then
|
|
EXTRA_DOMAINS="$(cat "${__object}/parameter/extra-domain")"
|
|
fi
|
|
|
|
#TODO: support linux too
|
|
REALM_DIR="/usr/local/etc/pki/realms/${REALM}"
|
|
REALM_CERT="${REALM_DIR}/default.crt"
|
|
REALM_KEY="${REALM_DIR}/default.key"
|
|
REALM_CERT_REQUEST="${ACME_TINY_CERT_REQUEST_DIR}/${REALM}.csr"
|
|
REALM_CERT_REQUEST_CNF="${ACME_TINY_CERT_REQUEST_DIR}/${REALM}.cnf"
|
|
|
|
CSR_ALT_NAMES=""
|
|
REALM_CERT_REQUEST_CNF_LINE=""
|
|
if [ -n "${EXTRA_DOMAINS}" ]; then
|
|
CSR_ALT_NAMES="DNS:${REALM}"
|
|
for domain in ${EXTRA_DOMAINS}; do
|
|
CSR_ALT_NAMES="${CSR_ALT_NAMES},DNS:${domain}"
|
|
done
|
|
# CSR requests are executed always against .new, only after succeeding .new replaces the .cnf
|
|
REALM_CERT_REQUEST_CNF_LINE="-reqexts SAN -config '${REALM_CERT_REQUEST_CNF}.new'"
|
|
fi
|
|
|
|
cat << EOF
|
|
if [ ! -d '${REALM_DIR}' ]; then
|
|
mkdir -p '${REALM_DIR}'
|
|
fi
|
|
if [ ! -f '${REALM_KEY}' ]; then
|
|
openssl genrsa 4096 > '${REALM_KEY}'
|
|
fi
|
|
|
|
if [ ! -d '${ACME_TINY_CERT_REQUEST_DIR}' ]; then
|
|
mkdir '${ACME_TINY_CERT_REQUEST_DIR}'
|
|
fi
|
|
|
|
FORCE_CSR_REGEN=""
|
|
if [ -n '${CSR_ALT_NAMES}' ]; then
|
|
# Generate new config
|
|
cat /etc/ssl/openssl.cnf > '${REALM_CERT_REQUEST_CNF}.new'
|
|
printf '[SAN]\nsubjectAltName=${CSR_ALT_NAMES}' >> '${REALM_CERT_REQUEST_CNF}.new'
|
|
# Compare to previous config if necessary
|
|
if [ -f '${REALM_CERT_REQUEST_CNF}' ]; then
|
|
CNF_DIFF=\$(diff -q '${REALM_CERT_REQUEST_CNF}' '${REALM_CERT_REQUEST_CNF}.new' || true)
|
|
if [ -n "\${CNF_DIFF}" ]; then
|
|
# Options have changed
|
|
FORCE_CSR_REGEN="YES"
|
|
else
|
|
# Since they match, we won't be using this, clean it
|
|
rm '${REALM_CERT_REQUEST_CNF}.new'
|
|
fi
|
|
else
|
|
# We never used SAN here, CSR regen needed.
|
|
FORCE_CSR_REGEN="YES"
|
|
fi
|
|
else
|
|
# We used SAN at some point, not any more
|
|
if [ -f '${REALM_CERT_REQUEST_CNF}' ]; then
|
|
rm '${REALM_CERT_REQUEST_CNF}'
|
|
FORCE_CSR_REGEN="YES"
|
|
fi
|
|
fi
|
|
|
|
# Create or re-create when params have changed
|
|
if [ ! -f '${REALM_CERT_REQUEST}' -o -n "\${FORCE_CSR_REGEN}" ]; then
|
|
openssl req -new -sha256 -key '${REALM_KEY}' -subj '/CN=${REALM}' -out '${REALM_CERT_REQUEST}' ${REALM_CERT_REQUEST_CNF_LINE}
|
|
fi
|
|
|
|
# Check if cert exists, and if so whether or not it's older than a month
|
|
if [ -f '${REALM_CERT}' ]; then
|
|
MODIFIED_IN_30d="\$(find '${REALM_CERT}' -mtime -30d)"
|
|
if [ -z "\${MODIFIED_IN_30d}" ]; then
|
|
# Cert is over a month old, it's fine to regenerate
|
|
FORCE_CRT_REGEN="YES"
|
|
fi
|
|
else
|
|
# This cert doesn't exist
|
|
FORCE_CRT_REGEN="YES"
|
|
fi
|
|
|
|
|
|
# Only request certificate when needed
|
|
# TODO: support linux too
|
|
if [ -n "\${FORCE_CSR_REGEN}" -o -n "\${FORCE_CRT_REGEN}" ]; then
|
|
doas -u acme-tiny -- acme_tiny \
|
|
--account '${ACME_TINY_ACCOUNT_KEY}' \
|
|
--csr '${REALM_CERT_REQUEST}' \
|
|
--acme-dir '${ACME_CHALLENGE_DIR}' > '${REALM_CERT}.new'
|
|
|
|
if [ -s '${REALM_CERT}.new' ]; then
|
|
mv '${REALM_CERT}.new' '${REALM_CERT}'
|
|
else
|
|
echo "Failed to generate cert for realm '${REALM}'."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ -n '${REALM_CERT_REQUEST_CNF_LINE}' -a -f '${REALM_CERT_REQUEST_CNF}.new' ]; then
|
|
# CSR and cert generation succeded with a new config, put new config in-place.
|
|
# This is the last thing we do, so we try again next time if sth fails.
|
|
mv '${REALM_CERT_REQUEST_CNF}.new' '${REALM_CERT_REQUEST_CNF}'
|
|
fi
|
|
EOF
|