Let’s Encrypt

class plinth.modules.letsencrypt.components.LetsEncrypt(component_id, domains=None, daemons=None, should_copy_certificates=False, private_key_path=None, certificate_path=None, user_owner=None, group_owner=None, managing_app=None)[source]

Component to receive Let’s Encrypt renewal hooks.

Performs the following tasks:

  • Listen to certificate change events from the Let’s Encrypt app. This could be obtain, re-obtain, renewal, revoke and delete events.

  • Filter out events after comparing domains list in certificate events to the list of domains the app (to which this component belongs) is interested in.

  • If requested, copy certificates from /etc/letsencrypt directory to app’s directory with the needed permissions and ownership.

  • Query status of copied certificates. Status could be up-to-date, self-signed, outdated (/etc/letsencrypt has more recent certificate), expired or a test certificate.

  • Optionally restart a bunch of daemons after interesting certificate event occurs.

__init__(component_id, domains=None, daemons=None, should_copy_certificates=False, private_key_path=None, certificate_path=None, user_owner=None, group_owner=None, managing_app=None)[source]

Initialize the Let’s Encrypt component.

component_id should be a unique ID across all components of an app and across all components.

domains is a list of domains that the app is configured for. Any certificate operation that is not happening on these domains is ignored by this component.

domains can be the string ‘*’ in which case it means that the app is relevant for (or is interested in) all domains configured in the system.

domains can be a callable instead of a list. In this case, the callable is called every time an operation needs to be checked against list of domains for the app. The callable must return a list of domains that the app is configured for.

daemons is a list of systemd units that need to be restarted (actually try-restarted, i.e., only if they are already running) when a relevant certificate operation happens.

should_copy_certificates indicates whether the app needs the Let’s Encrypt certificates in the directory /etc/letsencrypt to be copied to a different location with different permissions to be able to use them. If true, private_key_path, certificate_path, user_owner, group_owner and managing_app properties must be specified. Otherwise, ValueError is raised.

private_key_path is the string containing the file path to which a private key must be copied. It may contain the sub-string ‘{domain}’ which will be replaced with the name of the domain for which this certificate is being copied. Any non-existing parent directories are created with ‘root:root’ ownership and ‘0o755’ file permissions. The permissions for the file will be ‘0o600’ and ownership will be as specified in parameters user_owner and group_owner. If both private_key_path and certificate_path refer to the same path, the target file is created by appending the private key and certificate.

certificate_path is the string containing the file path to which a certificate must be copied. It may contain the sub-string ‘{domain}’ which will be replaced with the name of the domain for which this certificate is being copied. Any non-existing parent directories are created with ‘root:root’ ownership and ‘0o755’ file permissions. The permissions for the file will be ‘0o644’ and ownership will be as specified in parameters user_owner and group_owner. If both private_key_path and certificate_path refer to the same path, the target file is created by appending the private key and certificate.

user_owner specifies the user who should own the copied certificates. This is typically the unprivileged user account that runs the daemon.

group_owner specifies the group who should own the copied certificates. This is typically the unprivileged group account that runs the daemon.

managing_app is the name of the app that contains this component. This is used by the superuser action to verify that this app is allowed to copy certificates to the target location. The app must then define a property ‘managing_paths’ which contains a list of pathlib.Path() objects to which the app is allowed to write certificates and other files to.

property domains

Return a list of domains this component’s app is interested in.

get_status()[source]

Return the status of certificates for all interested domains.

A dictionary is returned containing a key for each domain and the value shall be a simple string with state of certificate for this app. Possible values are ‘outdated-copy’, ‘self-signed’, ‘unknown’, ‘valid’, ‘revoked’, ‘expired’ and ‘test_cert’.

classmethod list()[source]

Return a list of all Let’s Encrypt components.

on_certificate_deleted(domains, lineage)[source]

Handle event when a certificate is deleted.

For now, performs the same operations as obtaining a fresh certificate.

on_certificate_obtained(domains, lineage)[source]

Handle event when a certificate is obtained.

Filter any domains that are interesting for the app that this component is part of. For all interesting domains, copy the certificates if requested and then restart the daemons.

on_certificate_renewed(domains, lineage)[source]

Handle event when a certificate is renewed.

This is typically called when a Cron job triggers certbot renewal process which in turn triggers configured renewal hooks after successful renewal. It is also called when a valid certificate is re-obtained.

To trigger a renewal event for testing purposes, run certbot renew –force-renewal.

For now, performs the same operations as obtaining a fresh certificate.

on_certificate_revoked(domains, lineage)[source]

Handle event when a certificate is revoked.

Filter any domains that are interesting for the app that this component is part of. For all interesting domains, copy self-signed snakeoil certificates if requested and then restart the daemons.

setup_certificates(app_domains=None)[source]

Setup app certificates for all interested domains.

For every domain, a certificate is copied. If a valid certificate is not available in Let’s Encrypt, a self-signed snakeoil certificate is used. Each daemon is restarted if it is running.

app_domains is the list of domains for which certificates must be copied. If it is not provided, the component’s list of domains (which may be acquired by a callable) is used.