Use handlers for letsencrypt cert updates
This change proposes calling a handler each time a certificate is created/updated. The handler name is based on the name of the certificate given in the letsencrypt_certs variable, as described in the role documentation. Because Ansible considers calling a handler with no listeners an error this means each letsencrypt user will need to provide a handler. One simple option illustrated here is just to produce a stamp file. This can facilitate cross-playbook and even cross-orchestration-tool communication. For example, puppet or other ansible playbooks can detect this stamp file and schedule their reloads, etc. then remove the stamp file. It is conceivable more complex listeners could be setup via other roles, etc. should the need arise. A test is added to make sure the stamp file is created for the letsencrypt test hosts, which are always generating a new certificate in the gate test. Change-Id: I4e0609c4751643d6e0c8d9eaa38f184e0ce5452e
This commit is contained in:
parent
8baf6cabd3
commit
733122f0df
@ -1,4 +1,4 @@
|
||||
letsencrypt_certs:
|
||||
main:
|
||||
graphite01-main:
|
||||
- graphite01.opendev.org
|
||||
- graphite.opendev.org
|
||||
|
32
playbooks/roles/letsencrypt-create-certs/handlers/main.yaml
Normal file
32
playbooks/roles/letsencrypt-create-certs/handlers/main.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
# Handlers for "letsencrypt update {{ key }}" events
|
||||
#
|
||||
# Note that because Ansible requires every called handler to have a
|
||||
# listener, every host will need to provide a handler somehow.
|
||||
#
|
||||
# NOTE(ianw): as at 04/2019 it seems that something like
|
||||
#
|
||||
# listen: letsencrypt updated letsencrypt01-main-service
|
||||
#
|
||||
# doesn't actually register the handler. May be a bug or a feature to
|
||||
# do with import_tasks; currently unsure.
|
||||
|
||||
- name: letsencrypt updated graphite01-main
|
||||
import_tasks: touch_file.yaml
|
||||
vars:
|
||||
touch_file: '/tmp/letsencrypt-graphite01-main.stamp'
|
||||
|
||||
# Gate testing hosts:
|
||||
- name: letsencrypt updated letsencrypt01-main-service
|
||||
import_tasks: touch_file.yaml
|
||||
vars:
|
||||
touch_file: '/tmp/letsencrypt01-main-service.stamp'
|
||||
|
||||
- name: letsencrypt updated letsencrypt01-other-service
|
||||
import_tasks: touch_file.yaml
|
||||
vars:
|
||||
touch_file: '/tmp/letsencrypt01-other-service.stamp'
|
||||
|
||||
- name: letsencrypt updated letsencrypt02-main-service
|
||||
import_tasks: touch_file.yaml
|
||||
vars:
|
||||
touch_file: '/tmp/letsencrypt02-main-service.stamp'
|
@ -0,0 +1,5 @@
|
||||
- name: 'Touch {{ touch_file }}'
|
||||
file:
|
||||
path: '{{ touch_file }}'
|
||||
state: touch
|
||||
|
@ -10,5 +10,6 @@
|
||||
chdir: /opt/acme.sh/
|
||||
environment:
|
||||
LETSENCRYPT_STAGING: '{{ "1" if letsencrypt_use_staging else "0" }}'
|
||||
notify: 'letsencrypt updated {{ item.key }}'
|
||||
|
||||
# Keys generated!
|
@ -35,16 +35,25 @@ provision process.
|
||||
.. code-block:: yaml
|
||||
|
||||
letsencrypt_certs:
|
||||
main:
|
||||
hostname-main-cert:
|
||||
- hostname01.opendev.org
|
||||
- hostname.opendev.org
|
||||
secondary:
|
||||
hostname-secondary-cert:
|
||||
- foo.opendev.org
|
||||
|
||||
will ultimately result in two certificates being provisioned on the
|
||||
host in ``/etc/letsencrypt-certs/hostname01.opendev.org`` and
|
||||
``/etc/letsencrypt-certs/foo.opendev.org``.
|
||||
|
||||
Note the creation role ``letsencrypt-create-certs`` will call a
|
||||
handler ``letsencrypt updated {{ key }}`` (for example,
|
||||
``letsencrypt updated hostname-main-cert``) when that certificate
|
||||
is created or updated. Because Ansible errors if a handler is
|
||||
called with no listeners, you *must* define a listener for event.
|
||||
``letsencrypt-create-certs`` has ``handlers/main.yaml`` where
|
||||
handlers can be defined. Since handlers reside in a global
|
||||
namespace, you should choose an appropriately unique name.
|
||||
|
||||
Note that each entry will require a ``CNAME`` pointing the ACME
|
||||
challenge domain to the TXT record that will be created in the
|
||||
signing domain. For example above, the following records would need
|
||||
|
@ -1,7 +1,7 @@
|
||||
letsencrypt_certs:
|
||||
main:
|
||||
letsencrypt01-main-service:
|
||||
- letsencrypt01.opendev.org
|
||||
- letsencrypt.opendev.org
|
||||
- alias.opendev.org
|
||||
secondary:
|
||||
letsencrypt01-other-service:
|
||||
- someotherservice.opendev.org
|
@ -1,4 +1,4 @@
|
||||
letsencrypt_certs:
|
||||
main:
|
||||
letsencrypt02-main-service:
|
||||
- letsencrypt02.opendev.org
|
||||
- letsencrypt.opendev.org
|
||||
|
@ -68,3 +68,17 @@ def test_certs_created(host):
|
||||
|
||||
else:
|
||||
pytest.skip()
|
||||
|
||||
def test_updated_handler(host):
|
||||
if host.backend.get_hostname() == 'letsencrypt01.opendev.org':
|
||||
stamp_file = host.file('/tmp/letsencrypt01-main-service.stamp')
|
||||
assert stamp_file.exists
|
||||
stamp_file = host.file('/tmp/letsencrypt01-other-service.stamp')
|
||||
assert stamp_file.exists
|
||||
|
||||
elif host.backend.get_hostname() == 'letsencrypt02.opendev.org':
|
||||
stamp_file = host.file('/tmp/letsencrypt02-main-service.stamp')
|
||||
assert stamp_file.exists
|
||||
|
||||
else:
|
||||
pytest.skip()
|
||||
|
Loading…
Reference in New Issue
Block a user