def _authzr_from_response(self, response, identifier=None, uri=None): authzr = messages.AuthorizationResource( body=messages.Authorization.from_json(response.json()), uri=response.headers.get('Location', uri)) if identifier is not None and authzr.body.identifier != identifier: raise errors.UnexpectedUpdate(authzr) return authzr
def _mock_poll_solve_one_chall(self, authzr, desired_status): # pylint: disable=no-self-use """Dummy method that solves one chall at a time to desired_status. When all are solved.. it changes authzr.status to desired_status """ new_challbs = authzr.body.challenges for challb in authzr.body.challenges: if challb.status != desired_status: new_challbs = tuple( challb_temp if challb_temp != challb else acme_util.chall_to_challb(challb.chall, desired_status) for challb_temp in authzr.body.challenges ) break if all(test_challb.status == desired_status for test_challb in new_challbs): status_ = desired_status else: status_ = authzr.body.status new_authzr = messages.AuthorizationResource( uri=authzr.uri, new_cert_uri=authzr.new_cert_uri, body=messages.Authorization( identifier=authzr.body.identifier, challenges=new_challbs, combinations=authzr.body.combinations, status=status_, ), ) return (new_authzr, "response")
def setUp(self): super(ClientV2Test, self).setUp() self.directory = DIRECTORY_V2 from acme.client import ClientV2 self.client = ClientV2(self.directory, self.net) self.new_reg = self.new_reg.update(terms_of_service_agreed=True) self.authzr_uri2 = 'https://www.letsencrypt-demo.org/acme/authz/2' self.authz2 = self.authz.update(identifier=messages.Identifier( typ=messages.IDENTIFIER_FQDN, value='www.example.com'), status=messages.STATUS_PENDING) self.authzr2 = messages.AuthorizationResource( body=self.authz2, uri=self.authzr_uri2) self.order = messages.Order( identifiers=(self.authz.identifier, self.authz2.identifier), status=messages.STATUS_PENDING, authorizations=(self.authzr.uri, self.authzr_uri2), finalize='https://www.letsencrypt-demo.org/acme/acct/1/order/1/finalize') self.orderr = messages.OrderResource( body=self.order, uri='https://www.letsencrypt-demo.org/acme/acct/1/order/1', authorizations=[self.authzr, self.authzr2], csr_pem=CSR_SAN_PEM)
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)
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')
def _mock_deactivate(authzr): if authzr.body.status == messages.STATUS_VALID: if authzr.body.identifier.value == "is_valid_but_will_fail": raise acme_errors.Error("Mock deactivation ACME error") authzb = authzr.body.update(status=messages.STATUS_DEACTIVATED) authzr = messages.AuthorizationResource(body=authzb) else: # pragma: no cover raise errors.Error("Can't deactivate non-valid authz") return authzr
def setUp(self): self.verify_ssl = mock.MagicMock() self.wrap_in_jws = mock.MagicMock(return_value=mock.sentinel.wrapped) from acme.client import Client self.net = Client( new_reg_uri='https://www.letsencrypt-demo.org/acme/new-reg', key=KEY, alg=jose.RS256, verify_ssl=self.verify_ssl) self.nonce = jose.b64encode('Nonce') self.net._nonces.add(self.nonce) # pylint: disable=protected-access self.response = mock.MagicMock(ok=True, status_code=httplib.OK) self.response.headers = {} self.response.links = {} self.post = mock.MagicMock(return_value=self.response) self.get = mock.MagicMock(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(), recovery_token='t') 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='foo')) 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')
def test_poll_authorizations_success(self): deadline = datetime.datetime(9999, 9, 9) updated_authz2 = self.authz2.update(status=messages.STATUS_VALID) updated_authzr2 = messages.AuthorizationResource( body=updated_authz2, uri=self.authzr_uri2) updated_orderr = self.orderr.update(authorizations=[self.authzr, updated_authzr2]) self.response.json.side_effect = ( self.authz.to_json(), self.authz2.to_json(), updated_authz2.to_json()) self.assertEqual(self.client.poll_authorizations(self.orderr, deadline), updated_orderr)
def submit_order(self, key, names): """ Create a new order and return the OrderResource for that order with all the authorizations resolved. It will automatically create a new private key and CSR for the domain 'names'. :param key: Key for the future certificate. :param list of str names: Sequence of DNS names for which to request a new certificate. :return: The new authorization resource. :rtype: Deferred[`~acme.messages.Order`] """ # certbot helper API needs PEM. pem_key = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) csr_pem = make_csr(pem_key, names) identifiers = [fqdn_identifier(name) for name in names] message = messages.NewOrder(identifiers=identifiers) response = yield self._client.post(self.directory.newOrder, message) self._expect_response(response, [http.CREATED]) order_uri = self._maybe_location(response) authorizations = [] order_body = yield response.json() for uri in order_body['authorizations']: # We do a POST-as-GET respose = yield self._client.post(uri, obj=None) self._expect_response(response, [http.CREATED]) body = yield respose.json() authorizations.append( messages.AuthorizationResource( body=messages.Authorization.from_json(body), uri=uri, )) order = messages.OrderResource( body=messages.Order.from_json(order_body), uri=order_uri, authorizations=authorizations, csr_pem=csr_pem, ) # TODO: Not sure if all these sanity checks are required. for identifier in order.body.identifiers: if identifier not in identifiers: raise errors.UnexpectedUpdate(order) defer.returnValue(order)
def poll(self, authzr): challenges = [ self._challenges[u] for u in self._authorizations[authzr.body.identifier].values() ] status = (messages.STATUS_VALID if any( c.status == messages.STATUS_VALID for c in challenges) else messages.STATUS_PENDING) return succeed( (messages.AuthorizationResource(body=messages.Authorization( status=status, challenges=challenges, combinations=[[n] for n in range(len(challenges))])), 1.0))
def _parse_authorization(cls, response, uri=None): """ Parse an authorization resource. """ links = _parse_header_links(response) try: new_cert_uri = links[u'next'][u'url'] except KeyError: raise errors.ClientError('"next" link missing') return (response.json().addCallback( lambda body: messages.AuthorizationResource( body=messages.Authorization.from_json(body), uri=cls._maybe_location(response, uri=uri), new_cert_uri=new_cert_uri)))
def request_challenges(self, identifier): self._authorizations[identifier] = challenges = OrderedDict() for chall_type in self._challenge_types: uuid = unicode(uuid4()) challb = messages.ChallengeBody(chall=chall_type(token=b'token'), uri=uuid, status=messages.STATUS_PENDING) challenges[chall_type] = uuid self._challenges[uuid] = challb return succeed( messages.AuthorizationResource(body=messages.Authorization( identifier=identifier, status=messages.STATUS_PENDING, challenges=[self._challenges[u] for u in challenges.values()], combinations=[[n] for n in range(len(challenges))])))
def _authzr_from_response(self, response, identifier, uri=None, new_cert_uri=None): # pylint: disable=no-self-use if new_cert_uri is None: try: new_cert_uri = response.links['next']['url'] except KeyError: raise errors.ClientError('"next" link missing') authzr = messages.AuthorizationResource( body=messages.Authorization.from_json(response.json()), uri=response.headers.get('Location', uri), new_cert_uri=new_cert_uri) if authzr.body.identifier != identifier: raise errors.UnexpectedUpdate(authzr) return authzr
def gen_authzr(authz_status: messages.Status, domain: str, challs: Iterable[challenges.Challenge], statuses: Iterable[messages.Status], combos: bool = True) -> messages.AuthorizationResource: """Generate an authorization resource. :param authz_status: Status object :type authz_status: :class:`acme.messages.Status` :param list challs: Challenge objects :param list statuses: status of each challenge object :param bool combos: Whether or not to add combinations """ challbs = tuple( chall_to_challb(chall, status) for chall, status in zip(challs, statuses)) authz_kwargs = { "identifier": messages.Identifier(typ=messages.IDENTIFIER_FQDN, value=domain), "challenges": challbs, } if combos: authz_kwargs.update({"combinations": gen_combos(challbs)}) if authz_status == messages.STATUS_VALID: authz_kwargs.update({ "status": authz_status, "expires": datetime.datetime.now() + datetime.timedelta(days=31), }) else: authz_kwargs.update({ "status": authz_status, }) return messages.AuthorizationResource( uri="https://trusted.ca/new-authz-resource", body=messages.Authorization(**authz_kwargs))