Пример #1
0
    def register(self, new_reg=None):
        """Register.

        :param .NewRegistration new_reg:

        :returns: Registration Resource.
        :rtype: `.RegistrationResource`

        :raises .UnexpectedUpdate:

        """
        new_reg = messages.NewRegistration() if new_reg is None else new_reg
        assert isinstance(new_reg, messages.NewRegistration)

        response = self.net.post(self.directory[new_reg], new_reg)
        # TODO: handle errors
        assert response.status_code == http_client.CREATED

        # "Instance of 'Field' has no key/contact member" bug:
        # pylint: disable=no-member
        regr = self._regr_from_response(response)
        if (regr.body.key != self.key.public_key()
                or regr.body.contact != new_reg.contact):
            raise errors.UnexpectedUpdate(regr)

        return regr
Пример #2
0
    def setUp(self):
        self.response = mock.MagicMock(
            ok=True, status_code=http_client.OK, headers={}, links={})
        self.net = mock.MagicMock()
        self.net.post.return_value = self.response
        self.net.get.return_value = self.response

        self.identifier = messages.Identifier(
            typ=messages.IDENTIFIER_FQDN, value='example.com')

        # Registration
        self.contact = ('mailto:[email protected]', 'tel:+12025551212')
        reg = messages.Registration(
            contact=self.contact, key=KEY.public_key())
        self.new_reg = messages.NewRegistration(**dict(reg))
        self.regr = messages.RegistrationResource(
            body=reg, uri='https://www.letsencrypt-demo.org/acme/reg/1')

        # Authorization
        authzr_uri = 'https://www.letsencrypt-demo.org/acme/authz/1'
        challb = messages.ChallengeBody(
            uri=(authzr_uri + '/1'), status=messages.STATUS_VALID,
            chall=challenges.DNS(token=jose.b64decode(
                'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA')))
        self.challr = messages.ChallengeResource(
            body=challb, authzr_uri=authzr_uri)
        self.authz = messages.Authorization(
            identifier=messages.Identifier(
                typ=messages.IDENTIFIER_FQDN, value='example.com'),
            challenges=(challb,), combinations=None)
        self.authzr = messages.AuthorizationResource(
            body=self.authz, uri=authzr_uri)
Пример #3
0
 def register(self, new_reg=None):
     self._registered = True
     if new_reg is None:
         new_reg = messages.NewRegistration()
     self.regr = messages.RegistrationResource(body=messages.Registration(
         contact=new_reg.contact, agreement=new_reg.agreement))
     return succeed(self.regr)
Пример #4
0
    def setUp(self):
        self.response = mock.MagicMock(ok=True,
                                       status_code=http_client.OK,
                                       headers={},
                                       links={})
        self.net = mock.MagicMock()
        self.net.post.return_value = self.response
        self.net.get.return_value = self.response

        self.directory = messages.Directory({
            messages.NewRegistration:
            'https://www.letsencrypt-demo.org/acme/new-reg',
            messages.Revocation:
            'https://www.letsencrypt-demo.org/acme/revoke-cert',
        })

        from acme.client import Client
        self.client = Client(directory=self.directory,
                             key=KEY,
                             alg=jose.RS256,
                             net=self.net)

        self.identifier = messages.Identifier(typ=messages.IDENTIFIER_FQDN,
                                              value='example.com')

        # Registration
        self.contact = ('mailto:[email protected]', 'tel:+12025551212')
        reg = messages.Registration(contact=self.contact, key=KEY.public_key())
        self.new_reg = messages.NewRegistration(**dict(reg))
        self.regr = messages.RegistrationResource(
            body=reg,
            uri='https://www.letsencrypt-demo.org/acme/reg/1',
            new_authzr_uri='https://www.letsencrypt-demo.org/acme/new-reg',
            terms_of_service='https://www.letsencrypt-demo.org/tos')

        # Authorization
        authzr_uri = 'https://www.letsencrypt-demo.org/acme/authz/1'
        challb = messages.ChallengeBody(
            uri=(authzr_uri + '/1'),
            status=messages.STATUS_VALID,
            chall=challenges.DNS(token=jose.b64decode(
                'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA')))
        self.challr = messages.ChallengeResource(body=challb,
                                                 authzr_uri=authzr_uri)
        self.authz = messages.Authorization(identifier=messages.Identifier(
            typ=messages.IDENTIFIER_FQDN, value='example.com'),
                                            challenges=(challb, ),
                                            combinations=None)
        self.authzr = messages.AuthorizationResource(
            body=self.authz,
            uri=authzr_uri,
            new_cert_uri='https://www.letsencrypt-demo.org/acme/new-cert')

        # Request issuance
        self.certr = messages.CertificateResource(
            body=messages_test.CERT,
            authzrs=(self.authzr, ),
            uri='https://www.letsencrypt-demo.org/acme/cert/1',
            cert_chain_uri='https://www.letsencrypt-demo.org/ca')
Пример #5
0
def _monkeypatch_register(self, new_reg=None):
    new_reg = new_reg or messages.NewRegistration()
    response = self.net.post(self.directory[new_reg],
                             new_reg,
                             check_response=False)
    loc = None
    if response.status_code == client.http_client.CONFLICT and response.headers.get(
            'Location'):
        reg = messages.UpdateRegistration()
        loc = response.headers.get('Location')
        response = self.net.post(loc, reg)
    return self._regr_from_response(response, uri=loc)
Пример #6
0
def registerNewAccount(conf, key):
    """
    Attempt to create a new account on the ACME server
    with the key. No problem if it fails because this
    kye is already used.
    """
    LOG.info("Registering with ACME server with the new key")
    newReg = messages.NewRegistration(contact=tuple(conf['info']),
                                      key=key.public_key())
    acme_client = client.Client(conf['directory'], key)
    registration_resource = acme_client.register(newReg)
    LOG.info("Agreeing on the TOS on your behalf")
    acme_client.agree_to_tos(registration_resource)
Пример #7
0
def create_registration():
    global privkey, regr
    privkey = rsa.generate_private_key(public_exponent=65537,
                                       key_size=BITS,
                                       backend=default_backend())
    key = jose.JWKRSA(key=privkey)
    net = ClientNetwork(key)
    directory = net.get(DIRECTORY_URL).json()
    acme = client.ClientV2(directory, net)
    regbody = dict(
        messages.Registration(contact=('mailto:[email protected]', ),
                              terms_of_service_agreed=True,
                              key=key.public_key()))
    #NEED TO SAVE REGBODY VARIABLE TO FILE
    regr = acme.new_account(messages.NewRegistration(**regbody))
Пример #8
0
    def register(self, new_reg=None):
        """Register.

        :param .NewRegistration new_reg:

        :returns: Registration Resource.
        :rtype: `.RegistrationResource`

        """
        new_reg = messages.NewRegistration() if new_reg is None else new_reg
        response = self._post(self.directory[new_reg], new_reg)
        # TODO: handle errors
        assert response.status_code == http_client.CREATED

        # "Instance of 'Field' has no key/contact member" bug:
        return self._regr_from_response(response)
Пример #9
0
    def register(self, new_reg=None):
        """
        Create a new registration with the ACME server.

        :param ~acme.messages.NewRegistration new_reg: The registration message
            to use, or ``None`` to construct one.

        :return: The registration resource.
        :rtype: Deferred[`~acme.messages.RegistrationResource`]
        """
        if new_reg is None:
            new_reg = messages.NewRegistration()
        action = LOG_ACME_REGISTER(registration=new_reg)
        with action.context():
            return (DeferredContext(
                self.update_registration(
                    new_reg, uri=self.directory[new_reg])).addErrback(
                        self._maybe_registered, new_reg).addCallback(
                            tap(lambda r: action.add_success_fields(
                                registration=r))).addActionFinish())
Пример #10
0
    def _get_or_create_account(self):
        """Register account if not already done, else just return ACME client updated with existing account"""
        logger.info("Registering account...")

        ca_key = serialization.load_pem_private_key(
            data=self.account_key.read_bytes(),
            password=None,
            backend=default_backend(),
        )
        acc_key = jose.JWKRSA(key=ca_key)

        # Register account and accept TOS
        client_network = client.ClientNetwork(acc_key, user_agent=USER_AGENT)
        directory = messages.Directory.from_json(client_network.get(self.ca_api + '/directory').json())
        client_acme = client.ClientV2(directory=directory, net=client_network)

        try:
            # Creates account with contact information.
            # Terms of Service URL is in client_acme.directory.meta.terms_of_service
            client_acme.new_account(
                messages.NewRegistration.from_data(
                    email=self.contact_email,
                    terms_of_service_agreed=True,
                )
            )
            logger.info("New account successfully created!")
        except errors.ConflictError:
            logger.info("Account already registered!")
            # retrieve existing account information
            account_registration = messages.NewRegistration(key=acc_key.public_key(), only_return_existing=True)

            # TODO migrate to public API when available in ACME module
            #  reproduce code of client_acme.new_account but without throwing exception when account already exists
            response = client_acme._post(directory['newAccount'], account_registration)
            account_info = client_acme._regr_from_response(response)

            # assign registration information to existing client
            client_acme.net.account = account_info
        return client_acme
Пример #11
0
    async def connect(cls,
                      directory: str,
                      key: crypto.PrivateKey,
                      *,
                      loop: _T_AIO_LOOP = None) -> 'AsyncmeClient':
        """
        Connect to an ACME server.

        :param directory: The URI of the ACME server's directory.
        :param key: Private key used for interacting with the ACME server.
        :param loop: Event loop.

        :return: A new instance of ``AsyncmeClient`` which has been
         registered against the given ACME server, if the key has not already
         been registered.
        """

        # Determine the JWS 'alg' Type for the Given Key
        # RSA
        if key.algorithm is crypto.KeyAlgorithmType.RSA:
            if key.size / 8 == 256:
                alg = jose.jwa.RS256
            elif key.size / 8 == 384:
                alg = jose.jwa.RS384
            elif key.size / 8 == 512:
                alg = jose.jwa.RS512
            else:
                raise ValueError("RSA key size of {} "
                                 "is unsupported".format(key.size))

        # ECDSA
        elif key.algorithm is crypto.KeyAlgorithmType.ECDSA:
            if key.size == 256:
                alg = jose.jwa.ES256
            elif key.size == 384:
                alg = jose.jwa.ES384
            elif key.size == 521:
                alg = jose.jwa.ES512
            else:
                raise ValueError("ECDSA key size of {} "
                                 "is unsupported".format(key.size))

        # Other
        else:
            raise ValueError("Unsupported private key type, must "
                             "be RSA or ECDSA")

        # Convert Key
        password = os.urandom(255)
        acme_key = jose.JWKRSA(key=serialization.load_der_private_key(
            key.to_bytes(encoding=crypto.EncodingType.DER, password=password),
            password, default_backend()))

        # Get Async. Loop
        loop = loop or asyncio.get_event_loop()

        # Instantiate Underlying Client
        # (and make the initial connection to the ACME server)
        try:
            client = await ExecutorClient.connect(
                directory=directory,
                key=acme_key,
                alg=alg,
                net=ExtendedNetwork(
                    key=acme_key,
                    alg=alg,
                    user_agent='asyncme-python-{}'.format(ASYNCME_VERSION)),
                loop=loop)
        except TypeError:
            raise ValueError("Invalid ACME directory given")

        # Client Registration
        try:
            regr = await client.register()
        except errors.Error as e:

            # The upstream client currently has no way to "recover" a lost
            # registration resource, thus we must resort to the tactics below.

            if "key is already in use" in str(e):

                LOG.debug("Key already in use: attempting to recover "
                          "registration resource.")

                # (1) Send a Post in Attempt to Register the Client
                #     and Get a 409 Back in Response with Location
                #     Header set.

                post = functools.partial(client.net.post,
                                         client.directory['new-reg'],
                                         messages.NewRegistration(),
                                         checked=False)
                response = await loop.run_in_executor(None, post)
                assert response.status_code == 409

                # (2) Manually create a new Registration Resource and
                #     send an empty registration update.
                #     (per draft-ietf-acme-acme-03#section-6.2)

                regr = messages.RegistrationResource(
                    uri=response.headers.get("location"))

                # Empty Update
                regr = await client._send_recv_regr(
                    regr, body=messages.UpdateRegistration())

            else:
                raise RuntimeError(e)

        return cls(client, regr)