def obtain_certificate(self, domains, csr=None): """Obtains a certificate from the ACME server. :meth:`.register` must be called before :meth:`.obtain_certificate` .. todo:: This function does not currently handle csr correctly... :param set domains: domains to get a certificate :param csr: CSR must contain requested domains, the key used to generate this CSR can be different than self.authkey :type csr: :class:`CSR` :returns: cert_key, cert_path, chain_path :rtype: `tuple` of (:class:`letsencrypt.client.le_util.Key`, str, str) """ if self.auth_handler is None: msg = ("Unable to obtain certificate because authenticator is " "not set.") logging.warning(msg) raise errors.LetsEncryptClientError(msg) if self.account.regr is None: raise errors.LetsEncryptClientError( "Please register with the ACME server first.") # Perform Challenges/Get Authorizations authzr = self.auth_handler.get_authorizations(domains) # Create CSR from names cert_key = crypto_util.init_save_key( self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr( cert_key, domains, self.config.cert_dir) # Retrieve certificate certr = self.network.request_issuance( jose.ComparableX509( M2Crypto.X509.load_request_der_string(csr.data)), authzr) # Save Certificate cert_path, chain_path = self.save_certificate( certr, self.config.cert_path, self.config.chain_path) revoker.Revoker.store_cert_key( cert_path, self.account.key.file, self.config) return cert_key, cert_path, chain_path
def _get_cert(self, uri): """Returns certificate from URI. :param str uri: URI of certificate :returns: tuple of the form (response, :class:`letsencrypt.acme.jose.ComparableX509`) :rtype: tuple """ content_type = self.DER_CONTENT_TYPE # TODO: make it a param response = self._get(uri, headers={'Accept': content_type}, content_type=content_type) return response, jose.ComparableX509( M2Crypto.X509.load_cert_der_string(response.content))
def acme_certificate(self, csr_der): """Handle ACME "certificate" phase. :param str csr_der: CSR in DER format. :returns: ACME "certificate" message. :rtype: :class:`letsencrypt.acme.message.Certificate` """ logging.info("Preparing and sending CSR...") return self.network.send_and_receive_expected( messages.CertificateRequest.create( csr=jose.ComparableX509( M2Crypto.X509.load_request_der_string(csr_der)), key=jose.HashableRSAKey( Crypto.PublicKey.RSA.importKey(self.authkey.pem))), messages.Certificate)
def request_issuance(self, csr, authzrs): """Request issuance. :param csr: CSR :type csr: `M2Crypto.X509.Request` wrapped in `.ComparableX509` :param authzrs: `list` of `.AuthorizationResource` :returns: Issued certificate :rtype: `.messages2.CertificateResource` """ assert authzrs, "Authorizations list is empty" logging.debug("Requesting issuance...") # TODO: assert len(authzrs) == number of SANs req = messages2.CertificateRequest( csr=csr, authorizations=tuple(authzr.uri for authzr in authzrs)) content_type = self.DER_CONTENT_TYPE # TODO: add 'cert_type 'argument response = self._post( authzrs[0].new_cert_uri, # TODO: acme-spec #90 self._wrap_in_jws(req), content_type=content_type, headers={'Accept': content_type}) cert_chain_uri = response.links.get('up', {}).get('url') try: uri = response.headers['Location'] except KeyError: raise errors.NetworkError('"Location" Header missing') return messages2.CertificateResource( uri=uri, authzrs=authzrs, cert_chain_uri=cert_chain_uri, body=jose.ComparableX509( M2Crypto.X509.load_cert_der_string(response.content)))
import pkg_resources import unittest import M2Crypto import mock import requests from letsencrypt.acme import challenges from letsencrypt.acme import jose from letsencrypt.acme import messages2 from letsencrypt.client import account from letsencrypt.client import errors CERT = jose.ComparableX509( M2Crypto.X509.load_cert_string( pkg_resources.resource_string(__name__, os.path.join('testdata', 'cert.pem')))) CERT2 = jose.ComparableX509( M2Crypto.X509.load_cert_string( pkg_resources.resource_string(__name__, os.path.join('testdata', 'cert-san.pem')))) CSR = jose.ComparableX509( M2Crypto.X509.load_request_string( pkg_resources.resource_string(__name__, os.path.join('testdata', 'csr.pem')))) KEY = jose.JWKRSA.load( pkg_resources.resource_string('letsencrypt.acme.jose', os.path.join('testdata', 'rsa512_key.pem'))) KEY2 = jose.JWKRSA.load( pkg_resources.resource_string('letsencrypt.acme.jose',
import pkg_resources import unittest import Crypto.PublicKey.RSA import M2Crypto from letsencrypt.acme import challenges from letsencrypt.acme import errors from letsencrypt.acme import jose from letsencrypt.acme import other KEY = Crypto.PublicKey.RSA.importKey(pkg_resources.resource_string( 'letsencrypt.client.tests', 'testdata/rsa256_key.pem')) CERT = jose.ComparableX509(M2Crypto.X509.load_cert( pkg_resources.resource_filename( 'letsencrypt.client.tests', 'testdata/cert.pem'))) CSR = jose.ComparableX509(M2Crypto.X509.load_request( pkg_resources.resource_filename( 'letsencrypt.client.tests', 'testdata/csr.pem'))) CSR2 = jose.ComparableX509(M2Crypto.X509.load_request( pkg_resources.resource_filename( 'letsencrypt.acme.jose', 'testdata/csr2.pem'))) class MessageTest(unittest.TestCase): """Tests for letsencrypt.acme.messages.Message.""" def setUp(self): # pylint: disable=missing-docstring,too-few-public-methods from letsencrypt.acme.messages import Message
"""Tests for letsencrypt.acme.challenges.""" import os import pkg_resources import unittest import Crypto.PublicKey.RSA import M2Crypto from letsencrypt.acme import jose from letsencrypt.acme import other CERT = jose.ComparableX509( M2Crypto.X509.load_cert( pkg_resources.resource_filename('letsencrypt.client.tests', 'testdata/cert.pem'))) KEY = Crypto.PublicKey.RSA.importKey( pkg_resources.resource_string('letsencrypt.client.tests', os.path.join('testdata', 'rsa256_key.pem'))) class SimpleHTTPSTest(unittest.TestCase): def setUp(self): from letsencrypt.acme.challenges import SimpleHTTPS self.msg = SimpleHTTPS( token='evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA') self.jmsg = { 'type': 'simpleHttps', 'token': 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA', } def test_to_json(self):
def _get_cert(self, uri): content_type = self.DER_CONTENT_TYPE # TODO: make it a param response = self._get(uri, headers={'Accept': content_type}, content_type=content_type) return response, jose.ComparableX509( M2Crypto.X509.load_cert_der_string(response.content))