Make inventory/service for service-specific things, including the groups.yaml group definitions, and inventory/base for hostvars related to the base system, including the list of hosts. Move the exisitng host_vars into inventory/service, since most of them are likely service-specific. Move group_vars/all.yaml into base/group_vars as almost all of it is related to base things, with the execption of the gerrit public key. A followup patch will move host-specific values into equivilent files in inventory/base. This should let us override hostvars in gate jobs. It should also allow us to do better file matchers - and to be able to organize our playbooks move if we want to. Depends-On: https://review.opendev.org/731583 Change-Id: Iddf57b5be47c2e9de16b83a1bc83bee25db995cf
5.5 KiB
- title
-
letsencrypt
Let's Encrypt Certificates
We support provisioning certificates from https://letsencrypt.org for hosts in
the opendev.org
namespace.
At a Glance
- Ansible
- Resources
- Chat
-
- #opendev on freenode
Overview
We support automatic provisioning of certificates from Let's Encrypt
to hosts in the opendev.org
domain.
This is implemented in OpenDev via the roles driven from :git_file:`playbooks/letsencrypt.yaml`. The overall actions implemented by the above roles are roughly:
Hosts that want a certificate use the
amce.sh
tool to request it from the Let's Encrypt CA.Creation or renewal requests receive a TXT record authentication value that must be published to prove ownership of the domain. We implement this by making the challenge-request hostname
_acme-challenge.hostname.opendev.org
aCNAME
record to a special "signing domain"acme.opendev.org
.Note if valid certificates are present and they are not within the renewal period (which is most of the time) no further action is taken.
The provided TXT record authentication values are installed and published to the
acme.opendev.org
domain via the OpenDev nameservers.The host can now finalise certificate creation. Let's Encrypt checks
_acme-chellenge.hostname.opendev.org
, which is aCNAME
toacme.opendev.org
. Let's Encrypt then enumerates the TXT records there, and once finding the required key will return the signed keys to the host, which saves them to disk.
Configuring a host to get certificates
A basic configuration consists of the following steps:
Ensure the host is matched by the
letsencrypt
group in :git_file:`inventory/groups.yaml`.DNS entries for
_acme-chellenge.hostname
as aCNAME
toopendev.org
must be added and live in theopendev.org
zone.db file. Follow the other examples to ensure other fields such asCAA
records are set too.Take care to list all hostnames that you wish covered by the certificate (e.g.
hostname01.opendev.org
andhostname.opendev.org
)Configure the certificates to be issued to the host.
The roles look for certificate configuration in a
letsencrypt_certs
variable defined for each host. This is usually done via specific host variables ininventory/service/host_vars/<hostname>.opendev.org.yaml
. For a simple host that wants a single certificate to cover its numeric hostname and regularCNAME
this would look like :letsencrypt_certs: hostname01-opendev-org: - hostname01.opendev.org - hostname.opendev.org
This will result in certificate material in
/etc/letsencrypt-certs/hostname01.opendev.org/
on the host.Note that the "certificate name" dictionary keys (just
hostname01-opendev-org
above) are essentially a free-form string, but are used in the next step. Follow the naming conventions for similar hosts.For full details, including information on issuing multiple certificates for a single host, see :git_file:`playbooks/roles/letsencrypt-request-certs/README.rst`.
Define a handler for certificate creation and renewal actions.
When the certificate is created or renewed, the
letsencrypt-create-certs
role calls a predefined handler so action can be taken. This handler name is constructed by prependingletsencrypt updated
to the certificate name above. Thus in this example it would be :- name: letsencrypt updated hostname01-opendev-org ...
Usually these handlers are defined centrally in :git_file:`playbooks/roles/letsencrypt-create-certs/handlers/main.yaml` and common tasks such as restarting Apache have pre-defined tasks available for easy import.
You may choose to define the handler in another way, but it must exist (Ansible does not have a way to say "call this handler only if it exists", thus a missing handler will cause an Ansible error at runtime).
Debugging
The Ansible run logs on bridge.opendev.org
should be
consulted if the certificate material is not being created as
expected.
Hosts will log their acme.sh
output to
/var/log/acme.sh/acme.sh.log
The G Suite Toolbox Dig tool can be useful for checking DNS entries from a remote location.
Refreshing keys
In normal operation there should be no need to manually refresh keys on hosts. However there have been situations (such as LetsEncrypt revoking certificates made during a certain period due to bugs) which may necessitate a manual renewal.
The best way to do this is to move the .conf
files from
/etc/letsencrypt-certs/<certname>
on the affected
host and allow the next Ansible pulse to renew.
# cd /etc/letsencrypt-certs/<name>
# rename 's/.conf/.conf.old/' *.conf
# tail -f /var/log/acme.sh/acme.sh.log
... watch and should be renewed on next pulse
# rm *.conf.old