2017-08-24 18:25:42 +02:00
#!/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
#
2016-12-14 15:49:34 +01:00
2017-09-21 03:29:55 +02:00
set -e
2017-09-11 14:18:20 +02:00
usage( ) {
2017-09-21 03:29:55 +02:00
echo " Usage: $0 [ --cron ] NAME "
2017-09-21 00:39:06 +02:00
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 ""
2017-09-11 14:18:20 +02:00
}
2017-10-03 09:50:53 +02:00
debug( ) {
[ " $CRON " = "NO" ] && echo " $1 "
}
error( ) {
echo " error: $1 " >& 2
[ " $1 " = "invalid argument(s)" ] && usage
exit 1
}
2017-08-24 18:25:42 +02:00
mkconf_apache( ) {
2017-10-03 09:50:53 +02:00
debug "Apache detected... first configuration"
2017-09-21 03:29:55 +02:00
[ -f " /etc/apache2/ssl/ ${ vhost } .conf " ] && sed -i " s~^SSLCertificateFile.* $~SSLCertificateFile $CRT_DIR / ${ vhost } /live/fullchain.pem~ " " /etc/apache2/ssl/ ${ vhost } .conf "
apache2ctl -t
2017-08-24 18:25:42 +02:00
}
2016-12-14 15:49:34 +01:00
2017-08-24 18:25:42 +02:00
mkconf_nginx( ) {
2017-10-03 09:50:53 +02:00
debug "Nginx detected... first configuration"
2017-09-21 03:29:55 +02:00
[ -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
2017-08-24 18:25:42 +02:00
}
2016-12-14 15:49:34 +01:00
2017-08-24 18:25:42 +02:00
main( ) {
2017-09-21 00:39:06 +02:00
[ -f /etc/default/evoacme ] && . /etc/default/evoacme
2017-09-21 03:29:55 +02:00
[ -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
2017-10-03 09:50:53 +02:00
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)"
2017-09-21 03:29:55 +02:00
[ " $# " -eq 1 ] && vhost = $( basename " $1 " .conf) && CRON = NO
[ " $# " -eq 2 ] && vhost = $( basename " $2 " .conf) && CRON = YES
# verify .csr file
2017-10-03 09:50:53 +02:00
[ ! -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 "
2017-09-21 03:29:55 +02:00
# Hook for evoadmin-web in cluster mode : check master status
2017-09-21 00:39:06 +02:00
if [ -f " /home/ ${ vhost } /state " ] ; then
grep -q "STATE=master" " /home/ ${ vhost } /state " || exit 0
fi
2017-09-11 14:18:20 +02:00
2017-09-21 00:39:06 +02:00
if [ -n " $SSL_EMAIL " ] ; then
emailopt = " -m $SSL_EMAIL "
else
emailopt = "--register-unsafely-without-email"
fi
2017-09-21 03:29:55 +02:00
2017-09-21 00:39:06 +02:00
DATE = $( date "+%Y%m%d" )
2017-10-03 09:50:53 +02:00
[ ! -n " $DATE " ] && error "invalid date"
2017-09-21 03:29:55 +02:00
# If live link already exists, it's not our first time...
2017-09-21 00:39:06 +02:00
if [ -h " $CRT_DIR / ${ vhost } /live " ] ; then
2017-10-03 09:50:53 +02:00
openssl x509 -noout -modulus -in " $CRT_DIR / ${ vhost } /live/cert.crt " >/dev/null || error " $CRT_DIR / ${ vhost } /live/cert.crt is invalid "
2017-09-21 03:29:55 +02:00
# 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" )
2017-09-21 00:39:06 +02:00
date_today = $( date +'%s' )
2017-10-03 09:50:53 +02:00
[ " $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
2017-09-21 03:29:55 +02:00
else
2017-09-21 00:39:06 +02:00
which apache2ctl >/dev/null && mkconf_apache
which nginx >/dev/null && mkconf_nginx
fi
2017-09-21 03:29:55 +02:00
# renew certificate with certbot
2017-10-03 09:50:53 +02:00
[ -d " $CRT_DIR / ${ vhost } / ${ DATE } " ] && error " $CRT_DIR / ${ vhost } / ${ DATE } directory already exists, remove it manually. "
2017-09-21 03:29:55 +02:00
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
2017-10-03 09:50:53 +02:00
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 "
2017-09-21 03:29:55 +02:00
# link dance
[ -h " $CRT_DIR / ${ vhost } /live " ] && rm " $CRT_DIR / ${ vhost } /live "
ln -s " $CRT_DIR / ${ vhost } / ${ DATE } " " $CRT_DIR / ${ vhost } /live "
2017-10-03 09:50:53 +02:00
openssl x509 -noout -modulus -in " $CRT_DIR / ${ vhost } /live/cert.crt " >/dev/null || error " new $CRT_DIR /{vhost}/live/cert.crt is invalid "
2017-09-21 03:29:55 +02:00
# reload apache or nginx (TODO: need improvments)
2017-10-03 09:50:53 +02:00
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
2017-09-21 03:29:55 +02:00
2017-08-24 18:25:42 +02:00
}
main " $@ "