From 46b2d2cae8ae8ba49a075d3185109cfa7f677cad Mon Sep 17 00:00:00 2001 From: Andrea Dell'Amico Date: Fri, 22 Apr 2016 18:01:58 +0200 Subject: [PATCH] library/roles/haproxy: Fixes to the letsencrypt scripts. d4science-infrastructure/roles/redmine: support letsencrypt certificates on the dev redmine virtualhost. library/roles/apache/tasks/apache-letsencrypt.yml: Support for letsencrypt (acme tool). library/roles/ubuntu-deb-general/tasks/pki-basics.yml: Do not create the fake certificates if valid ones exist. --- apache/defaults/main.yml | 7 ++++ apache/files/apache-letsencrypt-acme.sh | 26 ++++++++++++++ apache/tasks/apache-letsencrypt.yml | 35 +++++++++++++++++++ apache/tasks/main.yml | 2 ++ apache/templates/letsencrypt-proxy.conf.j2 | 1 + haproxy/files/haproxy-letsencrypt-acme.sh | 7 +++- .../tasks/haproxy-letsencrypt-acmetool.yml | 7 ++++ letsencrypt-acmetool-client/tasks/main.yml | 4 +-- ubuntu-deb-general/tasks/pki-basics.yml | 23 ++++++------ 9 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 apache/files/apache-letsencrypt-acme.sh create mode 100644 apache/tasks/apache-letsencrypt.yml create mode 100644 apache/templates/letsencrypt-proxy.conf.j2 diff --git a/apache/defaults/main.yml b/apache/defaults/main.yml index b30d6c7..297e100 100644 --- a/apache/defaults/main.yml +++ b/apache/defaults/main.yml @@ -72,3 +72,10 @@ apache_additional_modules: False apache_additional_modules_list: # - # - + +apache_letsencrypt_proxy_modules: + - proxy + - proxy_http + +apache_letsencrypt_proxy_conf: + - letsencrypt-proxy.conf diff --git a/apache/files/apache-letsencrypt-acme.sh b/apache/files/apache-letsencrypt-acme.sh new file mode 100644 index 0000000..968140e --- /dev/null +++ b/apache/files/apache-letsencrypt-acme.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +LE_SERVICES_SCRIPT_DIR=/usr/lib/acme/hooks +LE_CERTS_DIR=/var/lib/acme/live/$HOSTNAME +LE_LOG_DIR=/var/log/letsencrypt +DATE=$( date ) + +[ ! -d $LE_LOG_DIR ] && mkdir $LE_LOG_DIR +echo "$DATE" >> $LE_LOG_DIR/apache.log + +if [ -f /etc/default/letsencrypt ] ; then + . /etc/default/letsencrypt +else + echo "No letsencrypt default file" >> $LE_LOG_DIR/apache.log +fi + +echo "Reload the apache service" >> $LE_LOG_DIR/apache.log +if [ -x /bin/systemctl ] ; then + systemctl reload apache2 >> $LE_LOG_DIR/apache.log 2>&1 +else + service apache2 reload >> $LE_LOG_DIR/apache.log 2>&1 +fi + +echo "Done." >> $LE_LOG_DIR/apache.log + +exit 0 diff --git a/apache/tasks/apache-letsencrypt.yml b/apache/tasks/apache-letsencrypt.yml new file mode 100644 index 0000000..d8a1cb4 --- /dev/null +++ b/apache/tasks/apache-letsencrypt.yml @@ -0,0 +1,35 @@ +--- +- block: + - name: Enable the proxy modules needed by letsencrypt + apache2_module: name={{ item }} state=present + notify: apache2 reload + with_items: '{{ apache_letsencrypt_proxy_modules }}' + + - name: Install the letsencrypt conf + template: src=letsencrypt-proxy.conf.j2 dest=/etc/apache2/conf-available/letsencrypt-proxy.conf owner=root group=root mode=0644 + notify: apache2 reload + + - name: Enable the letsencrypt conf + file: src=/etc/apache2/conf-available/letsencrypt-proxy.conf dest=/etc/apache2/conf-enabled/letsencrypt-proxy.conf state=link + notify: apache2 reload + + - name: Create the acme hooks directory if it does not yet exist + file: dest={{ letsencrypt_acme_services_scripts_dir }} state=directory owner=root group=root + + - name: Install a letsencrypt hook for apache + copy: src=apache-letsencrypt-acme.sh dest={{ letsencrypt_acme_services_scripts_dir }}/apache2 owner=root group=root mode=4555 + + when: letsencrypt_acme_install is defined and letsencrypt_acme_install + tags: [ 'apache', 'letsencrypt' ] + +- block: + - name: Disable the letsencrypt conf + file: dest=/etc/apache2/conf-enabled/letsencrypt-proxy.conf state=absent + notify: apache2 reload + + - name: Remove the letsencrypt hook for apache + file: path={{ letsencrypt_acme_services_scripts_dir }}/apache2 state=absent + + when: ( letsencrypt_acme_install is defined ) and ( not letsencrypt_acme_install ) + tags: [ 'apache', 'apache_mods', 'letsencrypt' ] + diff --git a/apache/tasks/main.yml b/apache/tasks/main.yml index ce8c9d6..a3d5e85 100644 --- a/apache/tasks/main.yml +++ b/apache/tasks/main.yml @@ -3,3 +3,5 @@ - include: apache-modules.yml - include: apache-basic-auth.yml when: apache_basic_auth +- include: apache-letsencrypt.yml + when: letsencrypt_acme_install is defined and letsencrypt_acme_install diff --git a/apache/templates/letsencrypt-proxy.conf.j2 b/apache/templates/letsencrypt-proxy.conf.j2 new file mode 100644 index 0000000..4dddd47 --- /dev/null +++ b/apache/templates/letsencrypt-proxy.conf.j2 @@ -0,0 +1 @@ +ProxyPass "/.well-known/acme-challenge" "http://127.0.0.1:{{ letsencrypt_acme_standalone_port}}/.well-known/acme-challenge" diff --git a/haproxy/files/haproxy-letsencrypt-acme.sh b/haproxy/files/haproxy-letsencrypt-acme.sh index 17dbc17..7b9d4ad 100644 --- a/haproxy/files/haproxy-letsencrypt-acme.sh +++ b/haproxy/files/haproxy-letsencrypt-acme.sh @@ -23,7 +23,12 @@ chmod 440 ${HAPROXY_CERTFILE} chgrp haproxy ${HAPROXY_CERTFILE} echo "Reload the haproxy service" >> $LE_LOG_DIR/haproxy.log -service haproxy reload >/dev/null 2>&1 +if [ -x /bin/systemctl ] ; then + systemctl reload haproxy >> $LE_LOG_DIR/haproxy.log 2>&1 +else + service haproxy reload >> $LE_LOG_DIR/haproxy.log 2>&1 +fi + echo "Done." >> $LE_LOG_DIR/haproxy.log exit 0 diff --git a/haproxy/tasks/haproxy-letsencrypt-acmetool.yml b/haproxy/tasks/haproxy-letsencrypt-acmetool.yml index 67b0ced..857fb3a 100644 --- a/haproxy/tasks/haproxy-letsencrypt-acmetool.yml +++ b/haproxy/tasks/haproxy-letsencrypt-acmetool.yml @@ -1,4 +1,11 @@ --- +- name: Create the acme hooks directory if it does not yet exist + file: dest={{ letsencrypt_acme_services_scripts_dir }} state=directory owner=root group=root + when: + - haproxy_letsencrypt_managed + - letsencrypt_acme_install + tags: [ 'haproxy', 'letsencrypt' ] + - name: Install a script that fix the letsencrypt certificate for haproxy and then reload the service copy: src=haproxy-letsencrypt-acme.sh dest={{ letsencrypt_acme_services_scripts_dir }}/haproxy owner=root group=root mode=4555 when: diff --git a/letsencrypt-acmetool-client/tasks/main.yml b/letsencrypt-acmetool-client/tasks/main.yml index 3eb0a2c..150499c 100644 --- a/letsencrypt-acmetool-client/tasks/main.yml +++ b/letsencrypt-acmetool-client/tasks/main.yml @@ -103,11 +103,11 @@ cron: name="Letsencrypt certificate renewal" special_time=daily job="{{ letsencrypt_acme_command }} {{ letsencrypt_acme_command_opts }} reconcile > {{ letsencrypt_acme_log_dir }}/acme-cron.log 2>&1" user={{ letsencrypt_acme_user }} when: letsencrypt_acme_install tags: letsencrypt - + - name: letsencrypt acmetool initializaztion become: True become_user: '{{ letsencrypt_acme_user }}' - command: '{{ letsencrypt_acme_command }} {{ letsencrypt_acme_command_opts }} quickstart' + shell: 'rm -fr {{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert ; rm -fr {{ letsencrypt_acme_user_home }}/keys/fakeselfsigned/cert ; rm {{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }} ; {{ letsencrypt_acme_command }} {{ letsencrypt_acme_command_opts }} quickstart' args: creates: '{{ letsencrypt_acme_user_home }}/accounts' when: letsencrypt_acme_install diff --git a/ubuntu-deb-general/tasks/pki-basics.yml b/ubuntu-deb-general/tasks/pki-basics.yml index 913d0f3..3e892a3 100644 --- a/ubuntu-deb-general/tasks/pki-basics.yml +++ b/ubuntu-deb-general/tasks/pki-basics.yml @@ -8,44 +8,45 @@ with_items: '{{ pki_subdirs }}' tags: [ 'pki', 'ssl', 'letsencrypt' ] +- name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Check if a certificate already exists. If so, skip all the related tasks + stat: path={{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }} + register: true_cert + when: letsencrypt_acme_install is defined and letsencrypt_acme_install + tags: [ 'pki', 'ssl', 'letsencrypt' ] + - name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now the physical paths file: path={{ item }} mode=0755 state=directory with_items: - '{{ letsencrypt_acme_user_home }}/live' - '{{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert' - '{{ letsencrypt_acme_user_home }}/keys/fakeselfsignedcert' - when: letsencrypt_acme_install is defined and letsencrypt_acme_install + when: ( true_cert.stat.islnk is not defined ) and ( letsencrypt_acme_install is defined and letsencrypt_acme_install ) tags: [ 'pki', 'ssl', 'letsencrypt' ] - name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now the certificate and private key command: openssl req -x509 -newkey rsa:2048 -keyout {{ letsencrypt_acme_user_home }}/keys/fakeselfsignedcert/privkey -out {{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert/cert -days 10 -nodes -subj '/CN=self signed certificate' args: creates: '{{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert/cert' - when: letsencrypt_acme_install is defined and letsencrypt_acme_install + when: ( true_cert.stat.islnk is not defined ) and ( letsencrypt_acme_install is defined and letsencrypt_acme_install ) tags: [ 'pki', 'ssl', 'letsencrypt' ] - name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now the symbolic links for the private key file: src={{ letsencrypt_acme_user_home }}/keys/fakeselfsignedcert/privkey dest={{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert/privkey state=link - when: letsencrypt_acme_install is defined and letsencrypt_acme_install + when: ( true_cert.stat.islnk is not defined ) and ( letsencrypt_acme_install is defined and letsencrypt_acme_install ) tags: [ 'pki', 'ssl', 'letsencrypt' ] - name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now the symbolic links for the chain file file: src={{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert/cert dest={{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert/chain state=link - when: letsencrypt_acme_install is defined and letsencrypt_acme_install + when: ( true_cert.stat.islnk is not defined ) and ( letsencrypt_acme_install is defined and letsencrypt_acme_install ) tags: [ 'pki', 'ssl', 'letsencrypt' ] -- name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Check if a certificate already exists - stat: path={{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }} - register: true_cert - tags: [ 'pki', 'ssl', 'letsencrypt' ] - - name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now the symbolic links for the certificate if there is not one file: src={{ letsencrypt_acme_user_home }}/certs/fakeselfsignedcert dest={{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }} state=link - when: true_cert.stat.islnk is defined and true_cert.stat.islnk == False + when: ( true_cert.stat.islnk is not defined ) and ( letsencrypt_acme_install is defined and letsencrypt_acme_install ) tags: [ 'pki', 'ssl', 'letsencrypt' ] - name: When we are going to install letsencrypt certificates, create a preliminary path and a self signed cert. Now handle the haproxy special case - command: mkdir {{ pki_dir }}/haproxy ; cat {{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }}/privkey {{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }}/cert > {{ pki_dir }}/haproxy/haproxy.pem + shell: mkdir {{ pki_dir }}/haproxy ; cat {{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }}/privkey {{ letsencrypt_acme_user_home }}/live/{{ ansible_fqdn }}/cert > {{ pki_dir }}/haproxy/haproxy.pem args: creates: '{{ pki_dir }}/haproxy/haproxy.pem' when: