From 0b4624e8cae0f7a8893213a863ea713835125a78 Mon Sep 17 00:00:00 2001 From: Andrea Dell'Amico Date: Tue, 12 Apr 2016 19:40:28 +0200 Subject: [PATCH] library/roles/letsencrypt-client: Create a cli.ini, provide a script that manages the certs requests and renewal, cron job to automate the certs renewal. --- letsencrypt-client/defaults/main.yml | 23 +++++++++++++ letsencrypt-client/tasks/main.yml | 31 +++++++++++++++++ letsencrypt-client/templates/cli.ini.j2 | 11 ++++++ .../templates/letsencrypt-cert-request.sh.j2 | 34 +++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 letsencrypt-client/templates/cli.ini.j2 create mode 100644 letsencrypt-client/templates/letsencrypt-cert-request.sh.j2 diff --git a/letsencrypt-client/defaults/main.yml b/letsencrypt-client/defaults/main.yml index 73079c5..507b86c 100644 --- a/letsencrypt-client/defaults/main.yml +++ b/letsencrypt-client/defaults/main.yml @@ -7,3 +7,26 @@ letsencrypt_prerequisites: - git - bc +letsencrypt_auto: '{{ letsencrypt_dest_dir }}/letsencrypt/letsencrypt-auto' +letsencrypt_install_path: /root/.local/share/letsencrypt +letsencrypt_config_dir: /etc/letsencrypt +letsencrypt_certs_dir: '{{ letsencrypt_config_dir }}/{{ ansible_fqdn }}/live' +# In seconds. Default 7 days +letsencrypt_renew_before: 604800 +letsencrypt_logdir: /var/log/letsencrypt +# The various services maintainers need to put the reconfigure/restart scripts there +letsencrypt_services_scripts_dir: /usr/local/lib/letsencrypt + +# cli.ini parameters +letsencrypt_rsa_key_size: 4096 +letsencrypt_email: sysadmin@example.com +letsencrypt_authenticator: standalone +letsencrypt_standalone_supp_challenges: 'http-01' +letsencrypt_agree_tos: True +letsencrypt_verbose: False +letsencrypt_text_interface: True +# The first on the list gives the name to the certs live directory. +# If it is not the machine FQDN, change the letsencrypt_cert_dir definition. +letsencrypt_domains: '{{ ansible_fqdn }},example.com,example.org' +letsencrypt_renew_by_default: True +letsencrypt_standalone_port: 9999 diff --git a/letsencrypt-client/tasks/main.yml b/letsencrypt-client/tasks/main.yml index d429418..f838a1c 100644 --- a/letsencrypt-client/tasks/main.yml +++ b/letsencrypt-client/tasks/main.yml @@ -11,4 +11,35 @@ when: letsencrypt_install tags: letsencrypt +- name: letsencrypt initializaztion + command: '{{ letsencrypt_auto }}' + args: + creates: '{{ letsencrypt_install_path }}/bin/letsencrypt' + when: letsencrypt_install + tags: letsencrypt + +- name: Create the letsencrypt config directory + file: dest={{ letsencrypt_config_dir }} state=directory owner=root group=root mode=0755 + when: letsencrypt_install + tags: letsencrypt + +- name: Create the letsencrypt services scripts directory + file: dest={{ letsencrypt_services_scripts_dir }} state=directory owner=root group=root mode=0755 + when: letsencrypt_install + tags: letsencrypt + +- name: Install the letsencrypt cli.ini file + template: src=cli.ini.j2 dest={{ letsencrypt_config_dir }}/cli.ini owner=root group=root mode=0640 + when: letsencrypt_install + tags: letsencrypt + +- name: Install the command that asks for the certificates and their renewal + template: src=letsencrypt-cert-request.sh.j2 dest=/usr/local/sbin/letsencrypt-cert-request owner=root group=root mode=0550 + when: letsencrypt_install + tags: letsencrypt + +- name: Install a daily cron job to renew the certificates when needed + cron: name="Letsencrypt certificate renewal" special_time=daily job="/usr/local/sbin/letsencrypt-cert-request > {{ letsencrypt_logdir }}/letsencrypt-cert-cron.log 2>&1" + when: letsencrypt_install + tags: letsencrypt diff --git a/letsencrypt-client/templates/cli.ini.j2 b/letsencrypt-client/templates/cli.ini.j2 new file mode 100644 index 0000000..098c089 --- /dev/null +++ b/letsencrypt-client/templates/cli.ini.j2 @@ -0,0 +1,11 @@ +rsa-key-size = {{ letsencrypt_rsa_key_size }} +email = {{ letsencrypt_email }} +authenticator = {{ letsencrypt_authenticator }} +standalone-supported-challenges = {{ letsencrypt_standalone_supp_challenges }} +agree-tos = {{ letsencrypt_agree_tos }} +verbose = {{ letsencrypt_verbose }} +text = {{ letsencrypt_text_interface }} +domains = {{ letsencrypt_domains }} +renew-by-default = {{ letsencrypt_renew_by_default }} + + diff --git a/letsencrypt-client/templates/letsencrypt-cert-request.sh.j2 b/letsencrypt-client/templates/letsencrypt-cert-request.sh.j2 new file mode 100644 index 0000000..6ca753b --- /dev/null +++ b/letsencrypt-client/templates/letsencrypt-cert-request.sh.j2 @@ -0,0 +1,34 @@ +#!/bin/bash + +RENEW_BEFORE={{ letsencrypt_renew_before }} +LETSENCRYPT_BIN={{ letsencrypt_auto }} +LE_CERT_DIR={{ letsencrypt_certs_dir }} +LE_SERVICES_SCRIPT_DIR={{ letsencrypt_services_scripts_dir }} +LOG_DIR={{ letsencrypt_logdir }} +VALIDITY_RETVAL=0 +RETVAL=0 + +# Check if the cert file exists. If not, it is a certificate request and not a renewal. +if [ -f $LE_CERT_DIR/cert.pem ] ; then + VALIDITY_CHECK=$( openssl x509 -checkend $RENEW_BEFORE -noout -in $LE_CERT_DIR/cert.pem ) + VALIDITY_RETVAL=$? + if [ $VALIDITY_RETVAL -eq 0 ] ; then + echo "The certificate is still valid" >> $LOG_DIR/letsencrypt_request.log + exit 0 + fi +fi + +# Ask for a new certificate. First request or renewal are the same. We only support the standalone method right now +$LETSENCRYPT_BIN certonly --http-01-port {{ letsencrypt_standalone_port }} --config /etc/letsencrypt/cli.ini >> $LOG_DIR/letsencrypt_request.log 2>&1 +RETVAL=$? + +# Run the reconfiguration scripts to make the involved services load the new certificate +for f in $( /bin/ls -1 $LE_SERVICES_SCRIPT_DIR ) ; do + if [ -x $f ] ; then + echo "Running $f" >> $LOG_DIR/letsencrypt_request.log + $f >> $LOG_DIR/letsencrypt_request.log 2>&1 + fi +done + +exit 0 +