mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 08:08:00 +02:00
JSONDeSerializable acme.messages.Resource.
Provides API necessary to implement JSON-based account storage as described at https://github.com/letsencrypt/lets-encrypt-preview/pull/362#issuecomment-97946817
This commit is contained in:
@@ -466,6 +466,7 @@ class Client(object): # pylint: disable=too-many-instance-attributes
|
|||||||
updated_authzr, response = self.poll(updated[authzr])
|
updated_authzr, response = self.poll(updated[authzr])
|
||||||
updated[authzr] = updated_authzr
|
updated[authzr] = updated_authzr
|
||||||
|
|
||||||
|
# pylint: disable=no-member
|
||||||
if updated_authzr.body.status != messages.STATUS_VALID:
|
if updated_authzr.body.status != messages.STATUS_VALID:
|
||||||
# push back to the priority queue, with updated retry_after
|
# push back to the priority queue, with updated retry_after
|
||||||
heapq.heappush(waiting, (self.retry_after(
|
heapq.heappush(waiting, (self.retry_after(
|
||||||
|
|||||||
+12
-20
@@ -5,7 +5,6 @@ import os
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import M2Crypto
|
|
||||||
import mock
|
import mock
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@@ -14,16 +13,9 @@ from acme import errors
|
|||||||
from acme import jose
|
from acme import jose
|
||||||
from acme import jws as acme_jws
|
from acme import jws as acme_jws
|
||||||
from acme import messages
|
from acme import messages
|
||||||
|
from acme import messages_test
|
||||||
|
|
||||||
|
|
||||||
CERT = jose.ComparableX509(M2Crypto.X509.load_cert_string(
|
|
||||||
pkg_resources.resource_string(
|
|
||||||
'acme.jose', os.path.join('testdata', 'cert.der')),
|
|
||||||
M2Crypto.X509.FORMAT_DER))
|
|
||||||
CSR = jose.ComparableX509(M2Crypto.X509.load_request_string(
|
|
||||||
pkg_resources.resource_string(
|
|
||||||
'acme.jose', os.path.join('testdata', 'csr.der')),
|
|
||||||
M2Crypto.X509.FORMAT_DER))
|
|
||||||
KEY = jose.JWKRSA.load(pkg_resources.resource_string(
|
KEY = jose.JWKRSA.load(pkg_resources.resource_string(
|
||||||
'acme.jose', os.path.join('testdata', 'rsa512_key.pem')))
|
'acme.jose', os.path.join('testdata', 'rsa512_key.pem')))
|
||||||
KEY2 = jose.JWKRSA.load(pkg_resources.resource_string(
|
KEY2 = jose.JWKRSA.load(pkg_resources.resource_string(
|
||||||
@@ -82,7 +74,7 @@ class ClientTest(unittest.TestCase):
|
|||||||
|
|
||||||
# Request issuance
|
# Request issuance
|
||||||
self.certr = messages.CertificateResource(
|
self.certr = messages.CertificateResource(
|
||||||
body=CERT, authzrs=(self.authzr,),
|
body=messages_test.CERT, authzrs=(self.authzr,),
|
||||||
uri='https://www.letsencrypt-demo.org/acme/cert/1',
|
uri='https://www.letsencrypt-demo.org/acme/cert/1',
|
||||||
cert_chain_uri='https://www.letsencrypt-demo.org/ca')
|
cert_chain_uri='https://www.letsencrypt-demo.org/ca')
|
||||||
|
|
||||||
@@ -380,27 +372,27 @@ class ClientTest(unittest.TestCase):
|
|||||||
self.assertRaises(errors.UnexpectedUpdate, self.net.poll, self.authzr)
|
self.assertRaises(errors.UnexpectedUpdate, self.net.poll, self.authzr)
|
||||||
|
|
||||||
def test_request_issuance(self):
|
def test_request_issuance(self):
|
||||||
self.response.content = CERT.as_der()
|
self.response.content = messages_test.CERT.as_der()
|
||||||
self.response.headers['Location'] = self.certr.uri
|
self.response.headers['Location'] = self.certr.uri
|
||||||
self.response.links['up'] = {'url': self.certr.cert_chain_uri}
|
self.response.links['up'] = {'url': self.certr.cert_chain_uri}
|
||||||
self._mock_post_get()
|
self._mock_post_get()
|
||||||
self.assertEqual(
|
self.assertEqual(self.certr, self.net.request_issuance(
|
||||||
self.certr, self.net.request_issuance(CSR, (self.authzr,)))
|
messages_test.CSR, (self.authzr,)))
|
||||||
# TODO: check POST args
|
# TODO: check POST args
|
||||||
|
|
||||||
def test_request_issuance_missing_up(self):
|
def test_request_issuance_missing_up(self):
|
||||||
self.response.content = CERT.as_der()
|
self.response.content = messages_test.CERT.as_der()
|
||||||
self.response.headers['Location'] = self.certr.uri
|
self.response.headers['Location'] = self.certr.uri
|
||||||
self._mock_post_get()
|
self._mock_post_get()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.certr.update(cert_chain_uri=None),
|
self.certr.update(cert_chain_uri=None),
|
||||||
self.net.request_issuance(CSR, (self.authzr,)))
|
self.net.request_issuance(messages_test.CSR, (self.authzr,)))
|
||||||
|
|
||||||
def test_request_issuance_missing_location(self):
|
def test_request_issuance_missing_location(self):
|
||||||
self._mock_post_get()
|
self._mock_post_get()
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
errors.ClientError, self.net.request_issuance,
|
errors.ClientError, self.net.request_issuance,
|
||||||
CSR, (self.authzr,))
|
messages_test.CSR, (self.authzr,))
|
||||||
|
|
||||||
@mock.patch('acme.client.datetime')
|
@mock.patch('acme.client.datetime')
|
||||||
@mock.patch('acme.client.time')
|
@mock.patch('acme.client.time')
|
||||||
@@ -484,10 +476,10 @@ class ClientTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_check_cert(self):
|
def test_check_cert(self):
|
||||||
self.response.headers['Location'] = self.certr.uri
|
self.response.headers['Location'] = self.certr.uri
|
||||||
self.response.content = CERT.as_der()
|
self.response.content = messages_test.CERT.as_der()
|
||||||
self._mock_post_get()
|
self._mock_post_get()
|
||||||
self.assertEqual(
|
self.assertEqual(self.certr.update(body=messages_test.CERT),
|
||||||
self.certr.update(body=CERT), self.net.check_cert(self.certr))
|
self.net.check_cert(self.certr))
|
||||||
|
|
||||||
# TODO: split here and separate test
|
# TODO: split here and separate test
|
||||||
self.response.headers['Location'] = 'foo'
|
self.response.headers['Location'] = 'foo'
|
||||||
@@ -495,7 +487,7 @@ class ClientTest(unittest.TestCase):
|
|||||||
errors.UnexpectedUpdate, self.net.check_cert, self.certr)
|
errors.UnexpectedUpdate, self.net.check_cert, self.certr)
|
||||||
|
|
||||||
def test_check_cert_missing_location(self):
|
def test_check_cert_missing_location(self):
|
||||||
self.response.content = CERT.as_der()
|
self.response.content = messages_test.CERT.as_der()
|
||||||
self._mock_post_get()
|
self._mock_post_get()
|
||||||
self.assertRaises(errors.ClientError, self.net.check_cert, self.certr)
|
self.assertRaises(errors.ClientError, self.net.check_cert, self.certr)
|
||||||
|
|
||||||
|
|||||||
+87
-31
@@ -51,6 +51,7 @@ class Error(jose.JSONObjectWithFields, Exception):
|
|||||||
else:
|
else:
|
||||||
return str(self.detail)
|
return str(self.detail)
|
||||||
|
|
||||||
|
|
||||||
class _Constant(jose.JSONDeSerializable):
|
class _Constant(jose.JSONDeSerializable):
|
||||||
"""ACME constant."""
|
"""ACME constant."""
|
||||||
__slots__ = ('name',)
|
__slots__ = ('name',)
|
||||||
@@ -107,31 +108,29 @@ class Identifier(jose.JSONObjectWithFields):
|
|||||||
value = jose.Field('value')
|
value = jose.Field('value')
|
||||||
|
|
||||||
|
|
||||||
class Resource(jose.ImmutableMap):
|
class Resource(jose.JSONObjectWithFields):
|
||||||
"""ACME Resource.
|
"""ACME Resource.
|
||||||
|
|
||||||
|
:ivar str uri: Location of the resource.
|
||||||
:ivar acme.messages.ResourceBody body: Resource body.
|
:ivar acme.messages.ResourceBody body: Resource body.
|
||||||
|
|
||||||
|
"""
|
||||||
|
body = jose.Field('body')
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceWithURI(Resource):
|
||||||
|
"""ACME Resource with URI.
|
||||||
|
|
||||||
:ivar str uri: Location of the resource.
|
:ivar str uri: Location of the resource.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
__slots__ = ('body', 'uri')
|
uri = jose.Field('uri') # no ChallengeResource.uri
|
||||||
|
|
||||||
|
|
||||||
class ResourceBody(jose.JSONObjectWithFields):
|
class ResourceBody(jose.JSONObjectWithFields):
|
||||||
"""ACME Resource Body."""
|
"""ACME Resource Body."""
|
||||||
|
|
||||||
|
|
||||||
class RegistrationResource(Resource):
|
|
||||||
"""Registration Resource.
|
|
||||||
|
|
||||||
:ivar acme.messages.Registration body:
|
|
||||||
:ivar str new_authzr_uri: URI found in the 'next' ``Link`` header
|
|
||||||
:ivar str terms_of_service: URL for the CA TOS.
|
|
||||||
|
|
||||||
"""
|
|
||||||
__slots__ = ('body', 'uri', 'new_authzr_uri', 'terms_of_service')
|
|
||||||
|
|
||||||
|
|
||||||
class Registration(ResourceBody):
|
class Registration(ResourceBody):
|
||||||
"""Registration Resource Body.
|
"""Registration Resource Body.
|
||||||
|
|
||||||
@@ -146,21 +145,59 @@ class Registration(ResourceBody):
|
|||||||
recovery_token = jose.Field('recoveryToken', omitempty=True)
|
recovery_token = jose.Field('recoveryToken', omitempty=True)
|
||||||
agreement = jose.Field('agreement', omitempty=True)
|
agreement = jose.Field('agreement', omitempty=True)
|
||||||
|
|
||||||
|
phone_prefix = 'tel:'
|
||||||
|
email_prefix = 'mailto:'
|
||||||
|
|
||||||
class ChallengeResource(Resource, jose.JSONObjectWithFields):
|
@classmethod
|
||||||
"""Challenge Resource.
|
def from_data(cls, phone=None, email=None, **kwargs):
|
||||||
|
"""Create registration resource from contact detauls."""
|
||||||
|
details = list(kwargs.pop('contact', ()))
|
||||||
|
if phone is not None:
|
||||||
|
details.append(cls.phone_prefix + phone)
|
||||||
|
if email is not None:
|
||||||
|
details.append(cls.email_prefix + email)
|
||||||
|
kwargs['contact'] = tuple(details)
|
||||||
|
return cls(**kwargs)
|
||||||
|
|
||||||
:ivar acme.messages.ChallengeBody body:
|
def _filter_contact(self, prefix):
|
||||||
:ivar str authzr_uri: URI found in the 'up' ``Link`` header.
|
return tuple(
|
||||||
|
detail[len(prefix):] for detail in self.contact
|
||||||
"""
|
if detail.startswith(prefix))
|
||||||
__slots__ = ('body', 'authzr_uri')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def uri(self): # pylint: disable=missing-docstring,no-self-argument
|
def phones(self):
|
||||||
# bug? 'method already defined line None'
|
"""All phones found in the ``contact`` field."""
|
||||||
# pylint: disable=function-redefined
|
return self._filter_contact(self.phone_prefix)
|
||||||
return self.body.uri
|
|
||||||
|
@property
|
||||||
|
def emails(self):
|
||||||
|
"""All emails found in the ``contact`` field."""
|
||||||
|
return self._filter_contact(self.email_prefix)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def phone(self):
|
||||||
|
"""Phone."""
|
||||||
|
assert len(self.phones) == 1
|
||||||
|
return self.phones[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def email(self):
|
||||||
|
"""Email."""
|
||||||
|
assert len(self.emails) == 1
|
||||||
|
return self.emails[0]
|
||||||
|
|
||||||
|
|
||||||
|
class RegistrationResource(ResourceWithURI):
|
||||||
|
"""Registration Resource.
|
||||||
|
|
||||||
|
:ivar acme.messages.Registration body:
|
||||||
|
:ivar str new_authzr_uri: URI found in the 'next' ``Link`` header
|
||||||
|
:ivar str terms_of_service: URL for the CA TOS.
|
||||||
|
|
||||||
|
"""
|
||||||
|
body = jose.Field('body', decoder=Registration.from_json)
|
||||||
|
new_authzr_uri = jose.Field('new_authzr_uri')
|
||||||
|
terms_of_service = jose.Field('terms_of_service', omitempty=True)
|
||||||
|
|
||||||
|
|
||||||
class ChallengeBody(ResourceBody):
|
class ChallengeBody(ResourceBody):
|
||||||
@@ -199,14 +236,21 @@ class ChallengeBody(ResourceBody):
|
|||||||
return getattr(self.chall, name)
|
return getattr(self.chall, name)
|
||||||
|
|
||||||
|
|
||||||
class AuthorizationResource(Resource):
|
class ChallengeResource(Resource, jose.JSONObjectWithFields):
|
||||||
"""Authorization Resource.
|
"""Challenge Resource.
|
||||||
|
|
||||||
:ivar acme.messages.Authorization body:
|
:ivar acme.messages.ChallengeBody body:
|
||||||
:ivar str new_cert_uri: URI found in the 'next' ``Link`` header
|
:ivar str authzr_uri: URI found in the 'up' ``Link`` header.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
__slots__ = ('body', 'uri', 'new_cert_uri')
|
body = jose.Field('body', decoder=ChallengeBody.from_json)
|
||||||
|
authzr_uri = jose.Field('authzr_uri')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def uri(self): # pylint: disable=missing-docstring,no-self-argument
|
||||||
|
# bug? 'method already defined line None'
|
||||||
|
# pylint: disable=function-redefined
|
||||||
|
return self.body.uri # pylint: disable=no-member
|
||||||
|
|
||||||
|
|
||||||
class Authorization(ResourceBody):
|
class Authorization(ResourceBody):
|
||||||
@@ -244,6 +288,17 @@ class Authorization(ResourceBody):
|
|||||||
for combo in self.combinations)
|
for combo in self.combinations)
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorizationResource(ResourceWithURI):
|
||||||
|
"""Authorization Resource.
|
||||||
|
|
||||||
|
:ivar acme.messages.Authorization body:
|
||||||
|
:ivar str new_cert_uri: URI found in the 'next' ``Link`` header
|
||||||
|
|
||||||
|
"""
|
||||||
|
body = jose.Field('body', decoder=Authorization.from_json)
|
||||||
|
new_cert_uri = jose.Field('new_cert_uri')
|
||||||
|
|
||||||
|
|
||||||
class CertificateRequest(jose.JSONObjectWithFields):
|
class CertificateRequest(jose.JSONObjectWithFields):
|
||||||
"""ACME new-cert request.
|
"""ACME new-cert request.
|
||||||
|
|
||||||
@@ -256,7 +311,7 @@ class CertificateRequest(jose.JSONObjectWithFields):
|
|||||||
authorizations = jose.Field('authorizations', decoder=tuple)
|
authorizations = jose.Field('authorizations', decoder=tuple)
|
||||||
|
|
||||||
|
|
||||||
class CertificateResource(Resource):
|
class CertificateResource(ResourceWithURI):
|
||||||
"""Certificate Resource.
|
"""Certificate Resource.
|
||||||
|
|
||||||
:ivar acme.jose.util.ComparableX509 body:
|
:ivar acme.jose.util.ComparableX509 body:
|
||||||
@@ -265,7 +320,8 @@ class CertificateResource(Resource):
|
|||||||
:ivar tuple authzrs: `tuple` of `AuthorizationResource`.
|
:ivar tuple authzrs: `tuple` of `AuthorizationResource`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
__slots__ = ('body', 'uri', 'cert_chain_uri', 'authzrs')
|
cert_chain_uri = jose.Field('cert_chain_uri')
|
||||||
|
authzrs = jose.Field('authzrs')
|
||||||
|
|
||||||
|
|
||||||
class Revocation(jose.JSONObjectWithFields):
|
class Revocation(jose.JSONObjectWithFields):
|
||||||
|
|||||||
+97
-2
@@ -4,14 +4,23 @@ import os
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
import M2Crypto
|
||||||
import mock
|
import mock
|
||||||
import pytz
|
import pytz
|
||||||
from Crypto.PublicKey import RSA
|
|
||||||
|
|
||||||
from acme import challenges
|
from acme import challenges
|
||||||
from acme import jose
|
from acme import jose
|
||||||
|
|
||||||
|
|
||||||
|
CERT = jose.ComparableX509(M2Crypto.X509.load_cert_string(
|
||||||
|
pkg_resources.resource_string(
|
||||||
|
'acme.jose', os.path.join('testdata', 'cert.der')),
|
||||||
|
M2Crypto.X509.FORMAT_DER))
|
||||||
|
CSR = jose.ComparableX509(M2Crypto.X509.load_request_string(
|
||||||
|
pkg_resources.resource_string(
|
||||||
|
'acme.jose', os.path.join('testdata', 'csr.der')),
|
||||||
|
M2Crypto.X509.FORMAT_DER))
|
||||||
KEY = jose.util.HashableRSAKey(RSA.importKey(pkg_resources.resource_string(
|
KEY = jose.util.HashableRSAKey(RSA.importKey(pkg_resources.resource_string(
|
||||||
'acme.jose', os.path.join('testdata', 'rsa512_key.pem'))))
|
'acme.jose', os.path.join('testdata', 'rsa512_key.pem'))))
|
||||||
|
|
||||||
@@ -94,12 +103,16 @@ class ConstantTest(unittest.TestCase):
|
|||||||
self.assertTrue(self.const_a != self.const_b)
|
self.assertTrue(self.const_a != self.const_b)
|
||||||
self.assertFalse(self.const_a != const_a_prime)
|
self.assertFalse(self.const_a != const_a_prime)
|
||||||
|
|
||||||
|
|
||||||
class RegistrationTest(unittest.TestCase):
|
class RegistrationTest(unittest.TestCase):
|
||||||
"""Tests for acme.messages.Registration."""
|
"""Tests for acme.messages.Registration."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
key = jose.jwk.JWKRSA(key=KEY.publickey())
|
key = jose.jwk.JWKRSA(key=KEY.publickey())
|
||||||
contact = ('mailto:letsencrypt-client@letsencrypt.org',)
|
contact = (
|
||||||
|
'mailto:admin@foo.com',
|
||||||
|
'tel:1234',
|
||||||
|
)
|
||||||
recovery_token = 'XYZ'
|
recovery_token = 'XYZ'
|
||||||
agreement = 'https://letsencrypt.org/terms'
|
agreement = 'https://letsencrypt.org/terms'
|
||||||
|
|
||||||
@@ -117,6 +130,26 @@ class RegistrationTest(unittest.TestCase):
|
|||||||
self.jobj_from = self.jobj_to.copy()
|
self.jobj_from = self.jobj_to.copy()
|
||||||
self.jobj_from['key'] = key.to_json()
|
self.jobj_from['key'] = key.to_json()
|
||||||
|
|
||||||
|
def test_from_data(self):
|
||||||
|
from acme.messages import Registration
|
||||||
|
reg = Registration.from_data(phone='1234', email='admin@foo.com')
|
||||||
|
self.assertEqual(reg.contact, (
|
||||||
|
'tel:1234',
|
||||||
|
'mailto:admin@foo.com',
|
||||||
|
))
|
||||||
|
|
||||||
|
def test_phones(self):
|
||||||
|
self.assertEqual(('1234',), self.reg.phones)
|
||||||
|
|
||||||
|
def test_emails(self):
|
||||||
|
self.assertEqual(('admin@foo.com',), self.reg.emails)
|
||||||
|
|
||||||
|
def test_phone(self):
|
||||||
|
self.assertEqual('1234', self.reg.phone)
|
||||||
|
|
||||||
|
def test_email(self):
|
||||||
|
self.assertEqual('admin@foo.com', self.reg.email)
|
||||||
|
|
||||||
def test_to_partial_json(self):
|
def test_to_partial_json(self):
|
||||||
self.assertEqual(self.jobj_to, self.reg.to_partial_json())
|
self.assertEqual(self.jobj_to, self.reg.to_partial_json())
|
||||||
|
|
||||||
@@ -129,6 +162,25 @@ class RegistrationTest(unittest.TestCase):
|
|||||||
hash(Registration.from_json(self.jobj_from))
|
hash(Registration.from_json(self.jobj_from))
|
||||||
|
|
||||||
|
|
||||||
|
class RegistrationResourceTest(unittest.TestCase):
|
||||||
|
"""Tests for acme.messages.RegistrationResource."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
from acme.messages import RegistrationResource
|
||||||
|
self.regr = RegistrationResource(
|
||||||
|
body=mock.sentinel.body, uri=mock.sentinel.uri,
|
||||||
|
new_authzr_uri=mock.sentinel.new_authzr_uri,
|
||||||
|
terms_of_service=mock.sentinel.terms_of_service)
|
||||||
|
|
||||||
|
def test_to_partial_json(self):
|
||||||
|
self.assertEqual(self.regr.to_json(), {
|
||||||
|
'body': mock.sentinel.body,
|
||||||
|
'uri': mock.sentinel.uri,
|
||||||
|
'new_authzr_uri': mock.sentinel.new_authzr_uri,
|
||||||
|
'terms_of_service': mock.sentinel.terms_of_service,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class ChallengeResourceTest(unittest.TestCase):
|
class ChallengeResourceTest(unittest.TestCase):
|
||||||
"""Tests for acme.messages.ChallengeResource."""
|
"""Tests for acme.messages.ChallengeResource."""
|
||||||
|
|
||||||
@@ -220,6 +272,49 @@ class AuthorizationTest(unittest.TestCase):
|
|||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorizationResourceTest(unittest.TestCase):
|
||||||
|
"""Tests for acme.messages.AuthorizationResource."""
|
||||||
|
|
||||||
|
def test_json_de_serializable(self):
|
||||||
|
from acme.messages import AuthorizationResource
|
||||||
|
authzr = AuthorizationResource(
|
||||||
|
uri=mock.sentinel.uri,
|
||||||
|
body=mock.sentinel.body,
|
||||||
|
new_cert_uri=mock.sentinel.new_cert_uri,
|
||||||
|
)
|
||||||
|
self.assertTrue(isinstance(authzr, jose.JSONDeSerializable))
|
||||||
|
|
||||||
|
|
||||||
|
class CertificateRequestTest(unittest.TestCase):
|
||||||
|
"""Tests for acme.messages.CertificateRequest."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
from acme.messages import CertificateRequest
|
||||||
|
self.req = CertificateRequest(csr=CSR, authorizations=('foo',))
|
||||||
|
|
||||||
|
def test_json_de_serializable(self):
|
||||||
|
self.assertTrue(isinstance(self.req, jose.JSONDeSerializable))
|
||||||
|
from acme.messages import CertificateRequest
|
||||||
|
self.assertEqual(
|
||||||
|
self.req, CertificateRequest.from_json(self.req.to_json()))
|
||||||
|
|
||||||
|
|
||||||
|
class CertificateResourceTest(unittest.TestCase):
|
||||||
|
"""Tests for acme.messages.CertificateResourceTest."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
from acme.messages import CertificateResource
|
||||||
|
self.certr = CertificateResource(
|
||||||
|
body=CERT, uri=mock.sentinel.uri, authzrs=(),
|
||||||
|
cert_chain_uri=mock.sentinel.cert_chain_uri)
|
||||||
|
|
||||||
|
def test_json_de_serializable(self):
|
||||||
|
self.assertTrue(isinstance(self.certr, jose.JSONDeSerializable))
|
||||||
|
from acme.messages import CertificateResource
|
||||||
|
self.assertEqual(
|
||||||
|
self.certr, CertificateResource.from_json(self.certr.to_json()))
|
||||||
|
|
||||||
|
|
||||||
class RevocationTest(unittest.TestCase):
|
class RevocationTest(unittest.TestCase):
|
||||||
"""Tests for acme.messages.RevocationTest."""
|
"""Tests for acme.messages.RevocationTest."""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user