Commit 17515b45 authored by Adrien Dorsaz's avatar Adrien Dorsaz

account delete: be more consistent with function names and add simple test

parent 7fda2726
......@@ -3,14 +3,14 @@ jessie:
before_script:
- pip3 install -r tests/requirements.txt
script:
- coverage run --source ./ -m unittest -v tests.test_acme_dns_tiny tests.test_acme_account_rollover
- coverage report --include=acme_dns_tiny.py,tools/acme_account_rollover.py
- coverage run --source ./ -m unittest -v tests.test_acme_dns_tiny tests.test_acme_account_rollover tests.test_acme_account_delete
- coverage report --include=acme_dns_tiny.py,tools/acme_account_rollover.py,tools/acme_account_delete.py
jessie_backport:
image: adt-jessie_dnspython3_1.15-bpo
before_script:
- pip3 install -r tests/requirements.txt
script:
- coverage run --source ./ -m unittest -v tests.test_acme_dns_tiny tests.test_acme_account_rollover
- coverage report --include=acme_dns_tiny.py,tools/acme_account_rollover.py
- coverage run --source ./ -m unittest -v tests.test_acme_dns_tiny tests.test_acme_account_rollover tests.test_acme_account_delete
- coverage report --include=acme_dns_tiny.py,tools/acme_account_rollover.py,tools/acme_account_delete.py
......@@ -131,3 +131,10 @@ def generate_acme_account_rollover_config():
"oldaccountkey": old_account_key,
"newaccountkey": new_account_key
}
# generate an account key to delete it
def generate_acme_account_delete_config():
# account key
account_key = NamedTemporaryFile()
Popen(["openssl", "genrsa", "-out", account_key.name, "2048"]).wait()
return account_key
import unittest, sys, os
from subprocess import Popen, PIPE
from io import StringIO
import acme_dns_tiny
from tests.config_factory import generate_acme_account_delete_config
import tools.acme_account_delete
import logassert
ACMEDirectory = os.getenv("GITLABCI_ACMEDIRECTORY", "https://acme-staging.api.letsencrypt.org/directory")
class TestACMEAccountDelete(unittest.TestCase):
"Tests for acme_account_delete"
@classmethod
def setUpClass(self):
self.accountkey = generate_acme_account_delete_config()
super(TestACMEAccountDelete, self).setUpClass()
# To clean ACME staging server and close correctly temporary files
@classmethod
def tearDownClass(self):
# close temp files correctly
self.accountkey.close()
super(TestACMEAccountDelete, self).tearDownClass()
def setUp(self):
logassert.setup(self, 'acme_account_delete')
def test_success_account_delete(self):
""" Test success account key delete """
tools.acme_account_delete.main(["--account-key", self.accountkey.name,
"--acme-directory", ACMEDirectory])
self.assertLoggedInfo("Account key deleted !")
if __name__ == "__main__":
unittest.main()
......@@ -3,7 +3,7 @@ from subprocess import Popen, PIPE
from io import StringIO
import acme_dns_tiny
from tests.config_factory import generate_acme_dns_tiny_config
from tools.acme_account_delete import delete_account
from tools.acme_account_delete import account_delete
import logassert
ACMEDirectory = os.getenv("GITLABCI_ACMEDIRECTORY", "https://acme-staging.api.letsencrypt.org/directory")
......@@ -20,7 +20,7 @@ class TestACMEDNSTiny(unittest.TestCase):
@classmethod
def tearDownClass(self):
# delete account key registration at end of tests
delete_account(self.configs["accountkey"].name, ACMEDirectory)
account_delete(self.configs["accountkey"].name, ACMEDirectory)
# close temp files correctly
for tmpfile in self.configs:
self.configs[tmpfile].close()
......
......@@ -6,7 +6,7 @@ LOGGER = logging.getLogger("acme_account_delete")
LOGGER.addHandler(logging.StreamHandler())
LOGGER.setLevel(logging.INFO)
def delete_account(accountkeypath, acme_directory, log=LOGGER):
def account_delete(accountkeypath, acme_directory, log=LOGGER):
# helper function base64 encode as defined in acme spec
def _b64(b):
return base64.urlsafe_b64encode(b).decode("utf8").rstrip("=")
......@@ -24,13 +24,13 @@ def delete_account(accountkeypath, acme_directory, log=LOGGER):
def _send_signed_request(url, payload):
nonlocal jws_nonce
payload64 = _b64(json.dumps(payload).encode("utf8"))
protected = copy.deepcopy(header)
protected = copy.deepcopy(jws_header)
protected["nonce"] = jws_nonce or urlopen(acme_directory).getheader("Replay-Nonce", None)
protected64 = _b64(json.dumps(protected).encode("utf8"))
signature = _openssl("dgst", ["-sha256", "-sign", accountkeypath],
"{0}.{1}".format(protected64, payload64).encode("utf8"))
data = json.dumps({
"header": header, "protected": protected64,
"header": jws_header, "protected": protected64,
"payload": payload64, "signature": _b64(signature),
})
try:
......@@ -49,7 +49,7 @@ def delete_account(accountkeypath, acme_directory, log=LOGGER):
accountkey.decode("utf8"), re.MULTILINE | re.DOTALL).groups()
pub_exp = "{0:x}".format(int(pub_exp))
pub_exp = "0{0}".format(pub_exp) if len(pub_exp) % 2 else pub_exp
header = {
jws_header = {
"alg": "RS256",
"jwk": {
"e": _b64(binascii.unhexlify(pub_exp.encode("utf-8"))),
......@@ -88,17 +88,17 @@ def delete_account(accountkeypath, acme_directory, log=LOGGER):
def main(argv):
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent("""\
This script *deletes* your account from an ACME server.
description="""
This script *deletes* your account from an ACME server.
It will need to have access to your private account key, so
PLEASE READ THROUGH IT!
It's around 150 lines, so it won't take long.
It will need to have access to your private account key, so
PLEASE READ THROUGH IT!
It's around 150 lines, so it won't take long.
=== Example Usage ===
Remove account.key from staging Let's Encrypt:
python3 acme_account_delete.py --account-key account.key --acme-directory https://acme-staging.api.letsencrypt.org/directory
""")
=== Example Usage ===
Remove account.key from staging Let's Encrypt:
python3 acme_account_delete.py --account-key account.key --acme-directory https://acme-staging.api.letsencrypt.org/directory
"""
)
parser.add_argument("--account-key", required = True, help="path to the private account key to delete")
parser.add_argument("--acme-directory", required = True, help="ACME directory URL of the ACME server where to remove the key")
......
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