Merge pull request #760 from kuba/revocation

Revocation: simple implementation with integration tests
This commit is contained in:
James Kasten
2015-09-10 22:00:20 -04:00
4 changed files with 32 additions and 14 deletions
+2 -1
View File
@@ -454,7 +454,8 @@ class Client(object): # pylint: disable=too-many-instance-attributes
""" """
response = self.net.post(self.directory[messages.Revocation], response = self.net.post(self.directory[messages.Revocation],
messages.Revocation(certificate=cert)) messages.Revocation(certificate=cert),
content_type=None)
if response.status_code != http_client.OK: if response.status_code != http_client.OK:
raise errors.ClientError( raise errors.ClientError(
'Successful revocation must return HTTP OK status') 'Successful revocation must return HTTP OK status')
+1 -1
View File
@@ -360,7 +360,7 @@ class ClientTest(unittest.TestCase):
def test_revoke(self): def test_revoke(self):
self.client.revoke(self.certr.body) self.client.revoke(self.certr.body)
self.net.post.assert_called_once_with( self.net.post.assert_called_once_with(
self.directory[messages.Revocation], mock.ANY) self.directory[messages.Revocation], mock.ANY, content_type=None)
def test_revoke_bad_status_raises_error(self): def test_revoke_bad_status_raises_error(self):
self.response.status_code = http_client.METHOD_NOT_ALLOWED self.response.status_code = http_client.METHOD_NOT_ALLOWED
+22 -12
View File
@@ -16,12 +16,16 @@ import zope.component
import zope.interface.exceptions import zope.interface.exceptions
import zope.interface.verify import zope.interface.verify
from acme import client as acme_client
from acme import jose
import letsencrypt import letsencrypt
from letsencrypt import account from letsencrypt import account
from letsencrypt import configuration from letsencrypt import configuration
from letsencrypt import constants from letsencrypt import constants
from letsencrypt import client from letsencrypt import client
from letsencrypt import crypto_util
from letsencrypt import errors from letsencrypt import errors
from letsencrypt import interfaces from letsencrypt import interfaces
from letsencrypt import le_util from letsencrypt import le_util
@@ -241,16 +245,20 @@ def install(args, config, plugins):
le_client.enhance_config(domains, args.redirect) le_client.enhance_config(domains, args.redirect)
def revoke(args, unused_config, unused_plugins): def revoke(args, config, unused_plugins): # TODO: coop with renewal config
"""Revoke a previously obtained certificate.""" """Revoke a previously obtained certificate."""
if args.cert_path is None and args.key_path is None: if args.key_path is not None: # revocation by cert key
return "At least one of --cert-path or --key-path is required" logger.debug("Revoking %s using cert key %s",
args.cert_path[0], args.key_path[0])
# This depends on the renewal config and cannot be completed yet. acme = acme_client.Client(
zope.component.getUtility(interfaces.IDisplay).notification( config.server, key=jose.JWK.load(args.key_path[1]))
"Revocation is not available with the new Boulder server yet.") else: # revocation by account key
#client.revoke(args.installer, config, plugins, args.no_confirm, logger.debug("Revoking %s using Account Key", args.cert_path[0])
# args.cert_path, args.key_path) 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]))
def rollback(args, config, plugins): def rollback(args, config, plugins):
@@ -576,14 +584,16 @@ def _create_subparsers(helpful):
"--cert-path", required=True, help="Path to a certificate that " "--cert-path", required=True, help="Path to a certificate that "
"is going to be installed.") "is going to be installed.")
parser_install.add_argument( parser_install.add_argument(
"--key-path", required=True, help="Accompynying private key") "--key-path", required=True, help="Accompanying private key")
parser_install.add_argument( parser_install.add_argument(
"--chain-path", help="Accompanying path to a certificate chain.") "--chain-path", help="Accompanying path to a certificate chain.")
parser_revoke.add_argument( parser_revoke.add_argument(
"--cert-path", type=read_file, help="Revoke a specific certificate.") "--cert-path", type=read_file, help="Revoke a specific certificate.",
required=True)
parser_revoke.add_argument( parser_revoke.add_argument(
"--key-path", type=read_file, "--key-path", type=read_file,
help="Revoke all certs generated by the provided authorized key.") help="Revoke certificate using its accompanying key. Useful if "
"Account Key is lost.")
parser_rollback.add_argument( parser_rollback.add_argument(
"--checkpoints", type=int, metavar="N", "--checkpoints", type=int, metavar="N",
+7
View File
@@ -52,6 +52,13 @@ do
[ "${dir}/${latest}" = "$live" ] # renewer fails this test [ "${dir}/${latest}" = "$live" ] # renewer fails this test
done done
# revoke by account key
common revoke --cert-path "$root/conf/live/le.wtf/cert.pem"
# revoke renewed
common revoke --cert-path "$root/conf/live/le1.wtf/cert.pem"
# revoke by cert key
common revoke --cert-path "$root/conf/live/le2.wtf/cert.pem" \
--key-path "$root/conf/live/le2.wtf/privkey.pem"
if type nginx; if type nginx;
then then