txacme: A Twisted implementation of the ACME protocol¶
ACME is Automatic Certificate Management Environment, a protocol that allows clients and certificate authorities to automate verification and certificate issuance. The ACME protocol is used by the free Let’s Encrypt Certificate Authority.
txacme
is an implementation of the protocol for Twisted, the
event-driven networking engine for Python.
txacme
is still under heavy development, and currently only an
implementation of the client side of the protocol is planned; if you are
interested in implementing or have need of the server side, please get in
touch!
txacme
’s documentation lives at Read the Docs, the code on GitHub.
It’s rigorously tested on Python 2.7, 3.4+, and PyPy.
API entry points¶
There are several possible starting points for making use of txacme.
Server endpoint string¶
The simplest part of txacme to use is the stream server endpoint. Two endpoint
parsers are provided, under the le:
(Let’s Encrypt) and lets:
(Let’s
Encrypt Test in Staging) prefixes. The endpoint takes as parameters a directory
to store certificates in, and the underlying endpoint to listen on.
Note
The Let’s Encrypt staging environment generates certificates signed by Fake LE Intermediate X1, but does not have the stringent limits that the production environment has, so using it for testing before switching to the production environment is highly recommended.
A typical example:
twistd -n web --port lets:/srv/www/certs:tcp:443 --path /srv/www/root
Note
The certificate directory must already exist, and be writable by the user the application is running as.
The ACME client key will be stored in client.key
in the cert directory. If
this file does not exist, a new key will automatically be generated.
Certificates (and chain certificates and keys) in PEM format will be stored in
files named like some.domain.name.pem
in the certificate directory. The
appropriate certificate will be selected based on the servername that the
client sends by SNI, so clients that do not perform SNI will not be able to
connect.
In the event that there is no existing certificate available for a domain, an empty file can be used. This will be treated the same way as an expired certificate, and a new certificate will then be issued on startup. For example:
touch /srv/www/certs/example.com.pem
Note
This endpoint uses the tls-sni-01
challenge type to perform
authorization; this requires that the endpoint is reachable on port 443 for
those domains (possibly via port forwarding).
Note
A certificate directory can be shared amongst multiple applications,
using le:
for the application running on port 443 to keep the
certificates up to date, and txsni:
for the other applications to make
use of the same certificates.
At startup, and periodically (every 24 hours), a check will be performed for expiring certificates; if a certificate will expire in less than 30 days’ time, it will be reissued. If the reissue fails, it will be retried at the next check. If a certificate will expire in less than 15 days’ time, and reissue fails, a message will be logged at CRITICAL level.
Server endpoint API¶
The endpoint can be instantiated directly as well; this allows extra customizations beyond what the string syntax provides for. Most of the parameters that can be passed correspond to the parameters of the issuing service (see below).
-
class
txacme.endpoint.
AutoTLSEndpoint
(reactor, directory, client_creator, cert_store, cert_mapping, sub_endpoint, check_interval=datetime.timedelta(1), reissue_interval=datetime.timedelta(30), panic_interval=datetime.timedelta(15), panic=<function _default_panic>, generate_key=<functools.partial object>)[source] A server endpoint that does TLS SNI, with certificates automatically (re)issued from an ACME certificate authority.
Parameters: - reactor – The Twisted reactor.
- directory –
twisted.python.url.URL
for the ACME directory to use for issuing certs. - client_creator (Callable[[reactor,
twisted.python.url.URL
], Deferred[txacme.client.Client
]]) – A callable called with the reactor and directory URL for creating the ACME client. For example,partial(Client.from_url, key=acme_key, alg=RS256)
. - cert_store (ICertificateStore) – The certificate store containing the
certificates to manage. For example,
txacme.store.DirectoryStore
. - cert_mapping (dict) – The certificate mapping to use for SNI; for
example,
txsni.snimap.HostDirectoryMap
. Usually this should correspond to the same underlying storage ascert_store
. - check_interval (timedelta) – How often to check for expiring certificates.
- reissue_interval (timedelta) – If a certificate is expiring in less time than this interval, it will be reissued.
- panic_interval (timedelta) – If a certificate is expiring in less time than this interval, and reissuing fails, the panic callback will be invoked.
- panic (Callable[[Failure,
str
], Deferred]) – A callable invoked with the failure and server name when reissuing fails for a certificate expiring in thepanic_interval
. For example, you could generate a monitoring alert. The default callback logs a message at CRITICAL level. - generate_key – A 0-arg callable used to generate a private key for a new cert. Normally you would not pass this unless you have specialized key generation requirements.
-
listen
(protocolFactory)[source] Start an issuing service, and wait until initial issuing is complete.
Issuing service¶
The endpoint is a simple wrapper that combines the functionality of the txsni endpoint for handling SNI, and the issuing service which takes care of (re)issuing certificates using an ACME service.
-
class
txacme.service.
AcmeIssuingService
(cert_store, client, clock, responders, check_interval=datetime.timedelta(1), reissue_interval=datetime.timedelta(30), panic_interval=datetime.timedelta(15), panic=<function _default_panic>, generate_key=<functools.partial object>, waiting=NOTHING)[source] A service for keeping certificates up to date by using an ACME server.
Parameters: - cert_store (ICertificateStore) – The certificate store containing the certificates to manage.
- client (Client) – The ACME client to use. Typically
constructed with
Client.from_url
. - clock –
IReactorTime
provider; usually the reactor, when not testing. - responders (List[
IResponder
]) – Challenge responders. Usually only one responder is needed; if more than one responder for the same type is provided, only the first will be used. - check_interval (timedelta) – How often to check for expiring certificates.
- reissue_interval (timedelta) – If a certificate is expiring in less time than this interval, it will be reissued.
- panic_interval (timedelta) – If a certificate is expiring in less time than this interval, and reissuing fails, the panic callback will be invoked.
- panic (Callable[[Failure,
str
], Deferred]) – A callable invoked with the failure and server name when reissuing fails for a certificate expiring in thepanic_interval
. For example, you could generate a monitoring alert. The default callback logs a message at CRITICAL level. - generate_key – A 0-arg callable used to generate a private key for a new cert. Normally you would not pass this unless you have specialized key generation requirements.
-
when_certs_valid
()[source] Get a notification once the startup check has completed.
When the service starts, an initial check is made immediately; the deferred returned by this function will only fire once reissue has been attempted for any certificates within the panic interval.
Note
The reissue for any of these certificates may not have been successful; the panic callback will be invoked for any certificates in the panic interval that failed reissue.
Return type: Deferred
Returns: A deferred that fires once the initial check has resolved.
The ICertificateStore
and IResponder
interfaces are the main extension
points for using the issuing service directly. For example, a custom
implementation might manage the certificate configuration of a cloud load
balancer, implementing the dns-01
challenge type by modifying DNS entries
in the cloud DNS configuration.