From cdf086182106958858f2b19304727748656b2d52 Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Thu, 21 Sep 2017 00:00:30 +0200 Subject: [PATCH 1/6] More clear without include for determining apache/nginx presence --- evoacme/tasks/main.yml | 12 +++++++++++- evoacme/tasks/webserver.yml | 12 ------------ 2 files changed, 11 insertions(+), 13 deletions(-) delete mode 100644 evoacme/tasks/webserver.yml diff --git a/evoacme/tasks/main.yml b/evoacme/tasks/main.yml index beac178e..6bc21a02 100644 --- a/evoacme/tasks/main.yml +++ b/evoacme/tasks/main.yml @@ -13,7 +13,17 @@ - include: scripts.yml -- include: webserver.yml +- name: Determine Apache presence + stat: + path: /etc/apache2/apache2.conf + check_mode: no + register: sta + +- name: Determine Nginx presence + stat: + path: /etc/nginx/nginx.conf + check_mode: no + register: stn - include: apache.yml when: sta.stat.isreg is defined and sta.stat.isreg diff --git a/evoacme/tasks/webserver.yml b/evoacme/tasks/webserver.yml deleted file mode 100644 index 8092aa98..00000000 --- a/evoacme/tasks/webserver.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Determine Nginx presence - stat: - path: /etc/nginx/nginx.conf - check_mode: no - register: stn - -- name: Determine Apache presence - stat: - path: /etc/apache2/apache2.conf - check_mode: no - register: sta From a006a604f24db0bb9379d360aa3815c3aa0cb902 Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Thu, 21 Sep 2017 00:26:59 +0200 Subject: [PATCH 2/6] Rename /etc/cron.d/certbot to .disabled as written in https://wiki.evolix.org/HowtoLetsEncrypt --- evoacme/tasks/certbot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/evoacme/tasks/certbot.yml b/evoacme/tasks/certbot.yml index 20658ec2..88f0eb5b 100644 --- a/evoacme/tasks/certbot.yml +++ b/evoacme/tasks/certbot.yml @@ -42,6 +42,18 @@ path: /usr/local/bin/certbot state: absent +- name: stat /etc/cron.d/certbot + stat: + path: /etc/cron.d/certbot + register: etc_cron_d_certbot + +- name: Rename certbot dpkg cron to .disabled + copy: + remote_src: True + src: /etc/cron.d/certbot + dest: /etc/cron.d/certbot.disabled + when: etc_cron_d_certbot.stat.exists + - name: Remove certbot dpkg cron file: path: /etc/cron.d/certbot From 26d823174f70eaa1b85f9543fb41870ab748f72f Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Thu, 21 Sep 2017 00:32:34 +0200 Subject: [PATCH 3/6] use {{ evoacme_crt_dir }} var everywhere --- evoacme/tasks/conf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evoacme/tasks/conf.yml b/evoacme/tasks/conf.yml index b39b5384..4d9f6704 100644 --- a/evoacme/tasks/conf.yml +++ b/evoacme/tasks/conf.yml @@ -1,6 +1,6 @@ --- - ini_file: - dest: /etc/letsencrypt/openssl.cnf + dest: "{{ evoacme_crt_dir }}/openssl.cnf" section: 'req' option: "{{ item.name }}" value: "{{ item.var }}" From 81698d03de5392a1ae05646a0ce11480a8637d54 Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Thu, 21 Sep 2017 00:36:47 +0200 Subject: [PATCH 4/6] by default copy use files/ directory --- evoacme/tasks/scripts.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evoacme/tasks/scripts.yml b/evoacme/tasks/scripts.yml index 01e61fdb..b1ebe473 100644 --- a/evoacme/tasks/scripts.yml +++ b/evoacme/tasks/scripts.yml @@ -9,7 +9,7 @@ - name: Copy make-csr.sh script copy: - src: files/make-csr.sh + src: make-csr.sh dest: /usr/local/sbin/make-csr owner: root group: root @@ -17,7 +17,7 @@ - name: Copy evoacme script copy: - src: files/evoacme.sh + src: evoacme.sh dest: /usr/local/sbin/evoacme owner: root group: root From 7ea59826117fda8b59869a349de1d8057d8b2a7c Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Thu, 21 Sep 2017 00:39:06 +0200 Subject: [PATCH 5/6] empty commit, only :retab --- evoacme/files/certbot.cron | 2 +- evoacme/files/evoacme.sh | 104 +++++++++--------- evoacme/files/make-csr.sh | 212 ++++++++++++++++++------------------- 3 files changed, 159 insertions(+), 159 deletions(-) diff --git a/evoacme/files/certbot.cron b/evoacme/files/certbot.cron index a7c4eef2..eb2ddb3a 100755 --- a/evoacme/files/certbot.cron +++ b/evoacme/files/certbot.cron @@ -10,5 +10,5 @@ [ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt' find "${CRT_DIR}" -maxdepth 1 -mindepth 1 -type d ! -path "*accounts" -exec basename {} \; | while read vhost; do - evoacme "$vhost" + evoacme "$vhost" done diff --git a/evoacme/files/evoacme.sh b/evoacme/files/evoacme.sh index ffbf22ac..0504567e 100755 --- a/evoacme/files/evoacme.sh +++ b/evoacme/files/evoacme.sh @@ -8,12 +8,12 @@ # usage() { - echo "Usage: $0 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 "" + echo "Usage: $0 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 "" } mkconf_apache() { @@ -27,58 +27,58 @@ mkconf_nginx() { } mkconf_haproxy() { - mkdir -p /etc/ssl/haproxy -m 700 - cat "$CRT_DIR/${vhost}/live/fullchain.pem" "$SSL_KEY_DIR/${vhost}.key" > "/etc/ssl/haproxy/${vhost}.pem" - [ -f "$DH_DIR/${vhost}.pem" ] && cat "$DH_DIR/${vhost}.pem" >> "/etc/ssl/haproxy/${vhost}.pem" - haproxy -c -f /etc/haproxy/haproxy.cfg >/dev/null && service haproxy reload + mkdir -p /etc/ssl/haproxy -m 700 + cat "$CRT_DIR/${vhost}/live/fullchain.pem" "$SSL_KEY_DIR/${vhost}.key" > "/etc/ssl/haproxy/${vhost}.pem" + [ -f "$DH_DIR/${vhost}.pem" ] && cat "$DH_DIR/${vhost}.pem" >> "/etc/ssl/haproxy/${vhost}.pem" + haproxy -c -f /etc/haproxy/haproxy.cfg >/dev/null && service haproxy reload } main() { - [ -f /etc/default/evoacme ] && . /etc/default/evoacme - [ -z "${SSL_KEY_DIR}" ] && SSL_KEY_DIR='/etc/ssl/private' - [ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt' - [ -z "${CSR_DIR}" ] && CSR_DIR='/etc/ssl/requests' - [ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR='/etc/ssl/self-signed' - [ -z "${DH_DIR}" ] && DH_DIR='/etc/ssl/dhparam' - [ -z "${LOG_DIR}" ] && LOG_DIR='/var/log/evoacme' - - [ "$#" -ne 1 ] && usage && exit 1 + [ -f /etc/default/evoacme ] && . /etc/default/evoacme + [ -z "${SSL_KEY_DIR}" ] && SSL_KEY_DIR='/etc/ssl/private' + [ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt' + [ -z "${CSR_DIR}" ] && CSR_DIR='/etc/ssl/requests' + [ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR='/etc/ssl/self-signed' + [ -z "${DH_DIR}" ] && DH_DIR='/etc/ssl/dhparam' + [ -z "${LOG_DIR}" ] && LOG_DIR='/var/log/evoacme' + + [ "$#" -ne 1 ] && usage && exit 1 - vhost=$(basename "$1" .conf) + vhost=$(basename "$1" .conf) - # Check master status for evoadmin-cluster - if [ -f "/home/${vhost}/state" ]; then - grep -q "STATE=master" "/home/${vhost}/state" || exit 0 - fi + # Check master status for evoadmin-cluster + if [ -f "/home/${vhost}/state" ]; then + grep -q "STATE=master" "/home/${vhost}/state" || exit 0 + fi - SSL_EMAIL=$(grep emailAddress "${CRT_DIR}/openssl.cnf"|cut -d'=' -f2|xargs) - if [ -n "$SSL_EMAIL" ]; then - emailopt="-m $SSL_EMAIL" - else - emailopt="--register-unsafely-without-email" - fi - DATE=$(date "+%Y%m%d") - - if [ -h "$CRT_DIR/${vhost}/live" ]; then - crt_end_date=$(openssl x509 -noout -enddate -in "$CRT_DIR/${vhost}/live/cert.crt"|sed -e "s/.*=//") - date_crt=$(date -ud "$crt_end_date" +"%s") - date_today=$(date +'%s') - date_diff=$(((date_crt - date_today) / (60*60*24))) - [ "$date_diff" -ge "$SSL_MINDAY" ] && exit 0 - fi - rm -rf "$CRT_DIR/${vhost}/${DATE}" - mkdir -pm 755 "$CRT_DIR/${vhost}/${DATE}" - chown -R acme: "$CRT_DIR/${vhost}" - sudo -u acme certbot certonly --quiet --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" - if [ -f "$CRT_DIR/${vhost}/${DATE}/fullchain.pem" ]; then - rm -f "$CRT_DIR/${vhost}/live" - ln -s "$CRT_DIR/${vhost}/${DATE}" "$CRT_DIR/${vhost}/live" - which apache2ctl >/dev/null && mkconf_apache - which nginx >/dev/null && mkconf_nginx - which haproxy >/dev/null && mkconf_haproxy - else - rmdir "$CRT_DIR/${vhost}/${DATE}" - fi + SSL_EMAIL=$(grep emailAddress "${CRT_DIR}/openssl.cnf"|cut -d'=' -f2|xargs) + if [ -n "$SSL_EMAIL" ]; then + emailopt="-m $SSL_EMAIL" + else + emailopt="--register-unsafely-without-email" + fi + DATE=$(date "+%Y%m%d") + + if [ -h "$CRT_DIR/${vhost}/live" ]; then + crt_end_date=$(openssl x509 -noout -enddate -in "$CRT_DIR/${vhost}/live/cert.crt"|sed -e "s/.*=//") + date_crt=$(date -ud "$crt_end_date" +"%s") + date_today=$(date +'%s') + date_diff=$(((date_crt - date_today) / (60*60*24))) + [ "$date_diff" -ge "$SSL_MINDAY" ] && exit 0 + fi + rm -rf "$CRT_DIR/${vhost}/${DATE}" + mkdir -pm 755 "$CRT_DIR/${vhost}/${DATE}" + chown -R acme: "$CRT_DIR/${vhost}" + sudo -u acme certbot certonly --quiet --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" + if [ -f "$CRT_DIR/${vhost}/${DATE}/fullchain.pem" ]; then + rm -f "$CRT_DIR/${vhost}/live" + ln -s "$CRT_DIR/${vhost}/${DATE}" "$CRT_DIR/${vhost}/live" + which apache2ctl >/dev/null && mkconf_apache + which nginx >/dev/null && mkconf_nginx + which haproxy >/dev/null && mkconf_haproxy + else + rmdir "$CRT_DIR/${vhost}/${DATE}" + fi } main "$@" diff --git a/evoacme/files/make-csr.sh b/evoacme/files/make-csr.sh index 844847ab..5338ba2c 100755 --- a/evoacme/files/make-csr.sh +++ b/evoacme/files/make-csr.sh @@ -8,143 +8,143 @@ # get_domains() { - echo "$vhostfile"|grep -q nginx - if [ "$?" -eq 0 ]; then - domains=$(grep -oE "^( )*[^#]+" "$vhostfile" |grep -oE "[^\$]server_name.*;$"|sed 's/server_name//'|tr -d ';'|sed 's/\s\{1,\}//'|sed 's/\s\{1,\}/\n/g'|sort|uniq) - fi - - echo "$vhostfile" |grep -q apache2 - if [ "$?" -eq 0 ]; then - domains=$(grep -oE "^( )*[^#]+" "$vhostfile" |grep -oE "(ServerName|ServerAlias).*"|sed 's/ServerName//'|sed 's/ServerAlias//'|sed 's/\s\{1,\}//'|sort|uniq) - fi - valid_domains="" - nb=0 - - echo "Valid(s) domain(s) in $vhost :" - for domain in $domains; do - real_ip=$(dig +short "$domain"|grep -oE "([0-9]+\.){3}[0-9]+") - for ip in $(echo "$SRV_IP"|xargs -n1); do - if [ "${ip}" = "${real_ip}" ]; then - valid_domains="$valid_domains $domain" - nb=$(( nb + 1 )) - echo "* $domain -> $real_ip" - fi - done - done - - if [ "$nb" -eq 0 ]; then - nb=$(echo "$domains"|wc -l) - echo "* No valid domain found" - echo "All following(s) domain(s) will be used for CSR creation :" - for domain in $domains; do - echo "* $domain" - done - else - domains="$valid_domains" - fi - domains=$(echo "$domains"|xargs -n1) + echo "$vhostfile"|grep -q nginx + if [ "$?" -eq 0 ]; then + domains=$(grep -oE "^( )*[^#]+" "$vhostfile" |grep -oE "[^\$]server_name.*;$"|sed 's/server_name//'|tr -d ';'|sed 's/\s\{1,\}//'|sed 's/\s\{1,\}/\n/g'|sort|uniq) + fi + + echo "$vhostfile" |grep -q apache2 + if [ "$?" -eq 0 ]; then + domains=$(grep -oE "^( )*[^#]+" "$vhostfile" |grep -oE "(ServerName|ServerAlias).*"|sed 's/ServerName//'|sed 's/ServerAlias//'|sed 's/\s\{1,\}//'|sort|uniq) + fi + valid_domains="" + nb=0 + + echo "Valid(s) domain(s) in $vhost :" + for domain in $domains; do + real_ip=$(dig +short "$domain"|grep -oE "([0-9]+\.){3}[0-9]+") + for ip in $(echo "$SRV_IP"|xargs -n1); do + if [ "${ip}" = "${real_ip}" ]; then + valid_domains="$valid_domains $domain" + nb=$(( nb + 1 )) + echo "* $domain -> $real_ip" + fi + done + done + + if [ "$nb" -eq 0 ]; then + nb=$(echo "$domains"|wc -l) + echo "* No valid domain found" + echo "All following(s) domain(s) will be used for CSR creation :" + for domain in $domains; do + echo "* $domain" + done + else + domains="$valid_domains" + fi + domains=$(echo "$domains"|xargs -n1) } make_key() { - openssl genrsa -out "$SSL_KEY_DIR/${vhost}.key" "$SSL_KEY_SIZE" 2>/dev/null - chown root: "$SSL_KEY_DIR/${vhost}.key" - chmod 600 "$SSL_KEY_DIR/${vhost}.key" + openssl genrsa -out "$SSL_KEY_DIR/${vhost}.key" "$SSL_KEY_SIZE" 2>/dev/null + chown root: "$SSL_KEY_DIR/${vhost}.key" + chmod 600 "$SSL_KEY_DIR/${vhost}.key" } make_csr() { - domains="$1" - nb=$(echo "$domains"|wc -l) - config_file="/tmp/make-csr-${vhost}.conf" + domains="$1" + nb=$(echo "$domains"|wc -l) + config_file="/tmp/make-csr-${vhost}.conf" - mkdir -p "$CSR_DIR" -m 0755 - - if [ "$nb" -eq 1 ]; then - cat /etc/letsencrypt/openssl.cnf - > "$config_file" < "$config_file" < "$config_file" < "$config_file" < "$CSR_DIR/${vhost}.csr" - fi - - if [ -f "$CSR_DIR/${vhost}.csr" ]; then - chmod 644 "$CSR_DIR/${vhost}.csr" - mkdir -p "$SELF_SIGNED_DIR" -m 0755 - openssl x509 -req -sha256 -days 365 -in "$CSR_DIR/${vhost}.csr" -signkey "$SSL_KEY_DIR/${vhost}.key" -out "$SELF_SIGNED_DIR/${vhost}.pem" - [ -f "$SELF_SIGNED_DIR/${vhost}.pem" ] && chmod 644 "$SELF_SIGNED_DIR/${vhost}.pem" - fi + openssl req -new -sha256 -key "$SSL_KEY_DIR/${vhost}.key" -reqexts SAN -config "$config_file" > "$CSR_DIR/${vhost}.csr" + fi + + if [ -f "$CSR_DIR/${vhost}.csr" ]; then + chmod 644 "$CSR_DIR/${vhost}.csr" + mkdir -p "$SELF_SIGNED_DIR" -m 0755 + openssl x509 -req -sha256 -days 365 -in "$CSR_DIR/${vhost}.csr" -signkey "$SSL_KEY_DIR/${vhost}.key" -out "$SELF_SIGNED_DIR/${vhost}.pem" + [ -f "$SELF_SIGNED_DIR/${vhost}.pem" ] && chmod 644 "$SELF_SIGNED_DIR/${vhost}.pem" + fi } mkconf_apache() { - mkdir -p /etc/apache2/ssl - if [ ! -f "/etc/apache2/ssl/${vhost}.conf" ]; then - cat > "/etc/apache2/ssl/${vhost}.conf" < "/etc/apache2/ssl/${vhost}.conf" < "/etc/nginx/ssl/${vhost}.conf" < "/etc/nginx/ssl/${vhost}.conf" <&2 - exit 1 - fi - vhost=$(basename "$1" .conf) - local_ip=$(ip a|grep brd|cut -d'/' -f1|grep -oE "([0-9]+\.){3}[0-9]+") + if [ "$#" -ne 1 ]; then + echo "You need to provide one argument !" >&2 + exit 1 + fi + vhost=$(basename "$1" .conf) + local_ip=$(ip a|grep brd|cut -d'/' -f1|grep -oE "([0-9]+\.){3}[0-9]+") - [ -f /etc/default/evoacme ] && . /etc/default/evoacme - [ -z "${SSL_KEY_DIR}" ] && SSL_KEY_DIR='/etc/ssl/private' - [ -z "${CSR_DIR}" ] && CSR_DIR='/etc/ssl/requests' - [ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt' - [ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR='/etc/ssl/self-signed' - SSL_KEY_SIZE=$(grep default_bits /etc/letsencrypt/openssl.cnf|cut -d'=' -f2|xargs) - [ -n "${SRV_IP}" ] && SRV_IP="${SRV_IP} $local_ip" || SRV_IP="$local_ip" - - vhostfile=$(ls "/etc/nginx/sites-enabled/${vhost}" "/etc/nginx/sites-enabled/${vhost}.conf" "/etc/apache2/sites-enabled/${vhost}" "/etc/apache2/sites-enabled/${vhost}.conf" 2>/dev/null|head -n1) - - if [ ! -h "$vhostfile" ]; then - echo "$vhost is not a valid virtualhost !" >&2 - exit 1 - fi + [ -f /etc/default/evoacme ] && . /etc/default/evoacme + [ -z "${SSL_KEY_DIR}" ] && SSL_KEY_DIR='/etc/ssl/private' + [ -z "${CSR_DIR}" ] && CSR_DIR='/etc/ssl/requests' + [ -z "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt' + [ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR='/etc/ssl/self-signed' + SSL_KEY_SIZE=$(grep default_bits /etc/letsencrypt/openssl.cnf|cut -d'=' -f2|xargs) + [ -n "${SRV_IP}" ] && SRV_IP="${SRV_IP} $local_ip" || SRV_IP="$local_ip" + + vhostfile=$(ls "/etc/nginx/sites-enabled/${vhost}" "/etc/nginx/sites-enabled/${vhost}.conf" "/etc/apache2/sites-enabled/${vhost}" "/etc/apache2/sites-enabled/${vhost}.conf" 2>/dev/null|head -n1) + + if [ ! -h "$vhostfile" ]; then + echo "$vhost is not a valid virtualhost !" >&2 + exit 1 + fi - if [ -f "$SSL_KEY_DIR/${vhost}.key" ]; then - echo "$vhost key already exist, overwrite it ? (y)" - read REPLY - [ "$REPLY" = "Y" ] || [ "$REPLY" = "y" ] || exit 0 - rm -f "/etc/apache2/ssl/${vhost}.conf /etc/nginx/ssl/${vhost}.conf" - [ -h "${CRT_DIR}/${vhost}/live" ] && rm "${CRT_DIR}/${vhost}/live" - fi + if [ -f "$SSL_KEY_DIR/${vhost}.key" ]; then + echo "$vhost key already exist, overwrite it ? (y)" + read REPLY + [ "$REPLY" = "Y" ] || [ "$REPLY" = "y" ] || exit 0 + rm -f "/etc/apache2/ssl/${vhost}.conf /etc/nginx/ssl/${vhost}.conf" + [ -h "${CRT_DIR}/${vhost}/live" ] && rm "${CRT_DIR}/${vhost}/live" + fi - get_domains - make_key - make_csr "$domains" - which apache2ctl >/dev/null && mkconf_apache + get_domains + make_key + make_csr "$domains" + which apache2ctl >/dev/null && mkconf_apache which nginx >/dev/null && mkconf_nginx } From 30c47fcd502af2c22287d4d096f1dc30d2890629 Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Thu, 21 Sep 2017 03:29:55 +0200 Subject: [PATCH 6/6] A lot of improvments: add comments, add tests/tests/tests, add --cron option, drop HAProxy support, modify Apache/Nginx conf only first time --- evoacme/files/evoacme.sh | 109 +++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/evoacme/files/evoacme.sh b/evoacme/files/evoacme.sh index 0504567e..56f3f0e5 100755 --- a/evoacme/files/evoacme.sh +++ b/evoacme/files/evoacme.sh @@ -7,8 +7,10 @@ # Licence: AGPLv3 # +set -e + usage() { - echo "Usage: $0 NAME" + echo "Usage: $0 [ --cron ] NAME" echo "" echo "NAME must be correspond to :" echo "- a CSR in ${CSR_DIR}/NAME.csr" @@ -17,68 +19,97 @@ usage() { } mkconf_apache() { - [ -f "/etc/apache2/ssl/${vhost}.conf" ] && sed -i "s~^SSLCertificateFile.*$~SSLCertificateFile $CRT_DIR/${vhost}/live/fullchain.pem~" "/etc/apache2/ssl/${vhost}.conf" - apache2ctl -t 2>/dev/null && service apache2 reload + echo "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() { - [ -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 2>/dev/null && service nginx reload -} - -mkconf_haproxy() { - mkdir -p /etc/ssl/haproxy -m 700 - cat "$CRT_DIR/${vhost}/live/fullchain.pem" "$SSL_KEY_DIR/${vhost}.key" > "/etc/ssl/haproxy/${vhost}.pem" - [ -f "$DH_DIR/${vhost}.pem" ] && cat "$DH_DIR/${vhost}.pem" >> "/etc/ssl/haproxy/${vhost}.pem" - haproxy -c -f /etc/haproxy/haproxy.cfg >/dev/null && service haproxy reload + echo "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 "${CRT_DIR}" ] && CRT_DIR='/etc/letsencrypt' - [ -z "${CSR_DIR}" ] && CSR_DIR='/etc/ssl/requests' - [ -z "${SELF_SIGNED_DIR}" ] && SELF_SIGNED_DIR='/etc/ssl/self-signed' - [ -z "${DH_DIR}" ] && DH_DIR='/etc/ssl/dhparam' - [ -z "${LOG_DIR}" ] && LOG_DIR='/var/log/evoacme' - - [ "$#" -ne 1 ] && usage && exit 1 + [ -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 - vhost=$(basename "$1" .conf) + # misc verifications + [ "$1" = "-h" ] || [ "$1" = "--help" ] && usage && exit 0 + which openssl >/dev/null || ( echo "error: openssl command not installed" && exit 1 ) + which certbot >/dev/null || ( echo "error: certbot command not installed" && exit 1 ) + [ ! -d $ACME_DIR ] && echo "error: $ACME_DIR is not a directory" && exit 1 + [ ! -d $CSR_DIR ] && echo "error: $CSR_DIR is not a directory" && exit 1 + [ ! -d $LOG_DIR ] && echo "error: $LOG_DIR is not a directory" && exit 1 + [ "$#" -ge 3 ] || [ "$#" -le 0 ] && echo "error: invalid argument(s)" && usage && exit 1 + [ "$#" -eq 2 ] && [ "$1" != "--cron" ] && echo "error: invalid argument(s)" && usage && exit 1 - # Check master status for evoadmin-cluster + [ "$#" -eq 1 ] && vhost=$(basename "$1" .conf) && CRON=NO + [ "$#" -eq 2 ] && vhost=$(basename "$2" .conf) && CRON=YES + + # verify .csr file + test ! -f "$CSR_DIR/${vhost}.csr" && echo "error: $CSR_DIR/${vhost}.csr absent" && exit 1 + test ! -r "$CSR_DIR/${vhost}.csr" && echo "error: $CSR_DIR/${vhost}.csr is not readable" && exit 1 + openssl req -noout -modulus -in "$CSR_DIR/${vhost}.csr" >/dev/null || ( echo "error: $CSR_DIR/${vhost}.csr is invalid" && exit 1 ) + [ "$CRON" = "NO" ] && echo "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 - SSL_EMAIL=$(grep emailAddress "${CRT_DIR}/openssl.cnf"|cut -d'=' -f2|xargs) if [ -n "$SSL_EMAIL" ]; then emailopt="-m $SSL_EMAIL" else emailopt="--register-unsafely-without-email" fi + DATE=$(date "+%Y%m%d") - + [ ! -n "$DATE" ] && echo "error: invalid date" && exit 1 + + + # If live link already exists, it's not our first time... if [ -h "$CRT_DIR/${vhost}/live" ]; then - crt_end_date=$(openssl x509 -noout -enddate -in "$CRT_DIR/${vhost}/live/cert.crt"|sed -e "s/.*=//") - date_crt=$(date -ud "$crt_end_date" +"%s") + openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/live/cert.crt" >/dev/null || ( echo "error: $CRT_DIR/${vhost}/live/cert.crt is invalid" && exit 1 ) + + # 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_diff=$(((date_crt - date_today) / (60*60*24))) - [ "$date_diff" -ge "$SSL_MINDAY" ] && exit 0 - fi - rm -rf "$CRT_DIR/${vhost}/${DATE}" - mkdir -pm 755 "$CRT_DIR/${vhost}/${DATE}" - chown -R acme: "$CRT_DIR/${vhost}" - sudo -u acme certbot certonly --quiet --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" - if [ -f "$CRT_DIR/${vhost}/${DATE}/fullchain.pem" ]; then - rm -f "$CRT_DIR/${vhost}/live" - ln -s "$CRT_DIR/${vhost}/${DATE}" "$CRT_DIR/${vhost}/live" + [ "$date_today" -lt "$date_renew" ] && ( [ "$CRON" = "NO" ] && echo "Cert $CRT_DIR/${vhost}/live/cert.crt expires at $crt_end_date => more than $SSL_MINDAY days: thxbye." || true ) && exit 0 + else which apache2ctl >/dev/null && mkconf_apache which nginx >/dev/null && mkconf_nginx - which haproxy >/dev/null && mkconf_haproxy - else - rmdir "$CRT_DIR/${vhost}/${DATE}" fi + + # renew certificate with certbot + [ -d "$CRT_DIR/${vhost}/${DATE}" ] && echo "error: $CRT_DIR/${vhost}/${DATE} directory already exists, remove it manually." && exit 1 + 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 || ( echo "error: new $CRT_DIR/${vhost}/${DATE}/cert.crt is invalid" && exit 1 ) + openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/${DATE}/fullchain.pem" >/dev/null || ( echo "error: new $CRT_DIR/${vhost}/${DATE}/fullchain.pem is invalid" && exit 1 ) + openssl x509 -noout -modulus -in "$CRT_DIR/${vhost}/${DATE}/chain.pem" >/dev/null || ( echo "error: new $CRT_DIR/${vhost}/${DATE}/chain.pem is invalid" && exit 1 ) + + # 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 || ( echo "error: new $CRT_DIR/{vhost}/live/cert.crt is invalid" && exit 1 ) + + # reload apache or nginx (TODO: need improvments) + pidof apache2 >/dev/null && apache2ctl -t 2>/dev/null && ( [ "$CRON" = "NO" ] && echo "Apache detected... reloading" || true ) && systemctl reload apache2 + pidof nginx >/dev/null && nginx -t 2>/dev/null && ( [ "$CRON" = "NO" ] && echo "Nginx detected... reloading" || true ) && systemctl reload apache2 + } main "$@"