def from_url(cls, reactor, url, key, alg=jose.RS256, jws_client=None): """ Construct a client from an ACME directory at a given URL. :param url: The ``twisted.python.url.URL`` to fetch the directory from. See `txacme.urls` for constants for various well-known public directories. :param reactor: The Twisted reactor to use. :param ~acme.jose.jwk.JWK key: The client key to use. :param alg: The signing algorithm to use. Needs to be compatible with the type of key used. :param JWSClient jws_client: The underlying client to use, or ``None`` to construct one. :return: The constructed client. :rtype: Deferred[`Client`] """ action = LOG_ACME_CONSUME_DIRECTORY( url=url, key_type=key.typ, alg=alg.name) with action.context(): check_directory_url_type(url) jws_client = _default_client(jws_client, reactor, key, alg) return ( DeferredContext(jws_client.get(url.asText())) .addCallback(json_content) .addCallback(messages.Directory.from_json) .addCallback( tap(lambda d: action.add_success_fields(directory=d))) .addCallback(cls, reactor, key, jws_client) .addActionFinish())
def from_url(cls, reactor, url, key, alg=RS256, jws_client=None): """ Construct a client from an ACME directory at a given URL. :param url: The ``twisted.python.url.URL`` to fetch the directory from. See `txacme.urls` for constants for various well-known public directories. :param reactor: The Twisted reactor to use. :param ~josepy.jwk.JWK key: The client key to use. :param alg: The signing algorithm to use. Needs to be compatible with the type of key used. :param JWSClient jws_client: The underlying client to use, or ``None`` to construct one. :return: The constructed client. :rtype: Deferred[`Client`] """ action = LOG_ACME_CONSUME_DIRECTORY( url=url, key_type=key.typ, alg=alg.name) with action.context(): check_directory_url_type(url) jws_client = _default_client(jws_client, reactor, key, alg) return ( DeferredContext(jws_client.get(url.asText())) .addCallback(json_content) .addCallback(messages.Directory.from_json) .addCallback( tap(lambda d: action.add_success_fields(directory=d))) .addCallback(cls, reactor, key, jws_client) .addActionFinish())
def from_url( cls, reactor, url, key, alg=RS256, jws_client=None, timeout=_DEFAULT_TIMEOUT, ): """ Construct a client from an ACME directory at a given URL. At construct time, it validates the ACME directory. :param url: The ``twisted.python.url.URL`` to fetch the directory from. See `txacme.urls` for constants for various well-known public directories. :param reactor: The Twisted reactor to use. :param ~josepy.jwk.JWK key: The client key to use. :param alg: The signing algorithm to use. Needs to be compatible with the type of key used. :param JWSClient jws_client: The underlying client to use, or ``None`` to construct one. :param int timeout: Number of seconds to wait for an HTTP response during ACME server interaction. :return: The constructed client. :rtype: Deferred[`Client`] """ action = LOG_ACME_CONSUME_DIRECTORY(url=url, key_type=key.typ, alg=alg.name) with action.context(): check_directory_url_type(url) directory = url.asText() return (DeferredContext(jws_client=_default_client( jws_client, reactor, key, alg, directory, timeout )).addCallback( tap(lambda jws_client: action.add_success_fields( directory=directory))).addCallback(lambda jws_client: cls( reactor, key, jws_client)).addActionFinish())
class AutoTLSEndpoint(object): """ A server endpoint that does TLS SNI, with certificates automatically (re)issued from an ACME certificate authority. :param reactor: The Twisted reactor. :param directory: ``twisted.python.url.URL`` for the ACME directory to use for issuing certs. :type client_creator: Callable[[reactor, ``twisted.python.url.URL``], Deferred[`txacme.client.Client`]] :param client_creator: 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)``. :param .ICertificateStore cert_store: The certificate store containing the certificates to manage. For example, `txacme.store.DirectoryStore`. :param dict cert_mapping: The certificate mapping to use for SNI; for example, ``txsni.snimap.HostDirectoryMap``. Usually this should correspond to the same underlying storage as ``cert_store``. :param ~datetime.timedelta check_interval: How often to check for expiring certificates. :param ~datetime.timedelta reissue_interval: If a certificate is expiring in less time than this interval, it will be reissued. :param ~datetime.timedelta panic_interval: If a certificate is expiring in less time than this interval, and reissuing fails, the panic callback will be invoked. :type panic: Callable[[Failure, `str`], Deferred] :param panic: A callable invoked with the failure and server name when reissuing fails for a certificate expiring in the ``panic_interval``. For example, you could generate a monitoring alert. The default callback logs a message at *CRITICAL* level. :param 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. """ reactor = attr.ib() directory = attr.ib( validator=lambda inst, a, value: check_directory_url_type(value)) client_creator = attr.ib() cert_store = attr.ib() cert_mapping = attr.ib() sub_endpoint = attr.ib() check_interval = attr.ib(default=timedelta(days=1)) reissue_interval = attr.ib(default=timedelta(days=30)) panic_interval = attr.ib(default=timedelta(days=15)) _panic = attr.ib(default=_default_panic) _generate_key = attr.ib(default=partial(generate_private_key, u'rsa')) def listen(self, protocolFactory): # noqa """ Start an issuing service, and wait until initial issuing is complete. """ def _got_port(port): self.service = AcmeIssuingService( cert_store=self.cert_store, client_creator=partial( self.client_creator, self.reactor, self.directory), clock=self.reactor, responders=[responder], check_interval=self.check_interval, reissue_interval=self.reissue_interval, panic_interval=self.panic_interval, panic=self._panic, generate_key=self._generate_key) self.service.startService() return ( self.service.when_certs_valid() .addCallback( lambda _: _WrapperPort(port=port, service=self.service))) responder = TLSSNI01Responder() sni_map = SNIMap(responder.wrap_host_map(self.cert_mapping)) return ( maybeDeferred( self.sub_endpoint.listen, TLSMemoryBIOFactory( contextFactory=sni_map, isClient=False, wrappedFactory=protocolFactory)) .addCallback(_got_port))