Commit 7084e7c2 authored by Adrien Dorsaz's avatar Adrien Dorsaz

v2: acme_account_deactivate updates to Requests library

parent 782485db
#!/usr/bin/env python3
import sys, os, argparse, subprocess, json, base64, binascii, hashlib, re, copy, logging
import urllib.request
from urllib.error import HTTPError
import sys, argparse, subprocess, json, base64, binascii, re, copy, logging, requests
LOGGER = logging.getLogger("acme_account_rollover")
LOGGER.addHandler(logging.StreamHandler())
LOGGER.setLevel(logging.INFO)
def account_rollover(accountkeypath, new_accountkeypath, acme_directory, log=LOGGER):
# helper function base64 encode as defined in acme spec
......@@ -46,7 +43,7 @@ def account_rollover(accountkeypath, new_accountkeypath, acme_directory, log=LOG
payload64 = _b64(json.dumps(payload).encode("utf8"))
if keypath == accountkeypath:
protected = copy.deepcopy(jws_header)
protected["nonce"] = jws_nonce or webclient.open(acme_config["newNonce"]).getheader("Replay-Nonce", None)
protected["nonce"] = jws_nonce or requests.get(acme_config["newNonce"]).headers['Replay-Nonce']
elif keypath == new_accountkeypath:
protected = copy.deepcopy(new_jws_header)
if (keypath == new_accountkeypath
......@@ -66,20 +63,26 @@ def account_rollover(accountkeypath, new_accountkeypath, acme_directory, log=LOG
# helper function make signed requests
def _send_signed_request(url, keypath, payload):
nonlocal jws_nonce
data = json.dumps(_sign_request(url, keypath, payload))
jws = _sign_request(url, keypath, payload)
try:
resp = webclient.open(url, data.encode("utf8"))
except HTTPError as httperror:
resp = httperror
resp = requests.post(url, json=jws, headers=joseheaders)
except requests.exceptions.RequestException as error:
resp = error.response
finally:
jws_nonce = resp.getheader("Replay-Nonce", None)
return resp.getcode(), resp.read(), resp.getheaders()
jws_nonce = resp.headers['Replay-Nonce']
if resp.text != '':
return resp.status_code, resp.json(), resp.headers
else:
return resp.status_code, json.dumps({}), resp.headers
webclient = urllib.request.build_opener();
webclient.addheaders = [('User-Agent', 'acme-dns-tiny/2.0/account_rollover')]
log.info("Reading ACME directory.")
directory = webclient.open(acme_directory)
acme_config = json.loads(directory.read().decode("utf8"))
# main code
adtheaders = {'User-Agent': 'acme-dns-tiny/2.0'}
joseheaders=copy.deepcopy(adtheaders)
joseheaders['Content-Type']='application/jose+json'
log.info("Fetch informations from the ACME directory.")
directory = requests.get(acme_directory, headers=adtheaders)
acme_config = directory.json()
log.info("Parsing current account key...")
jws_header = _jws_header(accountkeypath)
......@@ -93,7 +96,7 @@ def account_rollover(accountkeypath, new_accountkeypath, acme_directory, log=LOG
code, result, headers = _send_signed_request(acme_config["newAccount"], accountkeypath, {
"onlyReturnExisting": True })
if code == 200:
jws_header["kid"] = dict(headers).get("Location")
jws_header["kid"] = headers["Location"]
else:
raise ValueError("Error looking or account URL: {0} {1}".format(code, result))
......@@ -110,25 +113,22 @@ def account_rollover(accountkeypath, new_accountkeypath, acme_directory, log=LOG
def main(argv):
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""
This script *rolls over* your account key on an ACME server.
description="Tiny ACME client to roll over an ACME account key with another one.",
epilog="""This script *rolls over* ACME account keys.
It will need to have access to your private account key, so
PLEASE READ THROUGH IT!
It will need to have access to the ACME private account keys, so PLEASE READ THROUGH IT!
It's around 150 lines, so it won't take long.
=== Example Usage ===
Rollover account.keys from account.key to newaccount.key:
python3 acme_account_rollover.py --current account.key --new newaccount.key --acme-directory https://acme-staging.api.letsencrypt.org/directory"""
)
Example: roll over account key from account.key to newaccount.key:
python3 acme_account_rollover.py --current account.key --new newaccount.key --acme-directory https://acme-staging-v02.api.letsencrypt.org/directory""")
parser.add_argument("--current", required = True, help="path to the current private account key")
parser.add_argument("--new", required = True, help="path to the newer private account key to register")
parser.add_argument("--acme-directory", required = True, help="ACME directory URL of the ACME server where to remove the key")
parser.add_argument("--quiet", action="store_const", const=logging.ERROR, help="suppress output except for errors")
args = parser.parse_args(argv)
LOGGER.setLevel(args.quiet or LOGGER.level)
account_rollover(args.current, args.new, args.acme_directory)
LOGGER.setLevel(args.quiet or logging.INFO)
account_rollover(args.current, args.new, args.acme_directory, log=LOGGER)
if __name__ == "__main__": # pragma: no cover
main(sys.argv[1:])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment