Merge remote-tracking branch 'github/letsencrypt/master' into acme-resource-json

Conflicts:
	acme/messages_test.py
This commit is contained in:
Jakub Warmuz 2015-06-22 21:03:57 +00:00
commit bff89936af
No known key found for this signature in database
GPG key ID: 2A7BAD3A489B52EA
7 changed files with 37 additions and 55 deletions

View file

@ -540,21 +540,17 @@ class Client(object): # pylint: disable=too-many-instance-attributes
else:
return None
def revoke(self, certr, when=messages.Revocation.NOW):
def revoke(self, cert):
"""Revoke certificate.
:param certr: Certificate Resource
:type certr: `.CertificateResource`
:param when: When should the revocation take place? Takes
the same values as `.messages.Revocation.revoke`.
:param .ComparableX509 cert: `M2Crypto.X509.X509` wrapped in
`.ComparableX509`
:raises .ClientError: If revocation is unsuccessful.
"""
rev = messages.Revocation(revoke=when, authorizations=tuple(
authzr.uri for authzr in certr.authzrs))
response = self._post(certr.uri, rev)
response = self._post(messages.Revocation.url(self.new_reg_uri),
messages.Revocation(certificate=cert))
if response.status_code != httplib.OK:
raise errors.ClientError(
'Successful revocation must return HTTP OK status')

View file

@ -509,8 +509,9 @@ class ClientTest(unittest.TestCase):
def test_revoke(self):
self._mock_post_get()
self.net.revoke(self.certr, when=messages.Revocation.NOW)
self.post.assert_called_once_with(self.certr.uri, mock.ANY)
self.net.revoke(self.certr.body)
self.post.assert_called_once_with(messages.Revocation.url(
self.net.new_reg_uri), mock.ANY)
def test_revoke_bad_status_raises_error(self):
self.response.status_code = httplib.METHOD_NOT_ALLOWED

View file

@ -1,4 +1,6 @@
"""ACME protocol messages."""
import urlparse
from acme import challenges
from acme import fields
from acme import jose
@ -327,28 +329,22 @@ class CertificateResource(ResourceWithURI):
class Revocation(jose.JSONObjectWithFields):
"""Revocation message.
:ivar revoke: Either a `datetime.datetime` or `Revocation.NOW`.
:ivar tuple authorizations: Same as `CertificateRequest.authorizations`
:ivar .ComparableX509 certificate: `M2Crypto.X509.X509` wrapped in
`.ComparableX509`
"""
certificate = jose.Field(
'certificate', decoder=jose.decode_cert, encoder=jose.encode_cert)
NOW = 'now'
"""A possible value for `revoke`, denoting that certificate should
be revoked now."""
# TODO: acme-spec#138, this allows only one ACME server instance per domain
PATH = '/acme/revoke-cert'
"""Path to revocation URL, see `url`"""
revoke = jose.Field('revoke')
authorizations = CertificateRequest._fields['authorizations']
@classmethod
def url(cls, base):
"""Get revocation URL.
@revoke.decoder
def revoke(value): # pylint: disable=missing-docstring,no-self-argument
if value == Revocation.NOW:
return value
else:
return fields.RFC3339Field.default_decoder(value)
:param str base: New Registration Resource or server (root) URL.
@revoke.encoder
def revoke(value): # pylint: disable=missing-docstring,no-self-argument
if value == Revocation.NOW:
return value
else:
return fields.RFC3339Field.default_encoder(value)
"""
return urlparse.urljoin(base, cls.PATH)

View file

@ -1,5 +1,4 @@
"""Tests for acme.messages."""
import datetime
import os
import pkg_resources
import unittest
@ -7,7 +6,6 @@ import unittest
from Crypto.PublicKey import RSA
import M2Crypto
import mock
import pytz
from acme import challenges
from acme import jose
@ -23,6 +21,9 @@ CSR = jose.ComparableX509(M2Crypto.X509.load_request_string(
M2Crypto.X509.FORMAT_DER))
KEY = jose.util.HashableRSAKey(RSA.importKey(pkg_resources.resource_string(
'acme.jose', os.path.join('testdata', 'rsa512_key.pem'))))
CERT = jose.ComparableX509(M2Crypto.X509.load_cert(
format=M2Crypto.X509.FORMAT_DER, file=pkg_resources.resource_filename(
'acme.jose', os.path.join('testdata', 'cert.der'))))
class ErrorTest(unittest.TestCase):
@ -318,27 +319,20 @@ class CertificateResourceTest(unittest.TestCase):
class RevocationTest(unittest.TestCase):
"""Tests for acme.messages.RevocationTest."""
def test_url(self):
from acme.messages import Revocation
url = 'https://letsencrypt-demo.org/acme/revoke-cert'
self.assertEqual(url, Revocation.url('https://letsencrypt-demo.org'))
self.assertEqual(
url, Revocation.url('https://letsencrypt-demo.org/acme/new-reg'))
def setUp(self):
from acme.messages import Revocation
self.rev_now = Revocation(authorizations=(), revoke=Revocation.NOW)
self.rev_date = Revocation(authorizations=(), revoke=datetime.datetime(
2015, 3, 27, tzinfo=pytz.utc))
self.jobj_now = {'authorizations': (), 'revoke': Revocation.NOW}
self.jobj_date = {'authorizations': (),
'revoke': '2015-03-27T00:00:00Z'}
def test_revoke_decoder(self):
from acme.messages import Revocation
self.assertEqual(self.rev_now, Revocation.from_json(self.jobj_now))
self.assertEqual(self.rev_date, Revocation.from_json(self.jobj_date))
def test_revoke_encoder(self):
self.assertEqual(self.jobj_now, self.rev_now.to_partial_json())
self.assertEqual(self.jobj_date, self.rev_date.to_partial_json())
self.rev = Revocation(certificate=CERT)
def test_from_json_hashable(self):
from acme.messages import Revocation
hash(Revocation.from_json(self.rev_now.to_json()))
hash(Revocation.from_json(self.rev.to_json()))
if __name__ == '__main__':

View file

@ -81,7 +81,3 @@ ACCOUNT_KEYS_DIR = "keys"
REC_TOKEN_DIR = "recovery_tokens"
"""Directory where all recovery tokens are saved (relative to
IConfig.work_dir)."""
NETSTAT = "/bin/netstat"
"""Location of netstat binary for checking whether a listener is already
running on the specified port (Linux-specific)."""

View file

@ -148,8 +148,7 @@ class IConfig(zope.interface.Interface):
"""
server = zope.interface.Attribute(
"CA hostname (and optionally :port). The server certificate must "
"be trusted in order to avoid further modifications to the client.")
"ACME new registration URI (including /acme/new-reg).")
email = zope.interface.Attribute(
"Email used for registration and recovery contact.")
rsa_key_size = zope.interface.Attribute("Size of the RSA key.")

View file

@ -253,7 +253,7 @@ class Revoker(object):
raise errors.LetsEncryptRevokerError(
"Corrupted backup key file: %s" % cert.backup_key_path)
return self.network.revoke(certr=None) # XXX
return self.network.revoke(cert=None) # XXX
def _remove_certs_keys(self, cert_list): # pylint: disable=no-self-use
"""Remove certificate and key.