Exemple #1
0
 def test_it(self):
     host, port = self.server.socket.getsockname()[:2]
     cert = crypto_util.probe_sni(b'localhost',
                                  host=host,
                                  port=port,
                                  timeout=1)
     self.assertEqual(jose.ComparableX509(cert),
                      jose.ComparableX509(self.certs[b'localhost'][1]))
Exemple #2
0
 def test_connect(self):
     socknames = self.servers.getsocknames()
     # connect to all addresses
     for sockname in socknames:
         host, port = sockname[:2]
         cert = crypto_util.probe_sni(b'localhost',
                                      host=host,
                                      port=port,
                                      timeout=1)
         self.assertEqual(jose.ComparableX509(cert),
                          jose.ComparableX509(self.certs[b'localhost'][1]))
Exemple #3
0
def revoke(config, unused_plugins):  # TODO: coop with renewal config
    """Revoke a previously obtained certificate.

    :param config: Configuration object
    :type config: interfaces.IConfig

    :param unused_plugins: List of plugins (deprecated)
    :type unused_plugins: `list` of `str`

    :returns: `None` or string indicating error in case of error
    :rtype: None or str

    """
    # For user-agent construction
    config.installer = config.authenticator = "None"
    if config.key_path is not None:  # revocation by cert key
        logger.debug("Revoking %s using cert key %s",
                     config.cert_path[0], config.key_path[0])
        crypto_util.verify_cert_matches_priv_key(config.cert_path[0], config.key_path[0])
        key = jose.JWK.load(config.key_path[1])
    else:  # revocation by account key
        logger.debug("Revoking %s using Account Key", config.cert_path[0])
        acc, _ = _determine_account(config)
        key = acc.key
    acme = client.acme_from_config_key(config, key)
    cert = crypto_util.pyopenssl_load_certificate(config.cert_path[1])[0]
    logger.debug("Reason code for revocation: %s", config.reason)

    try:
        acme.revoke(jose.ComparableX509(cert), config.reason)
        _delete_if_appropriate(config)
    except acme_errors.ClientError as e:
        return str(e)

    display_ops.success_revocation(config.cert_path[0])
Exemple #4
0
    async def request_cert(self, csr: crypto.x509CertSignReq) -> AcmeCert:
        """
        Request the issuance of a certificate for the given CSR.

        :param csr: The CSR to fulfill.

        :return: The newly issued x509 certificate.
        """

        # (1) First get a list of the authorization resources in the CSR
        #     by inspecting the SAN (we current do not look at the CN)
        domains = csr.get_subj_alt_dns_names()
        authzrs = []

        for domain in domains:
            new_authzr = await self._client.request_domain_challenges(domain)
            authzrs.append(new_authzr)

        # (2) Convert the CSR
        acme_csr = jose.ComparableX509(
            OpenSSL.crypto.load_certificate_request(
                OpenSSL.crypto.FILETYPE_PEM,
                csr.to_bytes(encoding=crypto.EncodingType.PEM)))

        # (3) Request the Issuance
        acme_cert = await self._client.request_issuance(acme_csr, authzrs)
        py_openssl_cert = acme_cert.body.wrapped

        # (4) Covert the Issuance Object
        cert = AcmeCert(OpenSSL.crypto.dump_certificate(
            OpenSSL.crypto.FILETYPE_PEM, py_openssl_cert),
                        acme_uri=acme_cert.uri,
                        issuer_uri=acme_cert.cert_chain_uri)

        return cert
Exemple #5
0
 def _check_obtain_certificate(self):
     self.client.auth_handler.get_authorizations.assert_called_once_with(self.eg_domains)
     self.acme.request_issuance.assert_called_once_with(
         jose.ComparableX509(OpenSSL.crypto.load_certificate_request(
             OpenSSL.crypto.FILETYPE_ASN1, CSR_SAN)),
         self.client.auth_handler.get_authorizations())
     self.acme.fetch_chain.assert_called_once_with(mock.sentinel.certr)
Exemple #6
0
def issue(client, authzs, cert_output=None):
    """Given a list of authzs that are being processed by the server,
       wait for them to be ready, then request issuance of a cert with a random
       key for the given domains.

       If cert_output is provided, write the cert as a PEM file to that path."""
    csr = make_csr([authz.body.identifier.value for authz in authzs])

    cert_resource = None
    try:
        cert_resource, _ = client.poll_and_request_issuance(
            jose.ComparableX509(csr), authzs)
    except acme_errors.PollError as error:
        # If we get a PollError, pick the first failed authz and turn it into a more
        # useful ValidationError that contains details we can look for in tests.
        for authz in error.updated:
            updated_authz = json.loads(urllib2.urlopen(authz.uri).read())
            domain = authz.body.identifier.value,
            for c in updated_authz['challenges']:
                if 'error' in c:
                    err = c['error']
                    raise ValidationError(domain, err['type'], err['detail'])
        # If none of the authz's had an error, just re-raise.
        raise
    if cert_output is not None:
        pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                              cert_resource.body)
        with open(cert_output, 'w') as f:
            f.write(pem)
    return cert_resource
Exemple #7
0
    def obtain_certificate_from_csr(self, domains, csr, authzr=None):
        """Obtain certificate.

        Internal function with precondition that `domains` are
        consistent with identifiers present in the `csr`.

        :param list domains: Domain names.
        :param .util.CSR csr: PEM-encoded Certificate Signing
            Request. The key used to generate this CSR can be different
            than `authkey`.
        :param list authzr: List of
            :class:`acme.messages.AuthorizationResource`

        :returns: `.CertificateResource` and certificate chain (as
            returned by `.fetch_chain`).
        :rtype: tuple

        """
        if self.auth_handler is None:
            msg = ("Unable to obtain certificate because authenticator is "
                   "not set.")
            logger.warning(msg)
            raise errors.Error(msg)
        if self.account.regr is None:
            raise errors.Error("Please register with the ACME server first.")

        logger.debug("CSR: %s, domains: %s", csr, domains)

        if authzr is None:
            authzr = self.auth_handler.get_authorizations(domains)

        certr = self.acme.request_issuance(
            jose.ComparableX509(
                OpenSSL.crypto.load_certificate_request(
                    OpenSSL.crypto.FILETYPE_PEM, csr.data)), authzr)

        notify = zope.component.getUtility(interfaces.IDisplay).notification
        retries = 0
        chain = None

        while retries <= 1:
            if retries:
                notify(
                    'Failed to fetch chain, please check your network '
                    'and continue',
                    pause=True)
            try:
                chain = self.acme.fetch_chain(certr)
                break
            except acme_errors.Error:
                logger.debug('Failed to fetch chain', exc_info=True)
                retries += 1

        if chain is None:
            raise acme_errors.Error(
                'Failed to fetch chain. You should not deploy the generated '
                'certificate, please rerun the command for a new one.')

        return certr, chain
Exemple #8
0
 def _check_obtain_certificate(self):
     self.client.auth_handler.get_authorizations.assert_called_once_with(
         ["example.com", "www.example.com"])
     self.network.request_issuance.assert_callend_once_with(
         jose.ComparableX509(
             M2Crypto.X509.load_request_der_string(CSR_SAN)),
         self.client.auth_handler.get_authorizations())
     self.network().fetch_chain.assert_called_once_with(mock.sentinel.certr)
Exemple #9
0
def _revoke(rawkey, rawcert):
    ns = ConfigNamespace(None)
    acme = acme_client.Client(
        ns.server,
        key=JWKRSA(key=serialization.load_pem_private_key(
            rawkey, password=None, backend=default_backend())))
    acme.revoke(
        jose.ComparableX509(
            OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                            rawcert)))
Exemple #10
0
 def test_revoke_with_key(self, mock_acme_client):
     server = 'foo.bar'
     self._call_no_clientmock(['--cert-path', CERT, '--key-path', KEY,
                              '--server', server, 'revoke'])
     with open(KEY) as f:
         mock_acme_client.Client.assert_called_once_with(
             server, key=jose.JWK.load(f.read()), net=mock.ANY)
     with open(CERT) as f:
         cert = crypto_util.pyopenssl_load_certificate(f.read())[0]
         mock_revoke = mock_acme_client.Client().revoke
         mock_revoke.assert_called_once_with(jose.ComparableX509(cert))
    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: Certificate, private key, and certificate chain (all
            PEM-encoded).
        :rtype: `tuple` of `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)

        cert_pem = certr.body.as_pem()
        chain_pem = None
        if certr.cert_chain_uri is not None:
            chain_pem = self.network.fetch_chain(certr)

        if chain_pem is None:
            # XXX: just to stop RenewableCert from complaining; this is
            #      probably not a good solution
            chain_pem = ""
        else:
            chain_pem = chain_pem.as_pem()

        return cert_pem, cert_key.pem, chain_pem
 def test_it(self):
     max_attempts = 5
     while max_attempts:
         max_attempts -= 1
         try:
             cert = crypto_util.probe_sni(b'localhost', b'0.0.0.0', self.port)
         except errors.Error:
             self.assertTrue(max_attempts > 0, "Timeout!")
             time.sleep(1)  # wait until thread starts
         else:
             self.assertEqual(jose.ComparableX509(cert),
                              test_util.load_comparable_cert('cert.pem'))
             break
Exemple #13
0
def revoke(args, config, unused_plugins):  # TODO: coop with renewal config
    """Revoke a previously obtained certificate."""
    if args.key_path is not None:  # revocation by cert key
        logger.debug("Revoking %s using cert key %s",
                     args.cert_path[0], args.key_path[0])
        acme = acme_client.Client(
            config.server, key=jose.JWK.load(args.key_path[1]))
    else:  # revocation by account key
        logger.debug("Revoking %s using Account Key", args.cert_path[0])
        acc, _ = _determine_account(args, config)
        # pylint: disable=protected-access
        acme = client._acme_from_config_key(config, acc.key)
    acme.revoke(jose.ComparableX509(crypto_util.pyopenssl_load_certificate(
        args.cert_path[1])[0]))
Exemple #14
0
    def request_issuance(self, csr, authzrs):
	print("Se ejecuta request issuance")
        """Request issuance.

        :param csr: CSR
        :type csr: `OpenSSL.crypto.X509Req` wrapped in `.ComparableX509`

        :param authzrs: `list` of `.AuthorizationResource`

        :returns: Issued certificate
        :rtype: `.messages.CertificateResource`

        """
        assert authzrs, "Authorizations list is empty"
        logger.debug("Requesting issuance...")
        # TODO: assert len(authzrs) == number of SANs

	#Checks if STARValidityCertbot file containing recurrent_cert_validity exists
	if os.path.isfile("../../STARValidityCertbot"):
		print "CLIENT.PY: STARValidityCertbot does exist"
		fileSTAR = open("../../STARValidityCertbot", "r")
		recurrent = True
		recurrent_cert_validity = int(float(fileSTAR.read()))  
	        req = messages.CertificateRequest(csr=csr, recurrent=recurrent,recurrent_cert_validity=recurrent_cert_validity)
	else:
		print "CLIENT.PY: STARValidityCertbot does NOT exist"
		req = messages.CertificateRequest(csr=csr)
	print "CSR sent to server is %s" % req 
        content_type = DER_CONTENT_TYPE  # TODO: add 'cert_type 'argument
        response = self.net.post(
            self.directory.new_cert,
            req,
            content_type=content_type,
            headers={'Accept': content_type})

        cert_chain_uri = response.links.get('up', {}).get('url')

        try:
            uri = response.headers['Location']
	    file=open('/root/certId','wr+')
	    file.write(uri)
	    print(uri)
        except KeyError:
            raise errors.ClientError('"Location" Header missing')

        return messages.CertificateResource(
            uri=uri, authzrs=authzrs, cert_chain_uri=cert_chain_uri,
            body=jose.ComparableX509(OpenSSL.crypto.load_certificate(
                OpenSSL.crypto.FILETYPE_ASN1, response.content)))
Exemple #15
0
    def test_renew(self, mock_c, mock_acc_storage, mock_pd):
        from letsencrypt import renewer

        test_cert = test_util.load_vector("cert-san.pem")
        for kind in ALL_FOUR:
            os.symlink(
                os.path.join("..", "..", "archive", "example.org",
                             kind + "1.pem"), getattr(self.test_rc, kind))
        fill_with_sample_data(self.test_rc)
        with open(self.test_rc.cert, "w") as f:
            f.write(test_cert)

        # Fails because renewalparams are missing
        self.assertFalse(renewer.renew(self.test_rc, 1))
        self.test_rc.configfile["renewalparams"] = {"some": "stuff"}
        # Fails because there's no authenticator specified
        self.assertFalse(renewer.renew(self.test_rc, 1))
        self.test_rc.configfile["renewalparams"]["rsa_key_size"] = "2048"
        self.test_rc.configfile["renewalparams"]["server"] = "acme.example.com"
        self.test_rc.configfile["renewalparams"]["authenticator"] = "fake"
        self.test_rc.configfile["renewalparams"]["tls_sni_01_port"] = "4430"
        self.test_rc.configfile["renewalparams"]["http01_port"] = "1234"
        self.test_rc.configfile["renewalparams"]["account"] = "abcde"
        self.test_rc.configfile["renewalparams"]["domains"] = ["example.com"]
        self.test_rc.configfile["renewalparams"]["config_dir"] = "config"
        self.test_rc.configfile["renewalparams"]["work_dir"] = "work"
        self.test_rc.configfile["renewalparams"]["logs_dir"] = "logs"
        mock_auth = mock.MagicMock()
        mock_pd.PluginsRegistry.find_all.return_value = {"apache": mock_auth}
        # Fails because "fake" != "apache"
        self.assertFalse(renewer.renew(self.test_rc, 1))
        self.test_rc.configfile["renewalparams"]["authenticator"] = "apache"
        mock_client = mock.MagicMock()
        # pylint: disable=star-args
        comparable_cert = jose.ComparableX509(CERT)
        mock_client.obtain_certificate.return_value = (mock.MagicMock(
            body=comparable_cert), [comparable_cert], mock.Mock(pem="key"),
                                                       mock.sentinel.csr)
        mock_c.return_value = mock_client
        self.assertEqual(2, renewer.renew(self.test_rc, 1))
        # TODO: We could also make several assertions about calls that should
        #       have been made to the mock functions here.
        mock_acc_storage().load.assert_called_once_with(account_id="abcde")
        mock_client.obtain_certificate.return_value = (mock.sentinel.certr, [],
                                                       mock.sentinel.key,
                                                       mock.sentinel.csr)
        # This should fail because the renewal itself appears to fail
        self.assertFalse(renewer.renew(self.test_rc, 1))
Exemple #16
0
    def test_it(self):
        max_attempts = 5
        for attempt in range(max_attempts):
            try:
                cert = crypto_util.probe_sni(b'localhost', b'0.0.0.0',
                                             self.port)
            except errors.Error:
                self.assertTrue(attempt + 1 < max_attempts, "Timeout!")
                time.sleep(1)  # wait until thread starts
            else:
                self.assertEqual(
                    jose.ComparableX509(cert),
                    test_util.load_comparable_cert('rsa2048_cert.pem'))
                break

            if attempt == 0:
                # the first attempt is always meant to fail, so we can test
                # the socket failure code-path for probe_sni, as well
                self.thread.start()
Exemple #17
0
def issue(client, authzs, cert_output=None):
    """Given a list of authzs that are being processed by the server,
       wait for them to be ready, then request issuance of a cert with a random
       key for the given domains.

       If cert_output is provided, write the cert as a PEM file to that path."""
    domains = [authz.body.identifier.value for authz in authzs]
    pkey = OpenSSL.crypto.PKey()
    pkey.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
    csr = OpenSSL.crypto.X509Req()
    csr.add_extensions([
        OpenSSL.crypto.X509Extension(
            'subjectAltName',
            critical=False,
            value=', '.join('DNS:' + d for d in domains).encode()),
    ])
    csr.set_pubkey(pkey)
    csr.set_version(2)
    csr.sign(pkey, 'sha256')

    cert_resource = None
    try:
        cert_resource, _ = client.poll_and_request_issuance(
            jose.ComparableX509(csr), authzs)
    except acme_errors.PollError as error:
        # If we get a PollError, pick the first failed authz and turn it into a more
        # useful ValidationError that contains details we can look for in tests.
        for authz in error.updated:
            updated_authz = json.loads(urllib2.urlopen(authz.uri).read())
            domain = authz.body.identifier.value,
            for c in updated_authz['challenges']:
                if 'error' in c:
                    err = c['error']
                    raise ValidationError(domain, err['type'], err['detail'])
        # If none of the authz's had an error, just re-raise.
        raise
    if cert_output is not None:
        pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                              cert_resource.body)
        with open(cert_output, 'w') as f:
            f.write(pem)
    return cert_resource
Exemple #18
0
    def request_issuance(self, csr, authzrs):
        """Request issuance.

        :param csr: CSR
        :type csr: `OpenSSL.crypto.X509Req` wrapped in `.ComparableX509`

        :param authzrs: `list` of `.AuthorizationResource`

        :returns: Issued certificate
        :rtype: `.messages.CertificateResource`

        """
        assert authzrs, "Authorizations list is empty"
        logger.debug("Requesting issuance...")

        # TODO: assert len(authzrs) == number of SANs
        req = messages.CertificateRequest(
            csr=csr, authorizations=tuple(authzr.uri for authzr in authzrs))

        content_type = self.DER_CONTENT_TYPE  # TODO: add 'cert_type 'argument
        response = self.net.post(
            authzrs[0].new_cert_uri,  # TODO: acme-spec #90
            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.ClientError('"Location" Header missing')

        return messages.CertificateResource(
            uri=uri,
            authzrs=authzrs,
            cert_chain_uri=cert_chain_uri,
            body=jose.ComparableX509(
                OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1,
                                                response.content)))
Exemple #19
0
import unittest

import Crypto.PublicKey.RSA
import M2Crypto

from acme import challenges
from acme import errors
from acme import jose
from acme import other

KEY = jose.HashableRSAKey(
    Crypto.PublicKey.RSA.importKey(
        pkg_resources.resource_string(
            'acme.jose', os.path.join('testdata', 'rsa512_key.pem'))))
CERT = jose.ComparableX509(
    M2Crypto.X509.load_cert(
        pkg_resources.resource_filename('letsencrypt.tests',
                                        os.path.join('testdata', 'cert.pem'))))
CSR = jose.ComparableX509(
    M2Crypto.X509.load_request(
        pkg_resources.resource_filename('letsencrypt.tests',
                                        os.path.join('testdata', 'csr.pem'))))
CSR2 = jose.ComparableX509(
    M2Crypto.X509.load_request(
        pkg_resources.resource_filename('acme.jose',
                                        os.path.join('testdata', 'csr2.pem'))))


class MessageTest(unittest.TestCase):
    """Tests for acme.messages.Message."""
    def setUp(self):
        # pylint: disable=missing-docstring,too-few-public-methods
Exemple #20
0
def load_csr(*names):
    """Load certificate request."""
    loader = _guess_loader(
        names[-1], OpenSSL.crypto.FILETYPE_PEM, OpenSSL.crypto.FILETYPE_ASN1)
    return jose.ComparableX509(OpenSSL.crypto.load_certificate_request(
        loader, load_vector(*names)))
import unittest

import M2Crypto
import mock
import requests

from acme import challenges
from acme import jose
from acme import jws as acme_jws
from acme import messages2

from letsencrypt import account
from letsencrypt 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('acme.jose',
                                  os.path.join('testdata', 'rsa512_key.pem')))
KEY2 = jose.JWKRSA.load(
    pkg_resources.resource_string('acme.jose',
Exemple #22
0
 def test_dvsni(self):
     cert = crypto_util.probe_sni(
         b'localhost', *self.server.socket.getsockname())
     self.assertEqual(jose.ComparableX509(cert),
                      jose.ComparableX509(self.certs[b'localhost'][1]))