From 89f066b81671df29772be31804af3c531f58cec1 Mon Sep 17 00:00:00 2001 From: vg Date: Tue, 21 May 2019 15:35:48 +0200 Subject: Initial commit --- tests/test_acme_dns_tiny.py | 132 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_script.sh | 9 +++ 2 files changed, 141 insertions(+) create mode 100644 tests/test_acme_dns_tiny.py create mode 100755 tests/test_script.sh (limited to 'tests') diff --git a/tests/test_acme_dns_tiny.py b/tests/test_acme_dns_tiny.py new file mode 100644 index 0000000..9a2562d --- /dev/null +++ b/tests/test_acme_dns_tiny.py @@ -0,0 +1,132 @@ +#!python3 + + +import collections +import os +import sys +import tempfile +import pytest + + +# append cwd to module importable paths (pytest-3 should be executed from main +# directory). +sys.path.append(os.path.realpath(".")) +import acme_dns_tiny + + +DOMAIN = os.getenv('TEST_DOMAIN') +ACME_STAGING_DIRECTORY = \ + 'https://acme-staging-v02.api.letsencrypt.org/directory' +CONTACT = os.getenv('TEST_CONTACT') # form: mailto:name@domain + + +def test_sanity_env(): + assert DOMAIN + assert CONTACT + + +@pytest.fixture(scope='module') +def casemap(tmpdir_factory): + + tmpdir = tmpdir_factory.mktemp("data") + + def _gen_key(name, size): + path = str(tmpdir.join(name)) + acme_dns_tiny.openssl(['genrsa', '-out', path, str(size)]) + return path + + account_key = _gen_key('account_key', 4096) + domain_key = _gen_key('domain_key', 4096) + weak_account_key = _gen_key('weak_account_key', 1024) + weak_domain_key = _gen_key('weak_domain_key', 1024) + + default_args = { + '--acme-directory': ACME_STAGING_DIRECTORY, + '--script': 'tests/test_script.sh', + '--account-key': account_key, + #'--ttl': 60, # already the default + '--ttl': None, + '--contact': None, + #'--contact': [CONTACT], # not supported by staging directory + '--verbose': None, + '--quiet': None, + } + + def _csr(name, domain_key, subj=f'/CN={DOMAIN}'): + path = str(tmpdir.join(name)) + acme_dns_tiny.openssl([ + 'req', '-new', '-key', domain_key, '-subj', subj, '-out', path + ]) + return {**default_args, '--csr': path} + + def _san_csr(name, subj='/', san=None): + path = str(tmpdir.join(name)) + with tempfile.NamedTemporaryFile('w', encoding='utf8') as conf, \ + open('/etc/ssl/openssl.cnf', 'r', encoding='utf8') as orig: + conf.write(orig.read()) + conf.write(f'\n[SAN]\nsubjectAltName={san}\n') + conf.flush() + acme_dns_tiny.openssl([ + 'req', '-new', '-key', domain_key, '-subj', subj, + '-reqexts', 'SAN', '-config', conf.name, '-out', path + ]) + return {**default_args, '--csr': path} + + return { + # single domain + 'single': _csr('csr_single', domain_key), + + # single, but weak account key used + 'weakaccountkey': { + **_csr('csr_simple', domain_key), + '--account-key': weak_account_key, + }, + + # single, but weak domain key used to sign csr + 'weakdomainkey': _csr('csr_weakdomain', weak_domain_key), + + # single, csr wrongly signed by account key + 'csrbyaccount': _csr('csr_byaccount', account_key), + + # wildcard domain in CN + 'wildcard': _csr('csr_wildcard', domain_key, f'/CN=*.{DOMAIN}'), + + # san only + 'sanonly': _san_csr('csr_sanonly', + san=f'DNS:{DOMAIN},DNS:www.{DOMAIN}'), + + # san and cn + 'san': _san_csr('csr_san', subj=f'/CN={DOMAIN}', + san=f'DNS:www.{DOMAIN}'), + + # san wildcard (domain + *.domain, contrary to wildcard in cn) + 'wildcardsan': _san_csr('csr_wildcardsan', + san=f'DNS:{DOMAIN},DNS:*.{DOMAIN}') + } + + +def assert_certificate_chain(captured): + #assert not captured.err + certlist = captured.out.split('-----BEGIN CERTIFICATE-----') + assert len(certlist) == 3 + assert certlist[0] == '' + assert '-----END CERTIFICATE-----\n' in certlist[1] + assert '-----END CERTIFICATE-----\n' in certlist[2] + textchain = acme_dns_tiny.openssl(['x509', '-text', '-noout'], + stdin=captured.out) + assert 'Issuer' in textchain + + +def test_success(capsys, casemap): + for name in ('single', 'wildcard', 'sanonly', 'san', 'wildcardsan'): + print(f'test_success case: {name}', file=sys.stderr) + acme_dns_tiny.main(casemap[name]) + captured = capsys.readouterr() + assert_certificate_chain(captured) + + +def test_assert(casemap): + for name in ('weakaccountkey', 'weakdomainkey', 'csrbyaccount'): + print(f'test_assert case: {name}', file=sys.stderr) + with pytest.raises(ValueError): + acme_dns_tiny.main(casemap[name]) diff --git a/tests/test_script.sh b/tests/test_script.sh new file mode 100755 index 0000000..dbd6812 --- /dev/null +++ b/tests/test_script.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +ssh -i "${TEST_SSHKEY}" "${TEST_USER}@${TEST_DNSSERVER}" : <