diff options
| author | vg <vgm+dev@devys.org> | 2020-03-12 17:43:52 +0100 | 
|---|---|---|
| committer | vg <vgm+dev@devys.org> | 2020-03-12 17:43:52 +0100 | 
| commit | cf2f1f2d3429650444685e07ee4e11bcd596bba8 (patch) | |
| tree | d49b166e56befaedeebf1f6195e68759a0f6a8ad | |
| parent | 0d836532023330efd8ffef7b23ad406ce0309f4e (diff) | |
| download | acme-dns-tiny-cf2f1f2d3429650444685e07ee4e11bcd596bba8.tar.gz acme-dns-tiny-cf2f1f2d3429650444685e07ee4e11bcd596bba8.tar.bz2 acme-dns-tiny-cf2f1f2d3429650444685e07ee4e11bcd596bba8.zip | |
Rework test (coverage and refactorization)
- better coverage (add contact tests)
- split one big test with a loop on a dict to single test functions,
  giving better view on test advance and report
- factorization of _csr and _san_csr to a single function
| -rw-r--r-- | tests/test_acme_dns_tiny.py | 189 | 
1 files changed, 115 insertions, 74 deletions
| diff --git a/tests/test_acme_dns_tiny.py b/tests/test_acme_dns_tiny.py index 9a2562d..bb96765 100644 --- a/tests/test_acme_dns_tiny.py +++ b/tests/test_acme_dns_tiny.py @@ -2,9 +2,13 @@  import collections +import inspect +import logging  import os +import subprocess  import sys  import tempfile +  import pytest @@ -14,20 +18,45 @@ 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' +DOMAIN  = os.getenv('TEST_DOMAIN')  CONTACT = os.getenv('TEST_CONTACT') # form: mailto:name@domain +SCRIPT  = os.getenv('TEST_SCRIPT') -def test_sanity_env(): -    assert DOMAIN -    assert CONTACT +def funcname(): +    return inspect.currentframe().f_back.f_code.co_name -@pytest.fixture(scope='module') -def casemap(tmpdir_factory): +def parent_funcname(): +    return inspect.currentframe().f_back.f_back.f_code.co_name + +def assert_success(capsys, args): +    name = parent_funcname() +    logging.info(f'assert_success({name}, {args})') +    acme_dns_tiny.main(args) +    captured = capsys.readouterr() +    #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 assert_assertion(args): +    name = parent_funcname() +    logging.info(f'assert_assertion({name}, {args})') +    with pytest.raises(ValueError): +        acme_dns_tiny.main(args) + +@pytest.fixture(scope='module') +def keys(tmpdir_factory):      tmpdir = tmpdir_factory.mktemp("data")      def _gen_key(name, size): @@ -35,98 +64,110 @@ def casemap(tmpdir_factory):          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) +    return { +            '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), +    } + + +@pytest.fixture(scope='module') +def csr_args(tmpdir_factory, keys): +    tmpdir = tmpdir_factory.mktemp("data")      default_args = {              '--acme-directory': ACME_STAGING_DIRECTORY, -            '--script': 'tests/test_script.sh', -            '--account-key': account_key, +            '--script': SCRIPT, +            '--account-key': keys['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}'): +    def _csr(subj, key_name='domain_key', san=None, args={}): +        name = parent_funcname() +        domain_key = keys[key_name]          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() +        if san is None:              acme_dns_tiny.openssl([ -                'req', '-new', '-key', domain_key, '-subj', subj, -                '-reqexts', 'SAN', '-config', conf.name, '-out', path +                'req', '-new', '-key', domain_key, '-subj', subj, '-out', path              ]) -        return {**default_args, '--csr': path} +        else: +            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, **args} -    return { -            # single domain -            'single': _csr('csr_single', domain_key), +    return _csr -            # 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), +def test_sanity_env(): +    assert bool(DOMAIN) +    assert bool(CONTACT) +    assert bool(SCRIPT) -            # 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}'), +def test_sanity_command(): +    subprocess.run([SCRIPT, 'add', f'_acme-challenge.{DOMAIN}.', 'dummy']) -            # 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}'), +def test_success_single_domain_in_cn(csr_args, capsys): +    subj = f'/CN={DOMAIN}' +    assert_success(capsys, csr_args(subj)) -            # san wildcard (domain + *.domain, contrary to wildcard in cn) -            'wildcardsan': _san_csr('csr_wildcardsan', -                    san=f'DNS:{DOMAIN},DNS:*.{DOMAIN}') -    } +def test_success_wildcard_in_cn(csr_args, capsys): +    subj = f'/CN=*.{DOMAIN}' +    assert_success(capsys, csr_args(subj)) -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_san_only(csr_args, capsys): +    subj = '/' +    san = f'DNS:{DOMAIN},DNS:www.{DOMAIN}' +    assert_success(capsys, csr_args(subj=subj, san=san)) + + +def test_success_san_only_contact(csr_args, capsys): +    subj = '/' +    san = f'DNS:{DOMAIN},DNS:www.{DOMAIN}' +    args = {'--contact': [CONTACT]} +    assert_success(capsys, csr_args(subj=subj, san=san, args=args)) + + +def test_success_san_contact(csr_args, capsys): +    subj = f'/CN={DOMAIN}' +    san = f'DNS:www.{DOMAIN}' +    args = {'--contact': [CONTACT]} +    assert_success(capsys, csr_args(subj=subj, san=san, args=args)) + + +def test_success_wildcard_san(csr_args, capsys): +    subj = '/' +    san = f'DNS:{DOMAIN},DNS:*.{DOMAIN}' +    assert_success(capsys, csr_args(subj=subj, san=san)) + + +def test_fail_weak_account_key(csr_args, keys): +    subj = f'/CN={DOMAIN}' +    args = {'--account-key': keys['weak_account_key']} +    assert_assertion(csr_args(subj, args=args)) -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_fail_weak_domain_key(csr_args): +    subj = f'/CN={DOMAIN}' +    assert_assertion(csr_args(subj, key_name='weak_domain_key')) -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]) +def test_fail_csr_by_account(csr_args): +    subj = f'/CN={DOMAIN}' +    # single, csr wrongly signed by account key +    assert_assertion(csr_args(subj, key_name='account_key')) | 
