From 5756978238ad7b7f2fe8dc46d511cfbd5245c0c3 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Wed, 16 Aug 2023 23:38:07 +0200 Subject: uacme roles almost done --- roles/x509/uacme/base/defaults/main.yml | 2 + roles/x509/uacme/base/tasks/main.yml | 11 +++-- roles/x509/uacme/base/tasks/selfsigned.yml | 47 ---------------------- .../uacme/base/templates/uacme-reconcile.sh.j2 | 32 +++++++++++++++ 4 files changed, 41 insertions(+), 51 deletions(-) delete mode 100644 roles/x509/uacme/base/tasks/selfsigned.yml create mode 100644 roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 (limited to 'roles/x509/uacme/base') diff --git a/roles/x509/uacme/base/defaults/main.yml b/roles/x509/uacme/base/defaults/main.yml index 50ac8019..264bc2d9 100644 --- a/roles/x509/uacme/base/defaults/main.yml +++ b/roles/x509/uacme/base/defaults/main.yml @@ -4,3 +4,5 @@ uacme_directory_server: "{{ acme_directory_server }}" ### this defaults to '/var/run/acme/acme-challenge' # uacme_challenge_webroot_path: "/path/to/acme-challenge" + +# uacme_eab: :base64() diff --git a/roles/x509/uacme/base/tasks/main.yml b/roles/x509/uacme/base/tasks/main.yml index 3d1c8404..9d67e0e7 100644 --- a/roles/x509/uacme/base/tasks/main.yml +++ b/roles/x509/uacme/base/tasks/main.yml @@ -7,7 +7,7 @@ state: present - name: create acme account key - command: "uacme -c /var/lib/uacme.d -a '{{ uacme_directory_server }}' -y new '{{ uacme_account_email }}'" + command: "uacme -c /var/lib/uacme.d -a '{{ uacme_directory_server }}' -y{% if uacme_eab is defined %} -e {{ uacme_eab }}{% endif %} new '{{ uacme_account_email }}'" args: creates: /var/lib/uacme.d/private/key.pem @@ -44,7 +44,10 @@ alias {{ uacme_challenge_webroot_path | default('/var/run/acme/acme-challenge') }}/; } -- name: generate selfsigned interim certificate - include_tasks: selfsigned.yml +- name: install reconcile script + template: + src: uacme-reconcile.sh.j2 + dest: /usr/local/bin/uacme-reconcile.sh + mode: 0755 -## TODO: add global automatic refresher? +## TODO: add systemd units for automatic refreshing diff --git a/roles/x509/uacme/base/tasks/selfsigned.yml b/roles/x509/uacme/base/tasks/selfsigned.yml deleted file mode 100644 index fff77d42..00000000 --- a/roles/x509/uacme/base/tasks/selfsigned.yml +++ /dev/null @@ -1,47 +0,0 @@ ---- -- name: create directories for selfsigned interim certificate - loop: - - path: private/.self-signed - mode: "0700" - - path: .self-signed - mode: "0755" - loop_control: - label: "{{ item.path }}" - file: - path: "/var/lib/uacme.d/{{ item.path }}" - state: directory - mode: "{{ item.mode }}" - -- name: generate private key for selfsigned interim certificate - openssl_privatekey: - path: /var/lib/uacme.d/private/.self-signed/key.pem - mode: 0600 - -- name: generate csr for selfsigned interim certificate - community.crypto.openssl_csr_pipe: - privatekey_path: /var/lib/uacme.d/private/.self-signed/key.pem - common_name: "{{ ansible_fqdn }}" - register: selfsigned_interim_cert_req - changed_when: false - -### this is needed because strftime filter in ansible is exceptionally stupid -### see: https://github.com/ansible/ansible/issues/39835 -- name: get remote date-time 10s ago - command: date -d '10 seconds ago' -u '+%Y%m%d%H%M%SZ' - register: remote_datetime_10sago - changed_when: false - -- name: get remote date-time now - command: date -u '+%Y%m%d%H%M%SZ' - register: remote_datetime_now - changed_when: false - -- name: generate selfsigned interim certificate - community.crypto.x509_certificate: - path: /var/lib/uacme.d/.self-signed/cert.pem - privatekey_path: /var/lib/uacme.d/private/.self-signed/key.pem - csr_content: "{{ selfsigned_interim_cert_req.csr }}" - provider: selfsigned - ## make sure the certificate is not valid anymore to force uacme to create a new cert - selfsigned_not_before: "{{ remote_datetime_10sago.stdout }}" - selfsigned_not_after: "{{ remote_datetime_now.stdout }}" diff --git a/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 b/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 new file mode 100644 index 00000000..73a7f4a3 --- /dev/null +++ b/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 @@ -0,0 +1,32 @@ +#!/bin/bash + +declare -a csr_files +if [ -n "$1" ]; then + csr_files+=("/var/lib/uacme.d/$1/$1.csr") +else + readarray -d '' csr_files < <(find /var/lib/uacme.d -name "*.csr" -print0) +fi + +export UACME_CHALLENGE_PATH="{{ uacme_challenge_webroot_path | default('/var/run/acme/acme-challenge') }}" + +failed=0 +for csr_file in "${csr_files[@]}"; do + id=$(basename -s .csr "$csr_file") + uacme -c /var/lib/uacme.d -a "{{ uacme_directory_server }}" -h /usr/share/uacme/uacme.sh -n issue "$csr_file" + case $? in + 0) + echo "$id successfully (re)issued." + awk '{if(length($0) > 0) print} /-----END CERTIFICATE-----/ { exit }' "/var/lib/uacme.d/$id/$id-cert.pem" > "/var/lib/uacme.d/$id/crt.pem" + awk '(show==1) {if(length($0) > 0) print} /-----END CERTIFICATE-----/ { show=1 }' "/var/lib/uacme.d/$id/$id-cert.pem" > "/var/lib/uacme.d/$id/chain.pem" + ## TODO: reload services + ;; + 1) + echo "$id not updated." + ;; + *) + failed=1 + ;; + esac +done + +exit $failed -- cgit v1.2.3 From 775492cc28346ea86396a947e1371b8aa0784380 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Thu, 17 Aug 2023 00:23:01 +0200 Subject: revamp x509 service reloading --- roles/nginx/vhost/tasks/main.yml | 16 +++++++++------- roles/x509/acmetool/cert/prepare/handlers/main.yml | 6 ++++++ roles/x509/acmetool/cert/prepare/tasks/main.yml | 1 + roles/x509/selfsigned/cert/prepare/handlers/main.yml | 6 ++++++ roles/x509/selfsigned/cert/prepare/tasks/main.yml | 6 +++--- roles/x509/static/cert/prepare/handlers/main.yml | 6 ++++++ roles/x509/static/cert/prepare/tasks/main.yml | 12 ++++++------ roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 | 6 +++--- roles/x509/uacme/cert/prepare/handlers/main.yml | 6 ++++++ roles/x509/uacme/cert/prepare/tasks/main.yml | 14 ++++++++++---- roles/x509/uacme/cert/prepare/templates/updated.sh.j2 | 17 +++++++++++++++++ 11 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 roles/x509/acmetool/cert/prepare/handlers/main.yml create mode 100644 roles/x509/selfsigned/cert/prepare/handlers/main.yml create mode 100644 roles/x509/static/cert/prepare/handlers/main.yml create mode 100644 roles/x509/uacme/cert/prepare/handlers/main.yml create mode 100644 roles/x509/uacme/cert/prepare/templates/updated.sh.j2 (limited to 'roles/x509/uacme/base') diff --git a/roles/nginx/vhost/tasks/main.yml b/roles/nginx/vhost/tasks/main.yml index 55544733..2c1f0f29 100644 --- a/roles/nginx/vhost/tasks/main.yml +++ b/roles/nginx/vhost/tasks/main.yml @@ -1,13 +1,14 @@ --- - name: ensure certificate exists (fake it, until you make it) when: "'tls' in nginx_vhost" - include_role: - name: "x509/{{ nginx_vhost.tls.certificate_provider }}/cert/prepare" - public: true vars: x509_certificate_name: "{{ nginx_vhost.name }}" x509_certificate_hostnames: "{{ nginx_vhost.hostnames }}" - x509_notify_on_change: reload nginx + x509_certificate_reload_services: + - nginx + include_role: + name: "x509/{{ nginx_vhost.tls.certificate_provider }}/cert/prepare" + public: true - name: install nginx configs from template when: "'template' in nginx_vhost" @@ -39,9 +40,10 @@ meta: flush_handlers - name: actually request the certificate - include_role: - name: "x509/{{ nginx_vhost.tls.certificate_provider }}/cert/finalize" vars: x509_certificate_name: "{{ nginx_vhost.name }}" x509_certificate_hostnames: "{{ nginx_vhost.hostnames }}" - x509_notify_on_change: reload nginx + x509_certificate_reload_services: + - nginx + include_role: + name: "x509/{{ nginx_vhost.tls.certificate_provider }}/cert/finalize" diff --git a/roles/x509/acmetool/cert/prepare/handlers/main.yml b/roles/x509/acmetool/cert/prepare/handlers/main.yml new file mode 100644 index 00000000..b169d6ca --- /dev/null +++ b/roles/x509/acmetool/cert/prepare/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: reload services for x509 certificates + loop: "{{ x509_certificate_reload_services | default([]) }}" + service: + name: "{{ item }}" + state: reloaded diff --git a/roles/x509/acmetool/cert/prepare/tasks/main.yml b/roles/x509/acmetool/cert/prepare/tasks/main.yml index 146c5ac4..5bad1e5b 100644 --- a/roles/x509/acmetool/cert/prepare/tasks/main.yml +++ b/roles/x509/acmetool/cert/prepare/tasks/main.yml @@ -32,6 +32,7 @@ src: "../certs/{{ selfsigned_interim_cert_id }}" dest: "/var/lib/acme/live/{{ acme_missing_hostname }}" state: link + notify: reload services for x509 certificates - name: export paths to certificate files set_fact: diff --git a/roles/x509/selfsigned/cert/prepare/handlers/main.yml b/roles/x509/selfsigned/cert/prepare/handlers/main.yml new file mode 100644 index 00000000..b169d6ca --- /dev/null +++ b/roles/x509/selfsigned/cert/prepare/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: reload services for x509 certificates + loop: "{{ x509_certificate_reload_services | default([]) }}" + service: + name: "{{ item }}" + state: reloaded diff --git a/roles/x509/selfsigned/cert/prepare/tasks/main.yml b/roles/x509/selfsigned/cert/prepare/tasks/main.yml index 1af6ef5e..e7a47742 100644 --- a/roles/x509/selfsigned/cert/prepare/tasks/main.yml +++ b/roles/x509/selfsigned/cert/prepare/tasks/main.yml @@ -10,7 +10,7 @@ mode: "{{ selfsigned_cert_config.mode | default('0700') }}" owner: "{{ selfsigned_cert_config.owner | default(omit) }}" group: "{{ selfsigned_cert_config.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: generate key for selfsigned certificate openssl_privatekey: @@ -20,7 +20,7 @@ group: "{{ selfsigned_cert_config.key.group | default(omit) }}" type: "{{ selfsigned_cert_config.key.type | default(omit) }}" size: "{{ selfsigned_cert_config.key.size | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: generate csr for selfsigned certificate community.crypto.openssl_csr: @@ -59,7 +59,7 @@ selfsigned_digest: "{{ selfsigned_cert_config.cert.digest | default(omit) }}" selfsigned_not_before: "{{ selfsigned_cert_config.cert.not_before | default(omit) }}" selfsigned_not_after: "{{ selfsigned_cert_config.cert.not_after | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: export paths to certificate files set_fact: diff --git a/roles/x509/static/cert/prepare/handlers/main.yml b/roles/x509/static/cert/prepare/handlers/main.yml new file mode 100644 index 00000000..b169d6ca --- /dev/null +++ b/roles/x509/static/cert/prepare/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: reload services for x509 certificates + loop: "{{ x509_certificate_reload_services | default([]) }}" + service: + name: "{{ item }}" + state: reloaded diff --git a/roles/x509/static/cert/prepare/tasks/main.yml b/roles/x509/static/cert/prepare/tasks/main.yml index 1327c3b3..03df7542 100644 --- a/roles/x509/static/cert/prepare/tasks/main.yml +++ b/roles/x509/static/cert/prepare/tasks/main.yml @@ -10,7 +10,7 @@ mode: "{{ static_cert_config.mode | default('0700') }}" owner: "{{ static_cert_config.owner | default(omit) }}" group: "{{ static_cert_config.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: install key for static certificate copy: @@ -19,7 +19,7 @@ mode: "{{ static_cert_config.key.mode | default('0600') }}" owner: "{{ static_cert_config.key.owner | default(omit) }}" group: "{{ static_cert_config.key.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: install static certificate copy: @@ -28,7 +28,7 @@ mode: "{{ static_cert_config.cert.mode | default('0644') }}" owner: "{{ static_cert_config.cert.owner | default(omit) }}" group: "{{ static_cert_config.cert.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: export paths to basic certificate files set_fact: @@ -46,7 +46,7 @@ mode: "{{ static_cert_config.chain.mode | default('0644') }}" owner: "{{ static_cert_config.chain.owner | default(omit) }}" group: "{{ static_cert_config.chain.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: install fullchain for static certificate copy: @@ -57,7 +57,7 @@ mode: "{{ static_cert_config.cert.mode | default('0644') }}" owner: "{{ static_cert_config.cert.owner | default(omit) }}" group: "{{ static_cert_config.cert.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: export paths to additional certificate files set_fact: @@ -74,7 +74,7 @@ file: path: "{{ static_cert_path }}/{{ static_cert_name }}-{{ item }}.pem" state: absent - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: make sure variable that points to the chain certificate file is unset set_fact: diff --git a/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 b/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 index 73a7f4a3..ea02841d 100644 --- a/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 +++ b/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 @@ -16,9 +16,9 @@ for csr_file in "${csr_files[@]}"; do case $? in 0) echo "$id successfully (re)issued." - awk '{if(length($0) > 0) print} /-----END CERTIFICATE-----/ { exit }' "/var/lib/uacme.d/$id/$id-cert.pem" > "/var/lib/uacme.d/$id/crt.pem" - awk '(show==1) {if(length($0) > 0) print} /-----END CERTIFICATE-----/ { show=1 }' "/var/lib/uacme.d/$id/$id-cert.pem" > "/var/lib/uacme.d/$id/chain.pem" - ## TODO: reload services + if [ -x "/var/lib/uacme.d/$id/updated.sh" ]; then + /var/lib/uacme.d/$id/updated.sh + fi ;; 1) echo "$id not updated." diff --git a/roles/x509/uacme/cert/prepare/handlers/main.yml b/roles/x509/uacme/cert/prepare/handlers/main.yml new file mode 100644 index 00000000..b169d6ca --- /dev/null +++ b/roles/x509/uacme/cert/prepare/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: reload services for x509 certificates + loop: "{{ x509_certificate_reload_services | default([]) }}" + service: + name: "{{ item }}" + state: reloaded diff --git a/roles/x509/uacme/cert/prepare/tasks/main.yml b/roles/x509/uacme/cert/prepare/tasks/main.yml index 06b9f146..426a5eee 100644 --- a/roles/x509/uacme/cert/prepare/tasks/main.yml +++ b/roles/x509/uacme/cert/prepare/tasks/main.yml @@ -12,7 +12,7 @@ group: "{{ uacme_cert_config.key.group | default(omit) }}" type: "{{ uacme_cert_config.key.type | default(omit) }}" size: "{{ uacme_cert_config.key.size | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: generate csr for uacme-controlled certificate community.crypto.openssl_csr: @@ -60,7 +60,7 @@ selfsigned_not_after: "{{ remote_datetime_now.stdout }}" return_content: yes register: uacme_cert_selfsigned - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: make sure cert-only file exists copy: @@ -69,7 +69,7 @@ mode: "{{ uacme_cert_config.cert.mode | default('0644') }}" owner: "{{ uacme_cert_config.cert.owner | default(omit) }}" group: "{{ uacme_cert_config.cert.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates - name: make sure the chain file exists copy: @@ -78,7 +78,13 @@ mode: "{{ uacme_cert_config.cert.mode | default('0644') }}" owner: "{{ uacme_cert_config.cert.owner | default(omit) }}" group: "{{ uacme_cert_config.cert.group | default(omit) }}" - notify: "{{ x509_notify_on_change | default(omit) }}" + notify: reload services for x509 certificates + +- name: install script to be called when new certificate is generated + template: + src: updated.sh.j2 + dest: "/var/lib/uacme.d/{{ uacme_cert_name }}/updated.sh" + mode: 0755 - name: export paths to certificate files set_fact: diff --git a/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 b/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 new file mode 100644 index 00000000..b0fa705a --- /dev/null +++ b/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 @@ -0,0 +1,17 @@ +#!/bin/sh + +# split fullchain and fix permissions +awk '{if(length($0) > 0) print} /-----END CERTIFICATE-----/ { exit }' "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem" > "/var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem" +awk '(show==1) {if(length($0) > 0) print} /-----END CERTIFICATE-----/ { show=1 }' "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem" > "/var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem" +chmod "{{ uacme_cert_config.cert.mode | default('0644') }}" /var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem /var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem /var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem +{% if uacme_cert_config.cert.owner is defined %} +chown "{{ uacme_cert_config.cert.owner }}" /var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem /var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem /var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem +{% endif %} +{% if uacme_cert_config.cert.group is defined %} +chgrp "{{ uacme_cert_config.cert.group }}" /var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem /var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem /var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem +{% endif %} + +## reload services +{% for service in (x509_certificate_reload_services | default([])) %} +systemctl reload "{{ service }}.service" +{% endfor %} -- cgit v1.2.3 From 2ae1b55727449c61b320703a11bc622ec76b579a Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Thu, 17 Aug 2023 00:38:13 +0200 Subject: uacme: add automatic refresh timer/service --- roles/x509/uacme/base/tasks/main.yml | 15 ++++++++++++++- .../uacme/base/templates/uacme-reconcile.service.j2 | 18 ++++++++++++++++++ .../x509/uacme/base/templates/uacme-reconcile.timer.j2 | 10 ++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 roles/x509/uacme/base/templates/uacme-reconcile.service.j2 create mode 100644 roles/x509/uacme/base/templates/uacme-reconcile.timer.j2 (limited to 'roles/x509/uacme/base') diff --git a/roles/x509/uacme/base/tasks/main.yml b/roles/x509/uacme/base/tasks/main.yml index 9d67e0e7..17e6034f 100644 --- a/roles/x509/uacme/base/tasks/main.yml +++ b/roles/x509/uacme/base/tasks/main.yml @@ -50,4 +50,17 @@ dest: /usr/local/bin/uacme-reconcile.sh mode: 0755 -## TODO: add systemd units for automatic refreshing +- name: install systemd unit for automatic refresh + loop: + - service + - timer + template: + src: "uacme-reconcile.{{ item }}.j2" + dest: "/etc/systemd/system/uacme-reconcile.{{ item }}" + +- name: make sure systemd timer for automatic refresh is enabled and started + systemd: + daemon_reload: yes + name: uacme-reconcile.timer + state: started + enabled: yes diff --git a/roles/x509/uacme/base/templates/uacme-reconcile.service.j2 b/roles/x509/uacme/base/templates/uacme-reconcile.service.j2 new file mode 100644 index 00000000..c2fe917a --- /dev/null +++ b/roles/x509/uacme/base/templates/uacme-reconcile.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=Reconcile Let's Encrypt certificates using uacme + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/uacme-reconcile.sh +TimeoutStartSec=5min +CapabilityBoundingSet=CAP_CHOWN CAP_NET_BIND_SERVICE +NoNewPrivileges=yes +PrivateTmp=yes +PrivateDevices=yes +ProtectSystem=strict +ReadWritePaths=/var/lib/uacme.d {{ uacme_challenge_webroot_path | default('/var/run/acme/acme-challenge') }} +ProtectHome=yes +ProtectKernelTunables=yes +ProtectControlGroups=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 diff --git a/roles/x509/uacme/base/templates/uacme-reconcile.timer.j2 b/roles/x509/uacme/base/templates/uacme-reconcile.timer.j2 new file mode 100644 index 00000000..6d37a162 --- /dev/null +++ b/roles/x509/uacme/base/templates/uacme-reconcile.timer.j2 @@ -0,0 +1,10 @@ +[Unit] +Description=Reconcile Let's Encrypt certificates using uacme + +[Timer] +OnCalendar=*-*-* 00,12:00:00 +RandomizedDelaySec=1h +Persistent=yes + +[Install] +WantedBy=timers.target -- cgit v1.2.3 From f2d4ce732249e8711fc807fecd25d8c43a88175c Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Mon, 21 Aug 2023 01:02:51 +0200 Subject: x509/uacme: add support for special renewal actions --- dan/sk-testvm.yml | 4 +-- roles/x509/uacme/base/tasks/main.yml | 5 ++++ roles/x509/uacme/cert/prepare/handlers/main.yml | 4 +++ roles/x509/uacme/cert/prepare/tasks/main.yml | 30 +++++++++++++++++----- .../uacme/cert/prepare/templates/updated.sh.j2 | 26 +++++++++++++++---- 5 files changed, 56 insertions(+), 13 deletions(-) (limited to 'roles/x509/uacme/base') diff --git a/dan/sk-testvm.yml b/dan/sk-testvm.yml index 698eb7de..70b6f336 100644 --- a/dan/sk-testvm.yml +++ b/dan/sk-testvm.yml @@ -11,8 +11,8 @@ - name: Payload Setup hosts: sk-testvm vars: - # acme_client: uacme - acme_client: acmetool + acme_client: uacme + # acme_client: acmetool cert_provider: "{{ acme_client }}" # cert_provider: static # cert_provider: selfsigned diff --git a/roles/x509/uacme/base/tasks/main.yml b/roles/x509/uacme/base/tasks/main.yml index 17e6034f..3473d541 100644 --- a/roles/x509/uacme/base/tasks/main.yml +++ b/roles/x509/uacme/base/tasks/main.yml @@ -58,6 +58,11 @@ src: "uacme-reconcile.{{ item }}.j2" dest: "/etc/systemd/system/uacme-reconcile.{{ item }}" +- name: create system unit snippet directory + file: + path: /etc/systemd/system/uacme-reconcile.service.d/ + state: directory + - name: make sure systemd timer for automatic refresh is enabled and started systemd: daemon_reload: yes diff --git a/roles/x509/uacme/cert/prepare/handlers/main.yml b/roles/x509/uacme/cert/prepare/handlers/main.yml index b169d6ca..330bcd11 100644 --- a/roles/x509/uacme/cert/prepare/handlers/main.yml +++ b/roles/x509/uacme/cert/prepare/handlers/main.yml @@ -1,4 +1,8 @@ --- +- name: reload systemd + systemd: + daemon_reload: yes + - name: reload services for x509 certificates loop: "{{ x509_certificate_reload_services | default([]) }}" service: diff --git a/roles/x509/uacme/cert/prepare/tasks/main.yml b/roles/x509/uacme/cert/prepare/tasks/main.yml index 426a5eee..a83651b3 100644 --- a/roles/x509/uacme/cert/prepare/tasks/main.yml +++ b/roles/x509/uacme/cert/prepare/tasks/main.yml @@ -80,15 +80,33 @@ group: "{{ uacme_cert_config.cert.group | default(omit) }}" notify: reload services for x509 certificates -- name: install script to be called when new certificate is generated - template: - src: updated.sh.j2 - dest: "/var/lib/uacme.d/{{ uacme_cert_name }}/updated.sh" - mode: 0755 - - name: export paths to certificate files set_fact: x509_certificate_path_key: "/var/lib/uacme.d/{{ uacme_cert_name }}/key.pem" x509_certificate_path_cert: "/var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem" x509_certificate_path_chain: "/var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem" x509_certificate_path_fullchain: "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem" + +- name: install script to be called when new certificate is generated + template: + src: updated.sh.j2 + dest: "/var/lib/uacme.d/{{ uacme_cert_name }}/updated.sh" + mode: 0755 + +- name: install systemd unit snippet + when: "x509_certificate_renewal is defined and 'install' in x509_certificate_renewal" + copy: + dest: "/etc/systemd/system/uacme-reconcile.service.d/{{ x509_certificate_name }}.conf" + content: | + [Service] + {% for path in (x509_certificate_renewal.install | map(attribute='dest') | map('dirname') | unique | list) %} + ReadWritePaths={{ path }} + {% endfor %} + notify: reload systemd + +- name: remove systemd unit snippet + when: "x509_certificate_renewal is undefined or 'install' not in x509_certificate_renewal" + file: + path: "/etc/systemd/system/uacme-reconcile.service.d/{{ x509_certificate_name }}.conf" + state: absent + notify: reload systemd diff --git a/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 b/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 index b0fa705a..275ca189 100644 --- a/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 +++ b/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 @@ -1,17 +1,33 @@ #!/bin/sh +BASE_D="/var/lib/uacme.d/{{ uacme_cert_name }}" + # split fullchain and fix permissions -awk '{if(length($0) > 0) print} /-----END CERTIFICATE-----/ { exit }' "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem" > "/var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem" -awk '(show==1) {if(length($0) > 0) print} /-----END CERTIFICATE-----/ { show=1 }' "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem" > "/var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem" -chmod "{{ uacme_cert_config.cert.mode | default('0644') }}" /var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem /var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem /var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem +awk '{if(length($0) > 0) print} /-----END CERTIFICATE-----/ { exit }' "$BASE_D/{{ uacme_cert_name }}-cert.pem" > "$BASE_D/crt.pem" +awk '(show==1) {if(length($0) > 0) print} /-----END CERTIFICATE-----/ { show=1 }' "$BASE_D/{{ uacme_cert_name }}-cert.pem" > "$BASE_D/chain.pem" +chmod "{{ uacme_cert_config.cert.mode | default('0644') }}" $BASE_D/{{ uacme_cert_name }}-cert.pem $BASE_D/crt.pem $BASE_D/chain.pem {% if uacme_cert_config.cert.owner is defined %} -chown "{{ uacme_cert_config.cert.owner }}" /var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem /var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem /var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem +chown "{{ uacme_cert_config.cert.owner }}" $BASE_D/{{ uacme_cert_name }}-cert.pem $BASE_D/crt.pem $BASE_D/chain.pem {% endif %} {% if uacme_cert_config.cert.group is defined %} -chgrp "{{ uacme_cert_config.cert.group }}" /var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem /var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem /var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem +chgrp "{{ uacme_cert_config.cert.group }}" $BASE_D/{{ uacme_cert_name }}-cert.pem $BASE_D/crt.pem $BASE_D/chain.pem +{% endif %} +{% if x509_certificate_renewal is defined and 'install' in x509_certificate_renewal %} +{% for file in x509_certificate_renewal.install %} + +install{% if 'mode' in file %} -m {{ file.mode }}{% endif %}{% if 'owner' in file %} -o {{ file.owner }}{% endif %}{% if 'owner' in file %} -g {{ file.group }}{% endif %} /dev/null "{{ file.dest }}.new" +{% for src in file.src %} +cat "{{ hostvars[inventory_hostname]['x509_certificate_path_' + src] }}" >> "{{ file.dest }}.new" +mv "{{ file.dest }}.new" "{{ file.dest }}" +{% endfor %} +{% endfor %} {% endif %} ## reload services {% for service in (x509_certificate_reload_services | default([])) %} systemctl reload "{{ service }}.service" {% endfor %} +{% if x509_certificate_renewal is defined and 'reload' in x509_certificate_renewal %} + +{{ x509_certificate_renewal.reload | trim }} +{% endif %} -- cgit v1.2.3