ansible-roles/evoacme/files/evoacme.sh

126 lines
5.4 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
#
# evoacme is a shell script to manage Let's Encrypt certificate with
# certbot tool but with a dedicated user (no-root) and from a csr
#
# Author: Victor Laborie <vlaborie@evolix.fr>
# Licence: AGPLv3
#
set -e
usage() {
echo "Usage: $0 [ --cron ] NAME"
echo ""
echo "NAME must be correspond to :"
echo "- a CSR in ${CSR_DIR}/NAME.csr"
echo "- a KEY in ${SSL_KEY_DIR}/NAME.key"
echo ""
}
debug() {
[ "$CRON" = "NO" ] && echo "$1"
}
error() {
echo "error: $1" >&2
[ "$1" = "invalid argument(s)" ] && usage
exit 1
}
mkconf_apache() {
debug "Apache detected... first configuration"
[ -f "/etc/apache2/ssl/${vhost}.conf" ] && sed -i "s~^SSLCertificateFile.*$~SSLCertificateFile $CRT_DIR/${vhost}/live/fullchain.pem~" "/etc/apache2/ssl/${vhost}.conf"
apache2ctl -t
}
mkconf_nginx() {
debug "Nginx detected... first configuration"
[ -f "/etc/nginx/ssl/${vhost}.conf" ] && sed -i "s~^ssl_certificate[^_].*$~ssl_certificate $CRT_DIR/${vhost}/live/fullchain.pem;~" "/etc/nginx/ssl/${vhost}.conf"
nginx -t
}
main() {
[ -f /etc/default/evoacme ] && . /etc/default/evoacme
[ -z "${SSL_KEY_DIR}" ] && SSL_KEY_DIR=/etc/ssl/private
[ -z "${ACME_DIR}" ] && ACME_DIR=/var/lib/letsencrypt
[ -z "${CSR_DIR}" ] && CSR_DIR=/etc/ssl/requests
[ -z "${CRT_DIR}" ] && CRT_DIR=/etc/letsencrypt
[ -z "${LOG_DIR}" ] && LOG_DIR=/var/log/evoacme
[ -z "${SSL_MINDAY}" ] && SSL_MINDAY=30
[ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR=/etc/ssl/self-signed
[ -z "${DH_DIR}" ] && DH_DIR=etc/ssl/dhparam
# misc verifications
[ "$1" = "-h" ] || [ "$1" = "--help" ] && usage && exit 0
which openssl >/dev/null || error "openssl command not installed"
which certbot >/dev/null || error "certbot command not installed"
[ ! -d $ACME_DIR ] && error "$ACME_DIR is not a directory"
[ ! -d $CSR_DIR ] && error "$CSR_DIR is not a directory"
[ ! -d $LOG_DIR ] && error "$LOG_DIR is not a directory"
[ "$#" -ge 3 ] || [ "$#" -le 0 ] && error "invalid argument(s)"
[ "$#" -eq 2 ] && [ "$1" != "--cron" ] && error "invalid argument(s)"
[ "$#" -eq 1 ] && vhost=$(basename "$1" .conf) && CRON=NO
[ "$#" -eq 2 ] && vhost=$(basename "$2" .conf) && CRON=YES
# verify .csr file
[ ! -f "$CSR_DIR/${vhost}.csr" ] && error "$CSR_DIR/${vhost}.csr absent"
[ ! -r "$CSR_DIR/${vhost}.csr" ] && error "$C´SR_DIR/${vhost}.csr is not readable"
openssl req -noout -modulus -in "$CSR_DIR/${vhost}.csr" >/dev/null || error "$CSR_DIR/${vhost}.csr is invalid"
debug "Using CSR file: $CSR_DIR/${vhost}.csr"
# Hook for evoadmin-web in cluster mode : check master status
if [ -f "/home/${vhost}/state" ]; then
grep -q "STATE=master" "/home/${vhost}/state" || exit 0
fi
if [ -n "$SSL_EMAIL" ]; then
emailopt="-m $SSL_EMAIL"
else
emailopt="--register-unsafely-without-email"
fi
DATE=$(date "+%Y%m%d")
[ ! -n "$DATE" ] && error "invalid date"
# If live link already exists, it's not our first time...
if [ -h "$CRT_DIR/${vhost}/live" ]; then
openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/live/cert.crt" >/dev/null || error "$CRT_DIR/${vhost}/live/cert.crt is invalid"
# Verify if our certificate will expire
crt_end_date=$(openssl x509 -noout -enddate -in "$CRT_DIR/${vhost}/live/cert.crt" | cut -d= -f2)
date_renew=$(date -ud "$crt_end_date - $SSL_MINDAY days" +"%s")
date_today=$(date +'%s')
[ "$date_today" -lt "$date_renew" ] && debug "Cert $CRT_DIR/${vhost}/live/cert.crt expires at $crt_end_date => more than $SSL_MINDAY days: thxbye." && exit 0
else
which apache2ctl >/dev/null && mkconf_apache
which nginx >/dev/null && mkconf_nginx
fi
# renew certificate with certbot
[ -d "$CRT_DIR/${vhost}/${DATE}" ] && error "$CRT_DIR/${vhost}/${DATE} directory already exists, remove it manually."
mkdir -pm 755 "$CRT_DIR/${vhost}/${DATE}"
chown -R acme: "$CRT_DIR/${vhost}/${DATE}"
[ "$CRON" = "YES" ] && CERTBOT_OPTS="--quiet"
sudo -u acme certbot certonly $CERTBOT_OPTS --webroot --csr "$CSR_DIR/${vhost}.csr" --webroot-path "$ACME_DIR" -n --agree-tos --cert-path="$CRT_DIR/${vhost}/${DATE}/cert.crt" --fullchain-path="$CRT_DIR/${vhost}/${DATE}/fullchain.pem" --chain-path="$CRT_DIR/${vhost}/${DATE}/chain.pem" "$emailopt" --logs-dir "$LOG_DIR" 2>&1 | grep -v "certbot.crypto_util"
# verify if all is right
openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/${DATE}/cert.crt" >/dev/null || error "new $CRT_DIR/${vhost}/${DATE}/cert.crt is invalid"
openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/${DATE}/fullchain.pem" >/dev/null || error "new $CRT_DIR/${vhost}/${DATE}/fullchain.pem is invalid"
openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/${DATE}/chain.pem" >/dev/null || error "new $CRT_DIR/${vhost}/${DATE}/chain.pem is invalid"
# link dance
[ -h "$CRT_DIR/${vhost}/live" ] && rm "$CRT_DIR/${vhost}/live"
ln -s "$CRT_DIR/${vhost}/${DATE}" "$CRT_DIR/${vhost}/live"
openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/live/cert.crt" >/dev/null || error "new $CRT_DIR/{vhost}/live/cert.crt is invalid"
# reload apache or nginx (TODO: need improvments)
pidof apache2 >/dev/null && apache2ctl -t 2>/dev/null && debug "Apache detected... reloading" && systemctl reload apache2
pidof nginx >/dev/null && nginx -t 2>/dev/null && debug "Nginx detected... reloading" && systemctl reload apache2
}
main "$@"