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.
Contents¶
Using txacme¶
There are several possible ways to make use of txacme:
- An issuing service for keeping certificates in a certificate store up to date;
- A server endpoint, which may be used anywhere an endpoint is accepted, that combines the issuing service with TLS SNI for certificate mapping;
- A server endpoint string parser, which can be used anywhere a server endpoint string es accepted, that produces a server endpoint.
While the server endpoint string parser is a convenient high-level API the lower-level APIs (the issuing service and server endpoint) may be useful for better integration with existing systems. For example, if the requirements for storing certificates were more complex than a directory on a filesystem, one might implement a certificate store that communicated with a REST webservice or directly with a database and pass an instance of this to the server endpoint.
Server endpoint string¶
The simplest way to use txacme is the stream server endpoint string. 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. One might
use the following command to start a Twisted web server on TCP port 443 and
store certificates in the /srv/www/certs directory:
$ 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.
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.
The ACME client key will be stored in client.key in the certificate
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
the certificate directory using filenames based on the servername that the
client sends by SNI, e.g. some.domain.name.pem. The contents of the
directory are documented in more detail here. If there is no
existing certificate available for a domain, an empty file should be created to
have one issued on startup; the behaviour is as if the certificate had expired.
Importantly, clients that do not perform SNI will not be able to connect to the
endpoint.
At startup, and 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.
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).
Sharing certificates¶
A certificate directory can be shared amongst multiple applications by using
le: for the application running on port 443 to keep the certificates up to
date, and txsni: for other applications to make use of certificates in the
same directory.
Server endpoint¶
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.
-
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.URLfor 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 server 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_creator, clock, responders, email=None, 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 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_creator (Callable[[], Deferred[
txacme.client.Client]]) – A callable called with no arguments for creating the ACME client. For example,partial(Client.from_url, reactor=reactor, url=LETSENCRYPT_STAGING_DIRECTORY, key=acme_key, alg=RS256). - clock –
IReactorTimeprovider; 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. - email (str) – An (optional) email address to use during registration.
- 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.
-
issue_cert(server_name)[source] Issue a new cert for a particular name.
If an existing cert exists, it will be replaced with the new cert. If issuing is already in progress for the given name, a second issuing process will not be started.
Parameters: server_name (str) – The name to issue a cert for. Return type: DeferredReturns: A deferred that fires when issuing is complete.
-
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: DeferredReturns: 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 of ICertificateStore 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.
Certificates directory¶
The layout of the certificates directory used by DirectoryStore (and thus
the le: and lets: endpoints) is coordinated with txsni to allow
sharing a certificates directory with other applications. The txsni and txacme
maintainers have committed to coordination of any future changes to the
contents of this directory to ensure continued compatibility.
At present, the following entries may exist in this directory:
<server name>.pemA file containing a certificate and matching private key valid for
<server name>, serialized in PEM format.client.keyA file containing an ACME client key, serialized in PEM format.
All other filenames are currently reserved for future use; introducing non-specified files or directories into a certificates directory may result in conflicts with items specified by future versions of txacme and/or txsni.
API stability¶
txacme is versioned according to SemVer 2.0.0. In addition, since SemVer does not make this explicit, versions following txacme 1.0.0 will have a “rolling compatibility” guarantee: new major versions will not break behaviour that did not already emit a deprecation warning in the latest minor version of the previous major version series.
The current version number of 0.9.x is intended to reflect the not-quite-finalized nature of the API. While it is not expected that the API will change drastically, the 0.9 version series is intended to allow space for users to experiment and identify any issues obstructing their use cases so that these can be corrected before the API is finalized in the 1.0.0 release.
txacme changelog¶
Txacme 0.9.1 (2016-12-08)¶
Features¶
- INCOMPATIBLE CHANGE: AcmeIssuingService now takes a client creator, rather than a client, and invokes it for every issuing attempt. (#21)
- INCOMPATIBLE CHANGE: The
*_DIRECTORYconstants are now in txacme.urls. (#28) - INCOMPATIBLE CHANGE:
IResponder.start_respondingandIResponder.stop_respondingnow take the server_name and challenge object in addition to the challenge response object. (#60) - AcmeIssuingService now logs info messages about what it is doing. (#38)
- txacme.challenges.LibcloudDNSResponder implements a dns-01 challenge responder using libcloud. Installing txacme[libcloud] is necessary to pull in the dependencies for this. (#59)
txacme.challenges.HTTP01Responder, an http-01 challenge responder that can be embedded into an existing twisted.web application. (#65)txacme.endpoint.load_or_create_client_keygets a client key from the certs directory, using the same logic as the endpoints. (#71)AcmeIssuingServicenow accepts anemailparameter which it adds to the ACME registration. In addition, existing registrations are updated with this email address. (#72)AcmeIssuingServicenow has a publicissue_certmethod for safely issuing a new cert on demand. (#76)
Bugfixes¶
txacme.client.JWSClientnow automatically retries a POST request that fails with abadNonceerror. (#66)txacme.store.DirectoryStorenow handles bytes mode paths correctly. (#68)- The txacme endpoint plugin now lazily imports the rest of the code, avoiding ReactorAlreadyInstalled errors in various cases. (#79)
Improved Documentation¶
- The contents of the certificates directory, and compatibility with txsni, is now documented. (#35)
Misc¶
- #67
txacme¶
txacme package¶
Subpackages¶
txacme.challenges package¶
Module contents¶
-
class
txacme.challenges.LibcloudDNSResponder(reactor, thread_pool, driver, zone_name, settle_delay)[source]¶ A
dns-01challenge responder using libcloud.Warning
Some libcloud backends are broken with regard to TXT records at the time of writing; the Route 53 backend, for example. This makes them unusable with this responder.
Note
This implementation relies on invoking libcloud in a thread, so may not be entirely production quality.
-
classmethod
create(reactor, driver_name, username, password, zone_name=None, settle_delay=60.0)[source]¶ Create a responder.
Parameters: - reactor – The Twisted reactor to use for threading support.
- driver_name (str) – The name of the libcloud DNS driver to use.
- username (str) – The username to authenticate with (the meaning of this is driver-specific).
- password (str) – The username to authenticate with (the meaning of this is driver-specific).
- zone_name (str) – The zone name to respond in, or
Noneto automatically detect zones. Usually auto-detection should be fine, unless restricting responses to a single specific zone is desired. - settle_delay (float) – The time, in seconds, to allow for the DNS provider to propagate record changes.
-
classmethod
txacme.test package¶
Submodules¶
Test doubles.
-
class
txacme.test.matchers.ValidForName(name)[source]¶ Matches when the matchee object (must be a
CertificateorCertificateSigningRequest) is valid for the given name.
Miscellaneous strategies for Hypothesis testing.
Tests for txacme.challenges.
-
class
txacme.test.test_challenges.HTTPResponderTests(*args, **kwargs)[source]¶ HTTP01Responderis a responder for http-01 challenges.
-
class
txacme.test.test_challenges.TLSResponderTests(*args, **kwargs)[source]¶ TLSSNI01Responderis a responder for tls-sni-01 challenges that works with txsni.
-
class
txacme.test.test_challenges.MergingProxyTests(*args, **kwargs)[source]¶ _MergingMappingProxymerges two mappings together.-
test_get_both()[source]¶ Getting an key that exists in both the underlay and the overlay returns the value from the overlay.
-
test_get_overlay()[source]¶ Getting an key that only exists in the overlay returns the value from the overlay.
-
-
class
txacme.test.test_challenges.LibcloudResponderTests(*args, **kwargs)[source]¶ LibcloudDNSResponderimplements a responder for dns-01 challenges using libcloud on the backend.-
test_auto_zone()[source]¶ If the configured zone_name is
None, the zone will be guessed by finding the longest zone that is a suffix of the server name.
-
test_auto_zone_missing()[source]¶ If the configured zone_name is
None, and no matching zone is found,NotInZoneis raised.
-
test_missing_zone()[source]¶ ZoneNotFoundis raised if the configured zone cannot be found at the configured provider.
-
-
class
txacme.test.test_client.ClientTests(*args, **kwargs)[source]¶ Clientprovides a client interface for the ACME API.-
test_answer_challenge()[source]¶ answer_challengeresponds to a challenge and returns the updated challenge.
-
test_answer_challenge_function()[source]¶ The challenge is found in the responder after invoking
answer_challenge.
_parse_authorizationraisesClientErrorif the"next"link is missing.
_check_authorizationraisesUnexpectedUpdateif the return identifier doesn’t match.
-
test_challenge_missing_link()[source]¶ _parse_challengeraisesClientErrorif the"up"link is missing.
-
test_challenge_unexpected_uri()[source]¶ _check_challengeraisesUnexpectedUpdateif the challenge does not have the expected URI.
-
test_default_client()[source]¶ ~txacme.client._default_clientconstructs a client if one was not provided.
-
test_directory_url_type()[source]¶ from_urlexpects atwisted.python.url.URLinstance for theurlargument.
-
test_expect_response_wrong_code()[source]¶ _expect_responseraisesClientErrorif the response code does not match the expected code.
-
test_fetch_chain_empty()[source]¶ If a certificate has no issuer link,
Client.fetch_chainreturns an empty chain.
-
test_fetch_chain_okay()[source]¶ A certificate chain that is shorter than the max length is returned.
-
test_fetch_chain_too_long()[source]¶ A certificate chain that is too long fails with
ClientError.
-
test_fqdn_identifier()[source]¶ fqdn_identifierconstructs anIdentifierof the right type.
-
test_from_directory()[source]¶ from_url()constructs a client with a directory retrieved from the given URL.
-
test_no_tls_sni_01()[source]¶ If no tls-sni-01 challenges are available,
NoSupportedChallengesis raised.
-
test_poll()[source]¶ pollretrieves the latest state of an authorization resource, as well as the minimum time to wait before polling the state again.
-
test_poll_invalid()[source]¶ If the authorization enters an invalid state while polling,
poll_until_validwill fail withAuthorizationFailed.
-
test_poll_timeout()[source]¶ If the timeout is exceeded during polling,
poll_until_validwill fail withCancelledError.
-
test_poll_valid()[source]¶ If the authorization enters a valid state while polling,
poll_until_validwill fire with the updated authorization.
-
test_register_bad_nonce_once()[source]¶ If a badNonce error is received, we clear all old nonces and retry the request once.
-
test_register_bad_nonce_twice()[source]¶ If a badNonce error is received on a retry, fail the request.
-
test_register_error()[source]¶ If some other error occurs during registration, a
txacme.client.ServerErrorresults.
-
test_register_existing()[source]¶ If registration fails due to our key already being registered, the existing registration is returned.
-
test_register_existing_update()[source]¶ If registration fails due to our key already being registered, the existing registration is updated.
-
test_register_missing_next()[source]¶ If the directory does not return a
"next"link, aClientErrorfailure occurs.
-
test_request_challenges()[source]¶ request_challenges()creates a new authorization, and returns the authorization resource with a list of possible challenges to proceed with.
-
test_tls_sni_01_no_singleton()[source]¶ If a suitable singleton challenge is not found,
NoSupportedChallengesis raised.
-
test_unexpected_update()[source]¶ If the server does not return the registration we expected, an
UnexpectedUpdatefailure occurs.
-
-
class
txacme.test.test_client.ExtraCoverageTests(*args, **kwargs)[source]¶ Tests to get coverage on some test helpers that we don’t really want to maintain ourselves.
Tests for txacme.endpoint.
-
class
txacme.test.test_endpoint.EndpointTests(*args, **kwargs)[source]¶ Tests for
AutoTLSEndpoint.-
test_directory_url_type()[source]¶ AutoTLSEndpointexpects atwisted.python.url.URLinstance for thedirectoryargument.
-
-
class
txacme.test.test_endpoint.PluginTests(*args, **kwargs)[source]¶ Tests for the plugins.
-
test_le_parser()[source]¶ The
le:parser uses the Let’s Encrypt production directory, and provides the relevant interfaces.
-
-
class
txacme.test.test_matchers.ValidForNameTests(*args, **kwargs)[source]¶ ValidForNamematches if a CSR/cert is valid for the given name.
-
class
txacme.test.test_service.AcmeIssuingServiceTests(*args, **kwargs)[source]¶ Tests for
txacme.service.AcmeIssuingService.-
test_cancellation()[source]¶ Cancelling the deferred returned by
issue_certcancels the actual issuing process.
-
test_errors()[source]¶ If a cert renewal fails within the panic interval, the panic callback is invoked; otherwise the error is logged normally.
-
test_issue_concurrently()[source]¶ Invoking
issue_certmultiple times concurrently for the same name will not start multiple issuing processes, only wait for the first process to complete.
-
test_registration_email()[source]¶ If we give our service an email address, that address will be used as a registration contact.
-
test_time_marches_on()[source]¶ Any certs that have exceeded the panic or reissue intervals will be reissued at the next check.
-
test_timer_errors()[source]¶ If the timed check fails (for example, because registration fails), the error should be caught and logged.
-
test_when_certs_valid_all_certs_valid()[source]¶ The deferred returned by
when_certs_validfires immediately if none of the certs in the store are expired.
-
-
class
txacme.test.test_store.DirectoryStoreTests(*args, **kwargs)[source]¶ Tests for
txacme.store.DirectoryStore.
-
class
txacme.test.test_store.MemoryStoreTests(*args, **kwargs)[source]¶ Tests for
txacme.testing.MemoryStore.
-
class
txacme.test.test_util.GeneratePrivateKeyTests(*args, **kwargs)[source]¶ generate_private_keygenerates private keys of various types using sensible parameters.-
test_unknown_key_type()[source]¶ Passing an unknown key type results in
ValueError.
-
-
class
txacme.test.test_util.GenerateCertTests(*args, **kwargs)[source]¶ generate_tls_sni_01_certgenerates a cert and key suitable for responding for the given challenge SAN.-
test_cert_verifies()[source]¶ The certificates generated verify using
verify_cert.
-
-
class
txacme.test.test_util.CSRTests(*args, **kwargs)[source]¶ encode_csranddecode_csrserialize CSRs in JOSE Base64 DER encoding.-
test_common_name_too_long()[source]¶ If the first name provided is too long,
csr_for_namesuses a dummy value for the common name.
-
test_decode_garbage()[source]¶ If decoding fails,
decode_csrraisesDeserializationError.
-
test_empty_names_invalid()[source]¶ csr_for_namesraisesValueErrorif given an empty list of names.
-
test_valid_for_names()[source]¶ csr_for_namesreturns a CSR that is actually valid for the given names.
-
Module contents¶
Submodules¶
txacme.client module¶
ACME client API (like acme.client) implementation for Twisted.
-
class
txacme.client.Client(directory, reactor, key, jws_client)[source]¶ ACME client interface.
-
agree_to_tos(regr)[source]¶ Accept the terms-of-service for a registration.
Parameters: regr (RegistrationResource) – The registration to update. Returns: The updated registration resource. Return type: Deferred[ RegistrationResource]
-
answer_challenge(challenge_body, response)[source]¶ Respond to an authorization challenge.
Parameters: - challenge_body (ChallengeBody) – The challenge being responded to.
- response (ChallengeResponse) – The response to the challenge.
Returns: The updated challenge resource.
Return type: Deferred[
ChallengeResource]
-
fetch_chain(certr, max_length=10)[source]¶ Fetch the intermediary chain for a certificate.
Parameters: - certr (acme.messages.CertificateResource) – The certificate to fetch the chain for.
- max_length (int) – The maximum length of the chain that will be fetched.
Return type: Deferred[List[
acme.messages.CertificateResource]]Returns: The issuer certificate chain, ordered with the trust anchor last.
-
classmethod
from_url(reactor, url, key, alg=RS256, jws_client=None)[source]¶ Construct a client from an ACME directory at a given URL.
Parameters: - url – The
twisted.python.url.URLto fetch the directory from. Seetxacme.urlsfor constants for various well-known public directories. - reactor – The Twisted reactor to use.
- key (JWK) – The client key to use.
- alg – The signing algorithm to use. Needs to be compatible with the type of key used.
- jws_client (JWSClient) – The underlying client to use, or
Noneto construct one.
Returns: The constructed client.
Return type: Deferred[
Client]- url – The
-
register(new_reg=None)[source]¶ Create a new registration with the ACME server.
Parameters: new_reg (NewRegistration) – The registration message to use, or Noneto construct one.Returns: The registration resource. Return type: Deferred[ RegistrationResource]
-
request_challenges(identifier)[source]¶ Create a new authorization.
Parameters: identifier (Identifier) – The identifier to authorize. Returns: The new authorization resource. Return type: Deferred[ AuthorizationResource]
-
request_issuance(csr)[source]¶ Request a certificate.
Authorizations should have already been completed for all of the names requested in the CSR.
Note that unlike
acme.client.Client.request_issuance, the certificate resource will have the body data as raw bytes.See also
Todo
Delayed issuance is not currently supported, the server must issue the requested certificate immediately.
Parameters: csr – A certificate request message: normally txacme.messages.CertificateRequestoracme.messages.CertificateRequest.Return type: Deferred[ acme.messages.CertificateResource]Returns: The issued certificate.
-
classmethod
retry_after(response, default=5, _now=<built-in function time>)[source]¶ Parse the Retry-After value from a response.
-
update_registration(regr, uri=None)[source]¶ Submit a registration to the server to update it.
Parameters: - regr (RegistrationResource) – The registration to
update. Can be a
NewRegistrationinstead, in order to create a new registration. - uri (str) – The url to submit to. Must be
specified if a
NewRegistrationis provided.
Returns: The updated registration resource.
Return type: Deferred[
RegistrationResource]- regr (RegistrationResource) – The registration to
update. Can be a
-
-
class
txacme.client.JWSClient(treq_client, key, alg, user_agent='txacme/0.9.1+2.g9b52744.dirty')[source]¶ HTTP client using JWS-signed messages.
-
get(url, content_type='application/json', **kwargs)[source]¶ Send GET request and check response.
Parameters: Raises: - txacme.client.ServerError – If server response body carries HTTP Problem (draft-ietf-appsawg-http-problem-00).
- acme.errors.ClientError – In case of other protocol errors.
Returns: Deferred firing with the checked HTTP response.
-
head(url, *args, **kwargs)[source]¶ Send HEAD request without checking the response.
Note that
_check_responseis not called, as there will be no response body to check.Parameters: url (str) – The URL to make the request to.
-
post(url, obj, content_type='application/json', **kwargs)[source]¶ POST an object and check the response. Retry once if a badNonce error is received.
Parameters: - url (str) – The URL to request.
- obj (JSONDeSerializable) – The serializable payload of the request.
- content_type (bytes) – The expected content type of the response. By default, JSON.
Raises: - txacme.client.ServerError – If server response body carries HTTP Problem (draft-ietf-appsawg-http-problem-00).
- acme.errors.ClientError – In case of other protocol errors.
-
-
exception
txacme.client.ServerError(message, response)[source]¶ acme.messages.Errorisn’t usable as an asynchronous exception, because it doesn’t allow setting the__traceback__attribute like Twisted wants to do when cleaning Failures. This type exists to wrap such an error, as well as provide access to the original response.
-
txacme.client.fqdn_identifier(fqdn)[source]¶ Construct an identifier from an FQDN.
Trivial implementation, just saves on typing.
Parameters: fqdn (str) – The domain name. Returns: The identifier. Return type: Identifier
-
txacme.client.answer_challenge(authzr, client, responders)[source]¶ Complete an authorization using a responder.
Parameters: - auth (AuthorizationResource) – The authorization to complete.
- client (Client) – The ACME client.
- responders (List[
IResponder]) – A list of responders that can be used to complete the challenge with.
Returns: A deferred firing when the authorization is verified.
-
txacme.client.poll_until_valid(authzr, clock, client, timeout=300.0)[source]¶ Poll an authorization until it is in a state other than pending or processing.
Parameters: - auth (AuthorizationResource) – The authorization to complete.
- clock – The
IReactorTimeimplementation to use; usually the reactor, when not testing. - client (Client) – The ACME client.
- timeout (float) – Maximum time to poll in seconds, before giving up.
Raises: txacme.client.AuthorizationFailed – if the authorization is no longer in the pending, processing, or valid states.
Raises: twisted.internet.defer.CancelledErrorif the authorization was still in pending or processing state when the timeout was reached.Return type: Deferred[
AuthorizationResource]Returns: A deferred firing when the authorization has completed/failed; if the authorization is valid, the authorization resource will be returned.
txacme.endpoint module¶
A TLS endpoint that supports SNI automatically issues / renews certificates via an ACME CA (eg. Let’s Encrypt).
-
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.URLfor 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.
-
txacme.endpoint.load_or_create_client_key(pem_path)[source]¶ Load the client key from a directory, creating it if it does not exist.
Note
The client key that will be created will be a 2048-bit RSA key.
Parameters: pem_path ( twisted.python.filepath.FilePath) – The certificate directory to use, as with the endpoint.
txacme.errors module¶
Exception types for txacme.
txacme.interfaces module¶
Interface definitions for txacme.
-
interface
txacme.interfaces.IResponder¶ Configuration for a ACME challenge responder.
The actual responder may exist somewhere else, this interface is merely for an object that knows how to configure it.
-
challenge_type¶ The type of challenge this responder is able to respond for.
Must correspond to one of the types from
acme.challenges; for example,u'tls-sni-01'.
-
stop_responding(server_name, challenge, response)¶ Stop responding for a particular challenge.
May be a noop if a particular responder does not need or implement explicit cleanup; implementations should not rely on this method always being called.
Parameters: - server_name (str) – The server name for which the challenge is being completed.
- challenge – The
acme.challengeschallenge object; the exact type of this object depends on the challenge type. - response – The
acme.challengesresponse object; the exact type of this object depends on the challenge type.
-
start_responding(server_name, challenge, response)¶ Start responding for a particular challenge.
Parameters: - server_name (str) – The server name for which the challenge is being completed.
- challenge – The
acme.challengeschallenge object; the exact type of this object depends on the challenge type. - response – The
acme.challengesresponse object; the exact type of this object depends on the challenge type.
Return type: DeferredReturns: A deferred firing when the challenge is ready to be verified.
-
-
interface
txacme.interfaces.ICertificateStore¶ A store of certificate/keys/chains.
-
as_dict(self)¶ Get all certificates in the store.
Return type: Deferred[Dict[str, List[:ref:`pem-objects`]]]Returns: A deferred firing with a dict mapping server names to PEM Objects.
-
store(self, server_name, pem_objects)¶ Store PEM objects for the given server name.
Implementations do not have to permit invoking this with a server name that was not already present in the store.
Parameters: - server_name (str) – The server name to update.
- pem_objects – A list of PEM Objects; must contain exactly one private key, a certificate corresponding to that private key, and zero or more chain certificates.
Return type: Deferred
-
txacme.logging module¶
Eliot message and action definitions.
txacme.messages module¶
ACME protocol messages.
This module provides supplementary message implementations that are not already
provided by the acme library.
See also
txacme.service module¶
-
class
txacme.service.AcmeIssuingService(cert_store, client_creator, clock, responders, email=None, 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 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_creator (Callable[[], Deferred[
txacme.client.Client]]) – A callable called with no arguments for creating the ACME client. For example,partial(Client.from_url, reactor=reactor, url=LETSENCRYPT_STAGING_DIRECTORY, key=acme_key, alg=RS256). - clock –
IReactorTimeprovider; 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. - email (str) – An (optional) email address to use during registration.
- 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.
-
issue_cert(server_name)[source]¶ Issue a new cert for a particular name.
If an existing cert exists, it will be replaced with the new cert. If issuing is already in progress for the given name, a second issuing process will not be started.
Parameters: server_name (str) – The name to issue a cert for. Return type: DeferredReturns: A deferred that fires when issuing is complete.
-
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: DeferredReturns: A deferred that fires once the initial check has resolved.
txacme.store module¶
txacme.interfaces.ICertificateStore implementations.
txacme.testing module¶
Utilities for testing with txacme.
-
class
txacme.testing.FakeClient(key, clock, ca_key=None, controller=None)[source]¶ Provides the same API as
Client, but performs no network operations and issues certificates signed by its own fake CA.
-
class
txacme.testing.FakeClientController(paused=False)[source]¶ Controls issuing for
FakeClient.
txacme.urls module¶
txacme.util module¶
Utility functions that may prove useful when writing an ACME client.
-
txacme.util.generate_private_key(key_type)[source]¶ Generate a random private key using sensible parameters.
Parameters: key_type (str) – The type of key to generate. One of: rsa.
-
txacme.util.generate_tls_sni_01_cert(server_name, key_type=u'rsa', _generate_private_key=None)[source]¶ Generate a certificate/key pair for responding to a tls-sni-01 challenge.
Parameters: Return type: Tuple[`~cryptography.x509.Certificate`, PrivateKey]Returns: A tuple of the certificate and private key.
-
txacme.util.cert_cryptography_to_pyopenssl(cert)[source]¶ Convert a
cryptography.x509.Certificateobject to anOpenSSL.crypto.X509object.
-
txacme.util.key_cryptography_to_pyopenssl(key)[source]¶ Convert a Cryptography private key object to an
OpenSSL.crypto.PKeyobject.
-
txacme.util.tap(f)[source]¶ “Tap” a Deferred callback chain with a function whose return value is ignored.
-
txacme.util.encode_csr(csr)[source]¶ Encode CSR as JOSE Base-64 DER.
Parameters: csr (cryptography.x509.CertificateSigningRequest) – The CSR. Return type: str
-
txacme.util.decode_csr(b64der)[source]¶ Decode JOSE Base-64 DER-encoded CSR.
Parameters: b64der (str) – The encoded CSR. Return type: cryptography.x509.CertificateSigningRequestReturns: The decoded CSR.
-
txacme.util.csr_for_names(names, key)[source]¶ Generate a certificate signing request for the given names and private key.
See also
See also
Parameters: - List[str] – One or more names (subjectAltName) for which to request a certificate.
- key – A Cryptography private key object.
Return type: Returns: The certificate request message.
-
txacme.util.clock_now(clock)[source]¶ Get a datetime representing the current time.
Parameters: clock – An IReactorTimeprovider.Return type: datetimeReturns: A datetime representing the current time.