mirror of
https://github.com/certbot/certbot.git
synced 2026-05-28 04:34:11 -04:00
Add an account deactivate utility script. (#4254)
* Add an account deactivate utility script. This is handy if you created an account with a tool other than Certbot, and want to deactivate the account. * Move deactivate.py to tools. * Add test for ConflictError. * Fix lint error. * Document how to set server.
This commit is contained in:
parent
686f5d6c81
commit
10bac107ee
4 changed files with 69 additions and 0 deletions
|
|
@ -564,6 +564,9 @@ class ClientNetwork(object): # pylint: disable=too-many-instance-attributes
|
|||
except ValueError:
|
||||
jobj = None
|
||||
|
||||
if response.status_code == 409:
|
||||
raise errors.ConflictError(response.headers.get('Location'))
|
||||
|
||||
if not response.ok:
|
||||
if jobj is not None:
|
||||
if response_ct != cls.JSON_ERROR_CONTENT_TYPE:
|
||||
|
|
|
|||
|
|
@ -513,6 +513,12 @@ class ClientNetworkTest(unittest.TestCase):
|
|||
self.assertEqual(
|
||||
self.response, self.net._check_response(self.response))
|
||||
|
||||
def test_check_response_conflict(self):
|
||||
self.response.ok = False
|
||||
self.response.status_code = 409
|
||||
# pylint: disable=protected-access
|
||||
self.assertRaises(errors.ConflictError, self.net._check_response, self.response)
|
||||
|
||||
def test_check_response_jobj(self):
|
||||
self.response.json.return_value = {}
|
||||
for response_ct in [self.net.JSON_CONTENT_TYPE, 'foo']:
|
||||
|
|
|
|||
|
|
@ -82,3 +82,14 @@ class PollError(ClientError):
|
|||
def __repr__(self):
|
||||
return '{0}(exhausted={1!r}, updated={2!r})'.format(
|
||||
self.__class__.__name__, self.exhausted, self.updated)
|
||||
|
||||
class ConflictError(ClientError):
|
||||
"""Error for when the server returns a 409 (Conflict) HTTP status.
|
||||
|
||||
In the version of ACME implemented by Boulder, this is used to find an
|
||||
account if you only have the private key, but don't know the account URL.
|
||||
"""
|
||||
def __init__(self, location):
|
||||
self.location = location
|
||||
super(ConflictError, self).__init__()
|
||||
|
||||
|
|
|
|||
49
tools/deactivate.py
Normal file
49
tools/deactivate.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
Given an ACME account key as input, deactivate the account.
|
||||
|
||||
This can be useful if you created an account with a non-Certbot client and now
|
||||
want to deactivate it.
|
||||
|
||||
Private key should be in PKCS#8 PEM form.
|
||||
|
||||
To provide the URL for the ACME server you want to use, set it in the $DIRECTORY
|
||||
environment variable, e.g.:
|
||||
|
||||
DIRECTORY=https://acme-staging.api.letsencrypt.org/directory python \
|
||||
deactivate.py private_key.pem
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
|
||||
from acme import client as acme_client
|
||||
from acme import errors as acme_errors
|
||||
from acme import jose
|
||||
from acme import messages
|
||||
|
||||
DIRECTORY = os.getenv('DIRECTORY', 'http://localhost:4000/directory')
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python deactivate.py private_key.pem")
|
||||
sys.exit(1)
|
||||
|
||||
data = open(sys.argv[1], "r").read()
|
||||
key = jose.JWKRSA(key=serialization.load_pem_private_key(
|
||||
data, None, default_backend()))
|
||||
|
||||
net = acme_client.ClientNetwork(key, verify_ssl=False,
|
||||
user_agent="acme account deactivator")
|
||||
|
||||
client = acme_client.Client(DIRECTORY, key=key, net=net)
|
||||
try:
|
||||
# We expect this to fail and give us a Conflict response with a Location
|
||||
# header pointing at the account's URL.
|
||||
client.register()
|
||||
except acme_errors.ConflictError as e:
|
||||
location = e.location
|
||||
if location is None:
|
||||
raise "Key was not previously registered (but now is)."
|
||||
client.deactivate_registration(messages.RegistrationResource(uri=location))
|
||||
Loading…
Reference in a new issue