From 83681c07051e86770644e4cbea93889324c12960 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 2 May 2021 21:44:28 +0200 Subject: [PATCH 01/51] [wf] codecov test --- .github/workflows/codecov.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/codecov.yml diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml new file mode 100644 index 00000000..9d682170 --- /dev/null +++ b/.github/workflows/codecov.yml @@ -0,0 +1,30 @@ +name: Codecov +on: + push: + branches: + - 'main' + - 'devel' +jobs: + codecov: + name: Codecov Workflow + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@master + with: + python-version: 3.8 + - name: Generate coverage report + run: | + python -m pip install --upgrade pip + pip install pytest + pip install pytest-cov + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pytest --cov=./ --cov-report=xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage.xml + flags: unittests From 43a931846e54b415469ff2c3ab5f778a22404b42 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 9 May 2021 10:02:09 +0200 Subject: [PATCH 02/51] [wf] codecov workflow --- .github/.codecov.yml | 3 +++ .github/workflows/codecov.yml | 4 ++-- README.md | 3 +++ examples/ca_handler/skeleton_ca_handler.py | 5 +++-- 4 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .github/.codecov.yml diff --git a/.github/.codecov.yml b/.github/.codecov.yml new file mode 100644 index 00000000..7d547d4e --- /dev/null +++ b/.github/.codecov.yml @@ -0,0 +1,3 @@ +ignore: + - "examples/ca_handler/skeleton_ca_handler.py" + - "test" # wildcards accepted diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 9d682170..3ae57deb 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -2,12 +2,12 @@ name: Codecov on: push: branches: - - 'main' + - 'master' - 'devel' jobs: codecov: name: Codecov Workflow - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 diff --git a/README.md b/README.md index 2e1a8b37..0b344642 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/grindsa/acme2certifier/devel.svg?label=last%20commit%20into%20devel) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2581/badge)](https://bestpractices.coreinfrastructure.org/projects/2581) +![Codecov main](https://img.shields.io/codecov/c/gh/grindsa/acme2certifer/branch/main?label=test%20coverage%20master) +![Codecov devel](https://img.shields.io/codecov/c/gh/grindsa/acme2certifer/branch/devel?label=test%20coverage%20devel) + acme2certifier is development project to create an ACME protocol proxy. Main intention is to provide ACME services on CA servers which do not support this protocol yet. It consists of two libraries: diff --git a/examples/ca_handler/skeleton_ca_handler.py b/examples/ca_handler/skeleton_ca_handler.py index 06d58d64..bf072473 100644 --- a/examples/ca_handler/skeleton_ca_handler.py +++ b/examples/ca_handler/skeleton_ca_handler.py @@ -26,8 +26,9 @@ def _config_load(self): self.logger.debug('CAhandler._config_load()') config_dic = load_config(self.logger, 'CAhandler') - if 'parameter' in config_dic['CAhandler']: - self.parameter = config_dic['CAhandler']['parameter'] + if 'CAhandler' in config_dic: + if 'parameter' in config_dic['CAhandler']: + self.parameter = config_dic['CAhandler']['parameter'] self.logger.debug('CAhandler._config_load() ended') From aa3c6597891a6a4545e961ad1c69358eb09f6c17 Mon Sep 17 00:00:00 2001 From: grindsa Date: Thu, 13 May 2021 22:23:27 +0200 Subject: [PATCH 03/51] [tst] unittests --- acme/certificate.py | 24 ++- test/test_account.py | 94 +++++++++- test/test_authorization.py | 90 +++++++++ test/test_certificate.py | 374 ++++++++++++++++++++++++------------- test/test_directory.py | 7 + test/test_error.py | 6 + test/test_nonce.py | 4 + 7 files changed, 457 insertions(+), 142 deletions(-) diff --git a/acme/certificate.py b/acme/certificate.py index 22ea7e49..71809b9f 100644 --- a/acme/certificate.py +++ b/acme/certificate.py @@ -98,8 +98,13 @@ def _config_load(self): if 'CAhandler' in config_dic and 'handler_file' in config_dic['CAhandler']: try: ca_handler_module = importlib.import_module(ca_handler_get(self.logger, config_dic['CAhandler']['handler_file'])) - except BaseException: - ca_handler_module = importlib.import_module('acme.ca_handler') + except BaseException as err_: + self.logger.critical('Certificate._config_load(): loading CAhandler configured in cfg failed with err: {0}'.format(err_)) + try: + ca_handler_module = importlib.import_module('acme.ca_handler') + except BaseException as err_: + ca_handler_module = None + self.logger.critical('Certificate._config_load(): loading default EABHandler failed with err: {0}'.format(err_)) else: if 'CAhandler' in config_dic: ca_handler_module = importlib.import_module('acme.ca_handler') @@ -150,7 +155,7 @@ def _csr_check(self, certificate_name, csr): identifier_status = self._identifer_tnauth_list(identifier_dic, tnauthlist) except BaseException as err_: identifier_status = [] - self.logger.warning('Certificate._csr_check() error while loading parsing csr.\nerror: {0}'.format(err_)) + self.logger.warning('Certificate._csr_check() error while parsing csr.\nerror: {0}'.format(err_)) else: # get sans and compare identifiers against san try: @@ -158,7 +163,7 @@ def _csr_check(self, certificate_name, csr): identifier_status = self._identifer_status_list(identifiers, san_list) except BaseException as err_: identifier_status = [] - self.logger.warning('Certificate._csr_check() error while loading parsing csr.\nerror: {0}'.format(err_)) + self.logger.warning('Certificate._csr_check() error while checking csr.\nerror: {0}'.format(err_)) csr_check_result = False @@ -454,11 +459,12 @@ def dates_update(self): cert_list = certificate.certlist_search('issue_uts', 0, vlist=('id', 'name', 'cert', 'cert_raw', 'issue_uts', 'expire_uts')) self.logger.debug('Got {0} certificates to be updated...'.format(len(cert_list))) for cert in cert_list: - if cert['issue_uts'] == 0 and cert['expire_uts'] == 0: - if cert['cert_raw']: - (issue_uts, expire_uts) = cert_dates_get(self.logger, cert['cert_raw']) - if issue_uts or expire_uts: - self._store_cert(cert['name'], cert['cert'], cert['cert_raw'], issue_uts, expire_uts) + if 'issue_uts' in cert and 'expire_uts' in cert: + if cert['issue_uts'] == 0 and cert['expire_uts'] == 0: + if cert['cert_raw']: + (issue_uts, expire_uts) = cert_dates_get(self.logger, cert['cert_raw']) + if issue_uts or expire_uts: + self._store_cert(cert['name'], cert['cert'], cert['cert_raw'], issue_uts, expire_uts) # return None def enroll_and_store(self, certificate_name, csr): diff --git a/test/test_account.py b/test/test_account.py index cc6a8a79..84360531 100644 --- a/test/test_account.py +++ b/test/test_account.py @@ -41,7 +41,7 @@ def test_001_account__tos_check(self): def test_002_account__tos_check(self): """ test successful tos check """ - self.assertEqual((403, 'urn:ietf:params:acme:error:userActionRequired', 'tosfalse'), self.account._tos_check({'termsOfServiceAgreed': False})) + self.assertEqual((403, 'urn:ietf:params:acme:error:userActionRequired', 'tosfalse'), self.account._tos_check({'termsofserviceagreed': False})) def test_003_account__tos_check(self): """ test successful tos check """ @@ -261,6 +261,32 @@ def test_029_account_parse(self, mock_mcheck, mock_del, mock_nnonce): message = '{"foo" : "bar"}' self.assertEqual({'code': 200, 'data': {'status': 'deactivated'}, 'header': {'Replay-Nonce': 'new_nonce'}}, self.account.parse(message)) + @patch('acme.account.Account._key_change') + @patch('acme.nonce.Nonce.generate_and_add') + @patch('acme.account.Account._delete') + @patch('acme.message.Message.check') + def test_030_account_parse(self, mock_mcheck, mock_del, mock_nnonce, mock_keychange): + """ test succ account parse for key-change (unsuccessful) """ + mock_mcheck.return_value = (200, None, None, 'protected', {"payload" : "foo"}, 'account_name') + mock_del.return_value = (200, None, None) + mock_nnonce.return_value = 'new_nonce' + mock_keychange.return_value = (400, 'message', 'detail') + message = '{"foo" : "bar"}' + self.assertEqual({'code': 400, 'data': {'detail': 'detail', 'message': 'message', 'status': 400}, 'header': {}}, self.account.parse(message)) + + @patch('acme.account.Account._key_change') + @patch('acme.nonce.Nonce.generate_and_add') + @patch('acme.account.Account._delete') + @patch('acme.message.Message.check') + def test_031_account_parse(self, mock_mcheck, mock_del, mock_nnonce, mock_keychange): + """ test succ account parse for key-change (successful) """ + mock_mcheck.return_value = (200, None, None, 'protected', {"payload" : "foo"}, 'account_name') + mock_del.return_value = (200, None, None) + mock_nnonce.return_value = 'new_nonce' + mock_keychange.return_value = (200, None, None) + message = '{"foo" : "bar"}' + self.assertEqual({'code': 200, 'data': {}, 'header': {'Replay-Nonce': 'new_nonce'}}, self.account.parse(message)) + def test_030_account__onlyreturnexisting(self): """ test onlyReturnExisting with False """ # self.signature.dbstore.jwk_load.return_value = 1 @@ -706,6 +732,42 @@ def test_082_account_new(self, mock_mcheck, mock_aad, mock_nnonce, mock_tos): e_result = {'code': 200, 'data': {}, 'header': {'Location': 'http://tester.local/acme/acct/1', 'Replay-Nonce': 'new_nonce'}} self.assertEqual(e_result, self.account.new(message)) + @patch('acme.account.Account._eab_check') + @patch('acme.account.Account._tos_check') + @patch('acme.nonce.Nonce.generate_and_add') + @patch('acme.account.Account._add') + @patch('acme.message.Message.check') + def test_085_account_new(self, mock_mcheck, mock_aad, mock_nnonce, mock_tos, mock_eab): + """ Account.new() successful eab check retured error """ + mock_mcheck.return_value = (200, None, None, 'protected', {}, None) + self.account.contact_check_disable = True + self.account.eab_check = True + mock_tos.return_value = (200, None, None) + mock_aad.return_value = (200, 1, None) + mock_nnonce.return_value = 'new_nonce' + mock_eab.return_value = (400, 'message', 'detail') + message = {'foo' : 'bar'} + e_result = {'code': 400, 'data': {'detail': 'detail', 'message': 'message', 'status': 400}, 'header': {}} + self.assertEqual(e_result, self.account.new(message)) + + @patch('acme.account.Account._eab_check') + @patch('acme.account.Account._tos_check') + @patch('acme.nonce.Nonce.generate_and_add') + @patch('acme.account.Account._add') + @patch('acme.message.Message.check') + def test_086_account_new(self, mock_mcheck, mock_aad, mock_nnonce, mock_tos, mock_eab): + """ Account.new() successful """ + mock_mcheck.return_value = (200, None, None, 'protected', {}, None) + self.account.contact_check_disable = True + self.account.eab_check = True + mock_tos.return_value = (200, None, None) + mock_aad.return_value = (200, 1, None) + mock_nnonce.return_value = 'new_nonce' + mock_eab.return_value = (200, None, None) + message = {'foo' : 'bar'} + e_result = {'code': 200, 'data': {}, 'header': {'Location': 'http://tester.local/acme/acct/1', 'Replay-Nonce': 'new_nonce'}} + self.assertEqual(e_result, self.account.new(message)) + @patch('acme.message.Message.check') def test_083_account_new(self, mock_mcheck): """ Account.new() tos check skipped as no tos """ @@ -751,6 +813,11 @@ def test_087_account__key_change(self, mock_mcheck, moch_kchval): self.account._key_change('aname', {}, protected) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Account._key_change(): exc_key_change', lcm.output) + def test_087_account__delete(self): + """ test Account._delete() if dbstore.account_delete ok """ + self.account.dbstore.account_delete.return_value = 200 + self.assertEqual((200, None, None), self.account._delete('foo')) + def test_088_account__delete(self): """ test Account._delete() if dbstore.account_delete raises an exception """ self.account.dbstore.account_delete.side_effect = Exception('exc_delete') @@ -1044,8 +1111,26 @@ def test_113_config_load(self, mock_load_cfg): self.assertFalse(self.account.tos_check_disable) self.assertFalse(self.account.contact_check_disable) self.assertTrue(self.account.eab_check) + self.assertIn("CRITICAL:test_a2c:Account._config_load(): loading EABHandler configured in cfg failed with err: No module named 'foo'", lcm.output) + self.assertIn("CRITICAL:test_a2c:Account._config_load(): loading default EABHandler failed with err: No module named 'acme.eab_handler'", lcm.output) self.assertIn('CRITICAL:test_a2c:Account._config_load(): EABHandler configuration is missing in config file', lcm.output) + @patch('importlib.import_module') + @patch('acme.account.load_config') + def test_116_config_load(self, mock_load_cfg, mock_imp): + """ test _config_load account with contact_check_disable True """ + parser = configparser.ConfigParser() + parser['EABhandler'] = {'foo': 'bar', 'eab_handler_file': 'foo'} + mock_load_cfg.return_value = parser + mock_imp.return_value = Mock() + self.account._config_load() + self.assertFalse(self.account.inner_header_nonce_allow) + self.assertFalse(self.account.ecc_only) + self.assertFalse(self.account.tos_check_disable) + self.assertFalse(self.account.contact_check_disable) + self.assertTrue(self.account.eab_check) + self.assertTrue(self.account.eab_handler) + @patch('acme.account.load_config') def test_114_config_load(self, mock_load_cfg): """ test _config_load account with tos url check """ @@ -1170,5 +1255,12 @@ def test_130__eab_signature_verify(self, mock_eabchk): mock_eabchk.return_value = (False, 'error') self.assertEqual((False, 'error'), self.account._eab_signature_verify(content, mac_key)) + @patch('acme.account.Account._config_load') + def test_0131__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.account.__enter__() + self.assertTrue(mock_cfg.called) + if __name__ == '__main__': unittest.main() diff --git a/test/test_authorization.py b/test/test_authorization.py index a5b865cd..32913d00 100644 --- a/test/test_authorization.py +++ b/test/test_authorization.py @@ -4,6 +4,7 @@ # pylint: disable=C0302, C0415, R0904, R0913, R0914, R0915, W0212 import unittest import sys +import configparser from unittest.mock import patch, MagicMock sys.path.insert(0, '.') @@ -153,6 +154,20 @@ def test_014_authorization__authz_info(self, mock_name, mock_uts, mock_challenge self.authorization._authz_info('http://tester.local/acme/authz/foo') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_authz_update', lcm.output) + @patch('acme.challenge.Challenge.new_set') + @patch('acme.authorization.uts_now') + @patch('acme.authorization.generate_random_string') + def test_015_authorization__authz_info(self, mock_name, mock_uts, mock_challengeset): + """ test Authorization.auth_info() in case auth_lookup failed """ + mock_name.return_value = 'randowm_string' + mock_uts.return_value = 1543640400 + mock_challengeset.return_value = [{'key1' : 'value1', 'key2' : 'value2'}] + self.authorization.dbstore.authorization_update.return_value = 'foo' + self.authorization.dbstore.authorization_lookup.side_effect = Exception('exc_acc_lookup') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual({}, self.authorization._authz_info('http://tester.local/acme/authz/foo')) + self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_acc_lookup', lcm.output) + @patch('acme.challenge.Challenge.new_set') @patch('acme.authorization.uts_now') @patch('acme.authorization.generate_random_string') @@ -167,5 +182,80 @@ def test_015_authorization__authz_info(self, mock_name, mock_uts, mock_challenge self.authorization._authz_info('http://tester.local/acme/authz/foo') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_authz_update', lcm.output) + @patch('acme.authorization.Authorization._config_load') + def test_016__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.authorization.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('acme.authorization.load_config') + def test_017_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + mock_load_cfg.return_value = parser + self.authorization._config_load() + self.assertFalse(self.authorization.expiry_check_disable) + self.assertEqual(86400, self.authorization.validity ) + + @patch('acme.authorization.load_config') + def test_018_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + self.authorization._config_load() + self.assertFalse(self.authorization.expiry_check_disable) + self.assertEqual(86400, self.authorization.validity ) + + @patch('acme.authorization.load_config') + def test_019_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'expiry_check_disable': False} + mock_load_cfg.return_value = parser + self.authorization._config_load() + self.assertFalse(self.authorization.expiry_check_disable) + self.assertEqual(86400, self.authorization.validity ) + + @patch('acme.authorization.load_config') + def test_020_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'expiry_check_disable': True} + mock_load_cfg.return_value = parser + self.authorization._config_load() + self.assertTrue(self.authorization.expiry_check_disable) + self.assertEqual(86400, self.authorization.validity ) + + @patch('acme.authorization.load_config') + def test_021_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'validity': 60} + mock_load_cfg.return_value = parser + self.authorization._config_load() + self.assertFalse(self.authorization.expiry_check_disable) + self.assertEqual(60, self.authorization.validity ) + + @patch('acme.authorization.load_config') + def test_022_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'validity': 'foo'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.authorization._config_load() + self.assertFalse(self.authorization.expiry_check_disable) + self.assertEqual(86400, self.authorization.validity ) + self.assertIn('WARNING:test_a2c:Authorization._config_load(): failed to parse validity: foo', lcm.output) + + @patch('acme.authorization.Authorization._authz_info') + def test_023_new_get(self, mock_info): + """ new get """ + mock_info.return_value = 'foo' + result = {'code': 200, 'data': 'foo', 'header': {}} + self.assertEqual(result, self.authorization.new_get('url')) + if __name__ == '__main__': unittest.main() diff --git a/test/test_certificate.py b/test/test_certificate.py index 26cedf04..67c386bc 100644 --- a/test/test_certificate.py +++ b/test/test_certificate.py @@ -6,6 +6,7 @@ import sys import json import importlib +import configparser from unittest.mock import patch, MagicMock, Mock sys.path.insert(0, '.') @@ -45,55 +46,62 @@ def test_002_certificate__store_cert(self): self.certificate.dbstore.certificate_add.return_value = 'bar' self.assertEqual('bar', self.certificate._store_cert('cert_name', 'cert', 'raw')) - def test_003_certificate__info(self): + def test_003_certificate__store_cert(self): + """ test Certificate.store_cert() and check if we get something back """ + self.certificate.dbstore.certificate_add.side_effect = Exception('exc_cert_add') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertFalse(self.certificate._store_cert('cert_name', 'cert', 'raw')) + self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate._store_cert(): exc_cert_add', lcm.output) + + def test_004_certificate__info(self): """ test Certificate.new_get() """ self.certificate.dbstore.certificate_lookup.return_value = 'foo' self.assertEqual('foo', self.certificate._info('cert_name')) @patch('acme.certificate.Certificate._info') - def test_004_certificate_new_get(self, mock_info): + def test_005_certificate_new_get(self, mock_info): """ test Certificate.new_get() without certificate""" mock_info.return_value = {} self.assertEqual({'code': 500, 'data': 'urn:ietf:params:acme:error:serverInternal'}, self.certificate.new_get('url')) @patch('acme.certificate.Certificate._info') - def test_005_certificate_new_get(self, mock_info): + def test_006_certificate_new_get(self, mock_info): """ test Certificate.new_get() without unknown order_status_id""" mock_info.return_value = {'order__status_id': 'foo'} self.assertEqual({'code': 403, 'data': 'urn:ietf:params:acme:error:orderNotReady'}, self.certificate.new_get('url')) @patch('acme.certificate.Certificate._info') - def test_006_certificate_new_get(self, mock_info): + def test_007_certificate_new_get(self, mock_info): """ test Certificate.new_get() without order_status_id 4 (processing)""" mock_info.return_value = {'order__status_id': 4} self.assertEqual({'code': 403, 'data': 'urn:ietf:params:acme:error:rateLimited', 'header': {'Retry-After': '600'}}, self.certificate.new_get('url')) @patch('acme.certificate.Certificate._info') - def test_007_certificate_new_get(self, mock_info): + def test_008_certificate_new_get(self, mock_info): """ test Certificate.new_get() without order_status_id 5 (valid) but no certificate in""" mock_info.return_value = {'order__status_id': 5} self.assertEqual({'code': 500, 'data': 'urn:ietf:params:acme:error:serverInternal'}, self.certificate.new_get('url')) @patch('acme.certificate.Certificate._info') - def test_008_certificate_new_get(self, mock_info): + def test_009_certificate_new_get(self, mock_info): """ test Certificate.new_get() without order_status_id 5 (valid) and empty certificate field""" mock_info.return_value = {'order__status_id': 5, 'cert': None} self.assertEqual({'code': 500, 'data': 'urn:ietf:params:acme:error:serverInternal'}, self.certificate.new_get('url')) @patch('acme.certificate.Certificate._info') - def test_009_certificate_new_get(self, mock_info): + def test_010_certificate_new_get(self, mock_info): """ test Certificate.new_get() without order_status_id 5 (valid) but no certificate in""" mock_info.return_value = {'order__status_id': 5, 'cert': 'foo-bar'} self.assertEqual({'code': 200, 'data': 'foo-bar', 'header': {'Content-Type': 'application/pem-certificate-chain'}}, self.certificate.new_get('url')) @patch('acme.message.Message.check') - def test_010_certificate_new_post(self, mock_mcheck): + def test_011_certificate_new_post(self, mock_mcheck): """ test Certificate.new_post() message check returns an error """ mock_mcheck.return_value = (400, 'urn:ietf:params:acme:error:malformed', 'detail', 'protected', 'payload', 'account_name') self.assertEqual({'code': 400, 'header': {}, 'data': json.dumps({'status': 400, 'message': 'urn:ietf:params:acme:error:malformed', 'detail': 'detail'})}, self.certificate.new_post('content')) @patch('acme.message.Message.check') - def test_011_certificate_new_post(self, mock_mcheck): + def test_012_certificate_new_post(self, mock_mcheck): """ test Certificate.new_post() message check returns ok but no url in protected """ mock_mcheck.return_value = (200, 'urn:ietf:params:acme:error:malformed', 'detail', {'foo' : 'bar'}, 'payload', 'account_name') self.assertEqual({'code': 400, 'header': {}, 'data': json.dumps({'status': 400, 'message': 'urn:ietf:params:acme:error:malformed', 'detail': 'url missing in protected header'})}, self.certificate.new_post('content')) @@ -101,114 +109,114 @@ def test_011_certificate_new_post(self, mock_mcheck): @patch('acme.message.Message.prepare_response') @patch('acme.certificate.Certificate.new_get') @patch('acme.message.Message.check') - def test_012_certificate_new_post(self, mock_mcheck, mock_certget, mock_response): + def test_013_certificate_new_post(self, mock_mcheck, mock_certget, mock_response): """ test Certificate.new_post() message check returns ok """ mock_mcheck.return_value = (200, None, None, {'url' : 'example.com'}, 'payload', 'account_name') mock_certget.return_value = {'code': 403, 'data': 'foo'} mock_response.return_value = {'data': 'foo'} self.assertEqual({'data': 'foo'}, self.certificate.new_post('content')) - def test_013_certificate__revocation_reason_check(self): + def test_014_certificate__revocation_reason_check(self): """ test Certificate.revocation_reason_check with allowed reason""" rev_reason = 0 self.assertEqual('unspecified', self.certificate._revocation_reason_check(rev_reason)) - def test_014_certificate__revocation_reason_check(self): + def test_015_certificate__revocation_reason_check(self): """ test Certificate.revocation_reason_check with non-allowed reason""" rev_reason = 8 self.assertFalse(self.certificate._revocation_reason_check(rev_reason)) @patch('acme.certificate.cert_san_get') - def test_015_certificate__authorization_check(self, mock_san): + def test_016_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with some sans but failed order lookup""" self.certificate.dbstore.order_lookup.return_value = {} mock_san.return_value = ['DNS:san1.example.com', 'DNS:san2.example.com'] self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_016_certificate__authorization_check(self, mock_san): + def test_017_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with some sans and order returning wrong values (no 'identifiers' key) """ mock_san.return_value = ['DNS:san1.example.com', 'DNS:san2.example.com'] mock_san.return_value = ['san1.example.com', 'san2.example.com'] self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_017_certificate__authorization_check(self, mock_san): + def test_018_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with some sans and order lookup returning identifiers without json structure) """ self.certificate.dbstore.order_lookup.return_value = {'identifiers' : 'test'} mock_san.return_value = ['DNS:san1.example.com', 'DNS:san2.example.com'] self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_018_certificate__authorization_check(self, mock_san): + def test_019_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with wrong sans) """ self.certificate.dbstore.order_lookup.return_value = {'identifiers' : 'test'} mock_san.return_value = ['san1.example.com', 'san2.example.com'] self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_019_certificate__authorization_check(self, mock_san): + def test_020_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with SAN entry which is not in the identifier list""" self.certificate.dbstore.order_lookup.return_value = {'identifiers' : '[{"type": "dns", "value": "san1.example.com"}]'} mock_san.return_value = ['DNS:san1.example.com', 'DNS:san2.example.com'] self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_020_certificate__authorization_check(self, mock_san): + def test_021_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with single SAN entry and correct entry in identifier list""" self.certificate.dbstore.order_lookup.return_value = {'identifiers' : '[{"type": "dns", "value": "san1.example.com"}]'} mock_san.return_value = ['DNS:san1.example.com'] self.assertTrue(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_021_certificate__authorization_check(self, mock_san): + def test_022_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with multiple SAN entries and correct entries in identifier list""" self.certificate.dbstore.order_lookup.return_value = {'identifiers' : '[{"type": "dns", "value": "san1.example.com"}, {"type": "dns", "value": "san2.example.com"}]'} mock_san.return_value = ['DNS:san1.example.com', 'DNS:san2.example.com'] self.assertTrue(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_022_certificate__authorization_check(self, mock_san): + def test_023_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with one SAN entry and multiple entries in identifier list""" self.certificate.dbstore.order_lookup.return_value = {'identifiers' : '[{"type": "dns", "value": "san1.example.com"}, {"type": "dns", "value": "san2.example.com"}]'} mock_san.return_value = ['DNS:san1.example.com'] self.assertTrue(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_023_certificate__authorization_check(self, mock_san): + def test_024_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with uppercase SAN entries and lowercase entries in identifier list""" self.certificate.dbstore.order_lookup.return_value = {'identifiers' : '[{"type": "dns", "value": "san1.example.com"}, {"type": "dns", "value": "san2.example.com"}]'} mock_san.return_value = ['DNS:SAN1.EXAMPLE.COM', 'DNS:SAN2.EXAMPLE.COM'] self.assertTrue(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_024_certificate__authorization_check(self, mock_san): + def test_025_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with lowercase SAN entries and uppercase entries in identifier list""" self.certificate.dbstore.order_lookup.return_value = {'identifiers' : '[{"TYPE": "DNS", "VALUE": "SAN1.EXAMPLE.COM"}, {"TYPE": "DNS", "VALUE": "SAN2.EXAMPLE.COM"}]'} mock_san.return_value = ['dns:san1.example.com', 'dns:san2.example.com'] self.assertTrue(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.cert_san_get') - def test_025_certificate__authorization_check(self, mock_san): + def test_026_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check with lSAN entries (return none) and entries in identifier containing None""" self.certificate.dbstore.order_lookup.return_value = {'identifiers' : '[{"type": "None", "value": "None"}]'} mock_san.return_value = ['san1.example.com'] self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) - def test_026_certificate__revocation_request_validate(self): + def test_027_certificate__revocation_request_validate(self): """ test Certificate.revocation_request_validate empty payload""" payload = {} self.assertEqual((400, 'unspecified'), self.certificate._revocation_request_validate('account_name', payload)) @patch('acme.certificate.Certificate._revocation_reason_check') - def test_027_certificate__revocation_request_validate(self, mock_revrcheck): + def test_028_certificate__revocation_request_validate(self, mock_revrcheck): """ test Certificate.revocation_request_validate reason_check returns None""" payload = {'reason' : 0} mock_revrcheck.return_value = False self.assertEqual((400, 'urn:ietf:params:acme:error:badRevocationReason'), self.certificate._revocation_request_validate('account_name', payload)) @patch('acme.certificate.Certificate._revocation_reason_check') - def test_028_certificate__revocation_request_validate(self, mock_revrcheck): + def test_029_certificate__revocation_request_validate(self, mock_revrcheck): """ test Certificate.revocation_request_validate reason_check returns a reason""" payload = {'reason' : 0} mock_revrcheck.return_value = 'revrcheck' @@ -217,7 +225,7 @@ def test_028_certificate__revocation_request_validate(self, mock_revrcheck): @patch('acme.certificate.Certificate._authorization_check') @patch('acme.certificate.Certificate._account_check') @patch('acme.certificate.Certificate._revocation_reason_check') - def test_029_certificate__revocation_request_validate(self, mock_revrcheck, mock_account, mock_authz): + def test_030_certificate__revocation_request_validate(self, mock_revrcheck, mock_account, mock_authz): """ test Certificate.revocation_request_validate authz_check failed""" payload = {'reason' : 0, 'certificate': 'certificate'} mock_revrcheck.return_value = 'revrcheck' @@ -228,7 +236,7 @@ def test_029_certificate__revocation_request_validate(self, mock_revrcheck, mock @patch('acme.certificate.Certificate._authorization_check') @patch('acme.certificate.Certificate._account_check') @patch('acme.certificate.Certificate._revocation_reason_check') - def test_030_certificate__revocation_request_validate(self, mock_revrcheck, mock_account, mock_authz): + def test_031_certificate__revocation_request_validate(self, mock_revrcheck, mock_account, mock_authz): """ test Certificate.revocation_request_validate authz_check succeed""" payload = {'reason' : 0, 'certificate': 'certificate'} mock_revrcheck.return_value = 'revrcheck' @@ -237,20 +245,20 @@ def test_030_certificate__revocation_request_validate(self, mock_revrcheck, mock self.assertEqual((200, 'revrcheck'), self.certificate._revocation_request_validate('account_name', payload)) @patch('acme.message.Message.check') - def test_031_certificate_revoke(self, mock_mcheck): + def test_032_certificate_revoke(self, mock_mcheck): """ test Certificate.revoke with failed message check """ mock_mcheck.return_value = (400, 'message', 'detail', None, None, 'account_name') self.assertEqual({'header': {}, 'code': 400, 'data': {'status': 400, 'message': 'message', 'detail': 'detail'}}, self.certificate.revoke('content')) @patch('acme.message.Message.check') - def test_032_certificate_revoke(self, mock_mcheck): + def test_033_certificate_revoke(self, mock_mcheck): """ test Certificate.revoke with incorrect payload """ mock_mcheck.return_value = (200, 'message', 'detail', None, {}, 'account_name') self.assertEqual({'header': {}, 'code': 400, 'data': {'status': 400, 'message': 'urn:ietf:params:acme:error:malformed', 'detail': 'certificate not found'}}, self.certificate.revoke('content')) @patch('acme.certificate.Certificate._revocation_request_validate') @patch('acme.message.Message.check') - def test_033_certificate_revoke(self, mock_mcheck, mock_validate): + def test_034_certificate_revoke(self, mock_mcheck, mock_validate): """ test Certificate.revoke with failed request validation """ mock_mcheck.return_value = (200, None, None, None, {'certificate' : 'certificate'}, 'account_name') mock_validate.return_value = (400, 'error') @@ -259,7 +267,7 @@ def test_033_certificate_revoke(self, mock_mcheck, mock_validate): @patch('acme.nonce.Nonce.generate_and_add') @patch('acme.certificate.Certificate._revocation_request_validate') @patch('acme.message.Message.check') - def test_034_certificate_revoke(self, mock_mcheck, mock_validate, mock_nnonce): + def test_035_certificate_revoke(self, mock_mcheck, mock_validate, mock_nnonce): """ test Certificate.revoke with sucessful request validation """ mock_mcheck.return_value = (200, None, None, None, {'certificate' : 'certificate'}, 'account_name') mock_validate.return_value = (200, 'reason') @@ -269,212 +277,212 @@ def test_034_certificate_revoke(self, mock_mcheck, mock_validate, mock_nnonce): self.certificate.cahandler.revoke = Mock(return_value=(200, 'message', 'detail')) self.assertEqual({'code': 200, 'header': {'Replay-Nonce': 'new_nonce'}}, self.certificate.revoke('content')) - def test_035_certificate__revocation_reason_check(self): + def test_036_certificate__revocation_reason_check(self): """ test Certicate.revocation_reason_check() with a valid revocation reason""" self.assertEqual('unspecified', self.certificate._revocation_reason_check(0)) - def test_036_certificate__revocation_reason_check(self): + def test_037_certificate__revocation_reason_check(self): """ test Certicate.revocation_reason_check() with an invalid revocation reason""" self.assertFalse(self.certificate._revocation_reason_check(2)) - def test_037_certificate__tnauth_identifier_check(self): + def test_038_certificate__tnauth_identifier_check(self): """ identifier check empty """ identifier_dic = [] self.assertFalse(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_038_certificate__tnauth_identifier_check(self): + def test_039_certificate__tnauth_identifier_check(self): """ identifier check none input""" identifier_dic = None self.assertFalse(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_039_certificate__tnauth_identifier_check(self): + def test_040_certificate__tnauth_identifier_check(self): """ identifier check none input""" identifier_dic = 'foo' self.assertFalse(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_040_certificate__tnauth_identifier_check(self): + def test_041_certificate__tnauth_identifier_check(self): """ identifier check one identifier """ identifier_dic = [{'foo': 'bar'}] self.assertFalse(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_041_certificate__tnauth_identifier_check(self): + def test_042_certificate__tnauth_identifier_check(self): """ identifier check two identifiers """ identifier_dic = [{'foo': 'bar'}, {'foo': 'bar'}] self.assertFalse(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_042_certificate__tnauth_identifier_check(self): + def test_043_certificate__tnauth_identifier_check(self): """ identifier check hit first identifiers """ identifier_dic = [{'type': 'bar'}, {'foo': 'bar'}] self.assertFalse(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_043_certificate__tnauth_identifier_check(self): + def test_044_certificate__tnauth_identifier_check(self): """ identifier check hit first identifiers """ identifier_dic = [{'type': 'TNAUTHLIST'}, {'foo': 'bar'}] self.assertTrue(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_044_certificate__tnauth_identifier_check(self): + def test_045_certificate__tnauth_identifier_check(self): """ identifier check hit first identifiers """ identifier_dic = [{'type': 'tnauthlist'}, {'foo': 'bar'}] self.assertTrue(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_045_certificate__tnauth_identifier_check(self): + def test_046_certificate__tnauth_identifier_check(self): """ identifier check hit 2nd identifiers """ identifier_dic = [{'type': 'bar'}, {'type': 'tnauthlist'}] self.assertTrue(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_046_certificate__tnauth_identifier_check(self): + def test_047_certificate__tnauth_identifier_check(self): """ identifier check hit 2nd identifiers """ identifier_dic = [{'type': 'bar'}, {'type': 'TNAUTHLIST'}] self.assertTrue(self.certificate._tnauth_identifier_check(identifier_dic)) - def test_047_certificate__identifer_status_list(self): + def test_048_certificate__identifer_status_list(self): """ failed check identifiers against san """ identifier_dic = [{'foo': 'bar'}, {'foo': 'bar'}] san_list = ['foo:bar', 'foo:bar'] self.assertEqual([False, False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_048_certificate__identifer_status_list(self): + def test_049_certificate__identifer_status_list(self): """ failed check no sans """ identifier_dic = [{'foo': 'bar'}] san_list = [] self.assertEqual([False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_049_certificate__identifer_status_list(self): + def test_050_certificate__identifer_status_list(self): """ failed check no identifiers """ identifier_dic = [] san_list = ['foo:bar'] self.assertEqual([False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_050_certificate__identifer_status_list(self): + def test_051_certificate__identifer_status_list(self): """ failed check no identifiers """ identifier_dic = [] san_list = ['bar'] self.assertEqual([False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_051_certificate__identifer_status_list(self): + def test_052_certificate__identifer_status_list(self): """ succ check no identifiers """ identifier_dic = [{'type': 'dns', 'value': 'bar'}] san_list = ['dns:bar'] self.assertEqual([True], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_052_certificate__identifer_status_list(self): + def test_053_certificate__identifer_status_list(self): """ failed check san in identifier """ identifier_dic = [{'type': 'dns', 'value': 'bar1'}] san_list = ['dns:bar'] self.assertEqual([False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_053_certificate__identifer_status_list(self): + def test_054_certificate__identifer_status_list(self): """ failed check identifier in san """ identifier_dic = [{'type': 'dns', 'value': 'bar'}] san_list = ['dns:bar1'] self.assertEqual([False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_054_certificate__identifer_status_list(self): + def test_055_certificate__identifer_status_list(self): """ failed check identifier one identifier two sans""" identifier_dic = [{'type': 'dns', 'value': 'bar'}] san_list = ['dns:bar', 'dns:bar2'] self.assertEqual([True, False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_055_certificate__identifer_status_list(self): + def test_056_certificate__identifer_status_list(self): """ failed check identifier two identifier one san""" identifier_dic = [{'type': 'dns', 'value': 'bar1'}, {'type': 'dns', 'value': 'bar2'}] san_list = ['dns:bar1'] self.assertEqual([True], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_056_certificate__identifer_status_list(self): + def test_057_certificate__identifer_status_list(self): """ failed check identifier both ok""" identifier_dic = [{'type': 'dns', 'value': 'bar1'}, {'type': 'dns', 'value': 'bar2'}] san_list = ['dns:bar1', 'dns:bar2'] self.assertEqual([True, True], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_057_certificate__identifer_status_list(self): + def test_058_certificate__identifer_status_list(self): """ failed check identifier both ok - wrong order""" identifier_dic = [{'type': 'dns', 'value': 'bar1'}, {'type': 'dns', 'value': 'bar2'}] san_list = ['dns:bar2', 'dns:bar1'] self.assertEqual([True, True], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_058_certificate__identifer_status_list(self): + def test_059_certificate__identifer_status_list(self): """ failed check identifier first ok 2nd nok""" identifier_dic = [{'type': 'dns', 'value': 'bar1'}, {'type': 'dns', 'value': 'bar'}] san_list = ['dns:bar1', 'dns:bar2'] self.assertEqual([True, False], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_059_certificate__identifer_status_list(self): + def test_060_certificate__identifer_status_list(self): """ failed check identifier first nook 2nd ok""" identifier_dic = [{'type': 'dns', 'value': 'bar1'}, {'type': 'dns', 'value': 'bar2'}] san_list = ['dns:bar', 'dns:bar2'] self.assertEqual([False, True], self.certificate._identifer_status_list(identifier_dic, san_list)) - def test_060_certificate__identifer_tnauth_list(self): + def test_061_certificate__identifer_tnauth_list(self): """ empty identifier dic but tnauth exists """ identifier_dic = [] tnauthlist = 'foo' self.assertEqual([False], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) - def test_061_certificate__identifer_tnauth_list(self): + def test_062_certificate__identifer_tnauth_list(self): """ identifier dic but no tnauth """ identifier_dic = {'foo': 'bar'} tnauthlist = None self.assertEqual([False], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) - def test_062_certificate__identifer_tnauth_list(self): + def test_063_certificate__identifer_tnauth_list(self): """ wrong identifier """ identifier_dic = {'identifiers': '[{"foo": "bar"}]'} tnauthlist = 'foo' self.assertEqual([False], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) - def test_063_certificate__identifer_tnauth_list(self): + def test_064_certificate__identifer_tnauth_list(self): """ wrong type """ identifier_dic = {'identifiers': '[{"type": "bar"}]'} tnauthlist = 'foo' self.assertEqual([False], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) - def test_064_certificate__identifer_tnauth_list(self): + def test_065_certificate__identifer_tnauth_list(self): """ correct type but no value""" identifier_dic = {'identifiers': '[{"type": "TnAuThLiSt"}]'} tnauthlist = 'foo' self.assertEqual([False], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) - def test_065_certificate__identifer_tnauth_list(self): + def test_066_certificate__identifer_tnauth_list(self): """ correct type but wrong value""" identifier_dic = {'identifiers': '[{"type": "TnAuThLiSt", "value": "bar"}]'} tnauthlist = 'foo' self.assertEqual([False], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) - def test_066_certificate__identifer_tnauth_list(self): + def test_067_certificate__identifer_tnauth_list(self): """ correct type but wrong value""" identifier_dic = {'identifiers': '[{"type": "TnAuThLiSt", "value": "foo"}]'} tnauthlist = 'foo' self.assertEqual([True], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) - def test_067_certificate__identifer_tnauth_list(self): + def test_068_certificate__identifer_tnauth_list(self): """ correct type but wrong value""" identifier_dic = {'identifiers': '[{"type": "TnAuThLiSt", "value": "foo"}, {"type": "dns", "value": "foo"}]'} tnauthlist = 'foo' self.assertEqual([True, False], self.certificate._identifer_tnauth_list(identifier_dic, tnauthlist)) @patch('acme.certificate.Certificate._info') - def test_068_certificate__csr_check(self, mock_certinfo): + def test_069_certificate__csr_check(self, mock_certinfo): """ csr-check certname lookup failed """ mock_certinfo.return_value = {} self.assertFalse(self.certificate._csr_check('cert_name', 'csr')) @patch('acme.certificate.Certificate._info') - def test_069_certificate__csr_check(self, mock_certinfo): + def test_070_certificate__csr_check(self, mock_certinfo): """ csr-check order lookup failed """ mock_certinfo.return_value = {'order': 'order'} self.certificate.dbstore.order_lookup.return_value = {} self.assertFalse(self.certificate._csr_check('cert_name', 'csr')) @patch('acme.certificate.Certificate._info') - def test_070_certificate__csr_check(self, mock_certinfo): + def test_071_certificate__csr_check(self, mock_certinfo): """ csr-check order lookup returns rubbish """ mock_certinfo.return_value = {'order': 'order'} self.certificate.dbstore.order_lookup.return_value = {'foo': 'bar'} self.assertFalse(self.certificate._csr_check('cert_name', 'csr')) @patch('acme.certificate.Certificate._info') - def test_071_certificate__csr_check(self, mock_certinfo): + def test_072_certificate__csr_check(self, mock_certinfo): """ csr-check order lookup returns an identifier """ mock_certinfo.return_value = {'order': 'order'} self.certificate.dbstore.order_lookup.return_value = {'foo': 'bar', 'identifiers': 'bar'} @@ -482,7 +490,7 @@ def test_071_certificate__csr_check(self, mock_certinfo): @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_072_certificate__csr_check(self, mock_certinfo, mock_tnauthin): + def test_073_certificate__csr_check(self, mock_certinfo, mock_tnauthin): """ csr-check no tnauth """ mock_certinfo.return_value = {'order': 'order'} mock_tnauthin.return_value = False @@ -493,7 +501,7 @@ def test_072_certificate__csr_check(self, mock_certinfo, mock_tnauthin): @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_073_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_074_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check no tnauth status true """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -506,7 +514,7 @@ def test_073_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_074_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_075_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check no tnauth status False """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -519,7 +527,7 @@ def test_074_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_075_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_076_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check no tnauth status True, False """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -532,7 +540,7 @@ def test_075_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_076_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_077_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check no tnauth status True, False, True """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -545,7 +553,7 @@ def test_076_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_077_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_078_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check tnauth but tnauthlist_support off """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -558,7 +566,7 @@ def test_077_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_078_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_079_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check tnauth but tnauthlist_support on and returns true """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -572,7 +580,7 @@ def test_078_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_079_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_080_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check tnauth but tnauthlist_support on and returns true """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -586,7 +594,7 @@ def test_079_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_080_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_081_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check tnauth but tnauthlist_support on and returns True, False """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -600,7 +608,7 @@ def test_080_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.Certificate._info') - def test_081_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + def test_082_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): """ csr-check tnauth but tnauthlist_support on and returns True, False """ mock_certinfo.return_value = {'order': 'order'} mock_san.return_value = ['foo'] @@ -610,23 +618,39 @@ def test_081_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_sta self.certificate.dbstore.order_lookup.return_value = {'foo': 'bar', 'identifiers': 'bar'} self.assertFalse(self.certificate._csr_check('cert_name', 'csr')) - def test_082_certificate__authorization_check(self): + @patch('acme.certificate.csr_extensions_get') + @patch('acme.certificate.Certificate._identifer_tnauth_list') + @patch('acme.certificate.Certificate._tnauth_identifier_check') + @patch('acme.certificate.Certificate._info') + def test_083_certificate__csr_check(self, mock_certinfo, mock_tnauthin, mock_status, mock_san): + """ csr-check tnauth but tnauthlist_support on and returns True, False """ + mock_certinfo.return_value = {'order': 'order'} + mock_san.return_value = ['foo'] + mock_tnauthin.return_value = True + mock_status.side_effect = Exception('mock_status') + self.certificate.tnauthlist_support = True + self.certificate.dbstore.order_lookup.return_value = {'foo': 'bar', 'identifiers': 'bar'} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertFalse(self.certificate._csr_check('cert_name', 'csr')) + self.assertIn('WARNING:test_a2c:Certificate._csr_check() error while parsing csr.\nerror: mock_status', lcm.output) + + def test_084_certificate__authorization_check(self): """ _authorization_check order lookup failed """ self.certificate.dbstore.order_lookup.return_value = {} self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) - def test_083_certificate__authorization_check(self): + def test_085_certificate__authorization_check(self): """ _authorization_check order lookup returns rubbish """ self.certificate.dbstore.order_lookup.return_value = {'foo': 'bar'} self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) - def test_084_certificate__authorization_check(self): + def test_086_certificate__authorization_check(self): """ _authorization_check order lookup returns an identifier """ self.certificate.dbstore.order_lookup.return_value = {'foo': 'bar', 'identifiers': 'bar'} self.assertFalse(self.certificate._authorization_check('order_name', 'cert')) @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_085_certificate__authorization_check(self, mock_tnauthin): + def test_087_certificate__authorization_check(self, mock_tnauthin): """ _authorization_check no tnauth """ mock_tnauthin.return_value = False self.certificate.dbstore.order_lookup.return_value = {'foo': 'bar', 'identifiers': 'bar'} @@ -635,7 +659,7 @@ def test_085_certificate__authorization_check(self, mock_tnauthin): @patch('acme.certificate.cert_san_get') @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_086_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_088_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check no tnauth status true """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = False @@ -646,7 +670,7 @@ def test_086_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_san_get') @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_087_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_089_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check no tnauth status true """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = False @@ -657,7 +681,7 @@ def test_087_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_san_get') @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_088_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_090_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check no tnauth status False """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = False @@ -668,7 +692,7 @@ def test_088_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_san_get') @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_089_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_091_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check no tnauth status True, False """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = False @@ -679,7 +703,7 @@ def test_089_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_san_get') @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_090_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_092_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check no tnauth status True, False, True """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = False @@ -690,7 +714,7 @@ def test_090_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_san_get') @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_091_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_093_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check tnauth but tnauthlist_support off """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = True @@ -701,7 +725,7 @@ def test_091_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_extensions_get') @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_092_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_094_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check tnauth but tnauthlist_support on and returns true """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = True @@ -713,7 +737,7 @@ def test_092_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_extensions_get') @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_093_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_095_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check tnauth but tnauthlist_support on and returns true """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = True @@ -725,7 +749,7 @@ def test_093_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_extensions_get') @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_094_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_096_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check tnauth but tnauthlist_support on and returns True, False """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = True @@ -737,7 +761,7 @@ def test_094_certificate__authorization_check(self, mock_tnauthin, mock_status, @patch('acme.certificate.cert_extensions_get') @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') - def test_095_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): + def test_097_certificate__authorization_check(self, mock_tnauthin, mock_status, mock_san): """ _authorization_check tnauth but tnauthlist_support on and returns True, False """ mock_san.return_value = ['foo'] mock_tnauthin.return_value = True @@ -747,7 +771,7 @@ def test_095_certificate__authorization_check(self, mock_tnauthin, mock_status, self.assertFalse(self.certificate._authorization_check('cert_name', 'cert')) @patch('acme.certificate.Certificate._csr_check') - def test_096_certificate_enroll_and_store(self, mock_csr): + def test_098_certificate_enroll_and_store(self, mock_csr): """ Certificate.enroll_and_store() csr_check failed """ mock_csr.return_value = False certificate_name = 'cert_name' @@ -756,7 +780,7 @@ def test_096_certificate_enroll_and_store(self, mock_csr): @patch('acme.certificate.Certificate._store_cert_error') @patch('acme.certificate.Certificate._csr_check') - def test_097_certificate_enroll_and_store(self, mock_csr, mock_store): + def test_099_certificate_enroll_and_store(self, mock_csr, mock_store): """ Certificate.enroll_and_store() enrollment failed without polling_identifier """ mock_csr.return_value = True mock_store.return_value = True @@ -769,7 +793,7 @@ def test_097_certificate_enroll_and_store(self, mock_csr, mock_store): @patch('acme.certificate.Certificate._store_cert_error') @patch('acme.certificate.Certificate._csr_check') - def test_098_certificate_enroll_and_store(self, mock_csr, mock_store): + def test_100_certificate_enroll_and_store(self, mock_csr, mock_store): """ Certificate.enroll_and_store() enrollment with polling_identifier""" mock_csr.return_value = True mock_store.return_value = True @@ -783,7 +807,7 @@ def test_098_certificate_enroll_and_store(self, mock_csr, mock_store): @patch('acme.certificate.cert_dates_get') @patch('acme.certificate.Certificate._store_cert') @patch('acme.certificate.Certificate._csr_check') - def test_099_certificate_enroll_and_store(self, mock_csr, mock_store, mock_dates): + def test_101_certificate_enroll_and_store(self, mock_csr, mock_store, mock_dates): """ Certificate.enroll_and_store() enrollment with polling_identifier""" mock_csr.return_value = True mock_store.return_value = True @@ -795,44 +819,78 @@ def test_099_certificate_enroll_and_store(self, mock_csr, mock_store, mock_dates csr = 'csr' self.assertEqual((None, None), self.certificate.enroll_and_store(certificate_name, csr)) - def test_100_certificate__invalidation_check(self): + @patch('acme.certificate.cert_dates_get') + @patch('acme.certificate.Certificate._store_cert') + @patch('acme.certificate.Certificate._csr_check') + def test_102_certificate_enroll_and_store(self, mock_csr, mock_store, mock_dates): + """ Certificate.enroll_and_store() enrollment with polling_identifier""" + mock_csr.return_value = True + mock_store.side_effect = Exception('ex_cert_store') + mock_dates.return_value = (1, 2) + ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') + self.certificate.cahandler = ca_handler_module.CAhandler + self.certificate.cahandler.enroll = Mock(return_value=(None, 'certificate', None, 'poll_identifier')) + certificate_name = 'cert_name' + csr = 'csr' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, None), self.certificate.enroll_and_store(certificate_name, csr)) + self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.enroll_and_store(): ex_cert_store', lcm.output) + + @patch('acme.certificate.cert_dates_get') + @patch('acme.certificate.Certificate._store_cert_error') + @patch('acme.certificate.Certificate._csr_check') + def test_103_certificate_enroll_and_store(self, mock_csr, mock_store, mock_dates): + """ Certificate.enroll_and_store() enrollment with polling_identifier""" + mock_csr.return_value = True + mock_store.side_effect = Exception('ex_cert_error_store') + mock_dates.return_value = (1, 2) + ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') + self.certificate.cahandler = ca_handler_module.CAhandler + self.certificate.cahandler.enroll = Mock(return_value=('error', None, None, 'poll_identifier')) + certificate_name = 'cert_name' + csr = 'csr' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('error', 'poll_identifier'), self.certificate.enroll_and_store(certificate_name, csr)) + self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.enroll_and_store(): ex_cert_error_store', lcm.output) + + def test_104_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - empty dict """ cert_entry = {} timestamp = 1596240000 self.assertEqual((True, {}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_101_certificate__invalidation_check(self): + def test_105_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - wrong dict """ cert_entry = {'foo': 'bar'} timestamp = 1596240000 self.assertEqual((True, {'foo': 'bar'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_102_certificate__invalidation_check(self): + def test_106_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - certname in but rest ist wrong """ cert_entry = {'name': 'certname', 'foo': 'bar'} timestamp = 1596240000 self.assertEqual((False, {'name': 'certname', 'foo': 'bar'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_103_certificate__invalidation_check(self): + def test_107_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - non zero expiry date """ cert_entry = {'name': 'certname', 'expire_uts': 10} timestamp = 1596240000 self.assertEqual((True, {'expire_uts': 10, 'name': 'certname'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_104_certificate__invalidation_check(self): + def test_108_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - expire_uts zero but no cert_raw """ cert_entry = {'name': 'certname', 'expire_uts': 0} timestamp = 1596240000 self.assertEqual((True, {'expire_uts': 0, 'name': 'certname'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_105_certificate__invalidation_check(self): + def test_109_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - expire_uts zero but no cert_raw """ cert_entry = {'name': 'certname', 'expire_uts': 0, 'cert_raw': 'cert_raw'} timestamp = 1596240000 self.assertEqual((False, {'expire_uts': 0, 'name': 'certname', 'cert_raw': 'cert_raw'}), self.certificate._invalidation_check(cert_entry, timestamp)) @patch('acme.certificate.cert_dates_get') - def test_106_certificate__invalidation_check(self, mock_dates): + def test_110_certificate__invalidation_check(self, mock_dates): """ test Certificate._invalidation_check() - with expiry date lower than timestamp """ cert_entry = {'name': 'certname', 'expire_uts': 0, 'cert_raw': 'cert_raw'} mock_dates.return_value = (10, 1596200000) @@ -840,7 +898,7 @@ def test_106_certificate__invalidation_check(self, mock_dates): self.assertEqual((True, {'expire_uts': 1596200000, 'issue_uts': 10, 'name': 'certname', 'cert_raw': 'cert_raw'}), self.certificate._invalidation_check(cert_entry, timestamp)) @patch('acme.certificate.cert_dates_get') - def test_107_certificate__invalidation_check(self, mock_dates): + def test_111_certificate__invalidation_check(self, mock_dates): """ test Certificate._invalidation_check() - with expiry date at timestamp """ cert_entry = {'name': 'certname', 'expire_uts': 0, 'cert_raw': 'cert_raw'} mock_dates.return_value = (10, 1596240000) @@ -848,21 +906,21 @@ def test_107_certificate__invalidation_check(self, mock_dates): self.assertEqual((False, {'expire_uts': 0, 'name': 'certname', 'cert_raw': 'cert_raw'}), self.certificate._invalidation_check(cert_entry, timestamp)) @patch('acme.certificate.cert_dates_get') - def test_108_certificate__invalidation_check(self, mock_dates): + def test_112_certificate__invalidation_check(self, mock_dates): """ test Certificate._invalidation_check() - with expiry date higher than timestamp """ cert_entry = {'name': 'certname', 'expire_uts': 0, 'cert_raw': 'cert_raw'} mock_dates.return_value = (10, 1596250000) timestamp = 1596240000 self.assertEqual((False, {'expire_uts': 0, 'name': 'certname', 'cert_raw': 'cert_raw'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_109_certificate__invalidation_check(self): + def test_113_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - without created_at date """ cert_entry = {'name': 'certname', 'expire_uts': 0, 'csr': 'csr'} timestamp = 1596240000 self.assertEqual((False, {'expire_uts': 0, 'name': 'certname', 'csr': 'csr'}), self.certificate._invalidation_check(cert_entry, timestamp)) @patch('acme.certificate.date_to_uts_utc') - def test_110_certificate__invalidation_check(self, mock_date): + def test_114_certificate__invalidation_check(self, mock_date): """ test Certificate._invalidation_check() - with zero created_at date """ cert_entry = {'name': 'certname', 'expire_uts': 0, 'csr': 'csr', 'created_at': 'created_at'} mock_date.return_value = 0 @@ -870,7 +928,7 @@ def test_110_certificate__invalidation_check(self, mock_date): self.assertEqual((False, {'expire_uts': 0, 'name': 'certname', 'csr': 'csr', 'created_at': 'created_at'}), self.certificate._invalidation_check(cert_entry, timestamp)) @patch('acme.certificate.date_to_uts_utc') - def test_111_certificate__invalidation_check(self, mock_date): + def test_115_certificate__invalidation_check(self, mock_date): """ test Certificate._invalidation_check() - with zero created_at date lower than threshold""" cert_entry = {'name': 'certname', 'expire_uts': 0, 'csr': 'csr', 'created_at': 'created_at'} mock_date.return_value = 1591240000 @@ -878,38 +936,38 @@ def test_111_certificate__invalidation_check(self, mock_date): self.assertEqual((True, {'expire_uts': 0, 'name': 'certname', 'csr': 'csr', 'created_at': 'created_at'}), self.certificate._invalidation_check(cert_entry, timestamp)) @patch('acme.certificate.date_to_uts_utc') - def test_112_certificate__invalidation_check(self, mock_date): + def test_116_certificate__invalidation_check(self, mock_date): """ test Certificate._invalidation_check() - with zero created_at higher than threshold """ cert_entry = {'name': 'certname', 'expire_uts': 0, 'csr': 'csr', 'created_at': 'created_at'} mock_date.return_value = 1596220000 timestamp = 1596240000 self.assertEqual((False, {'expire_uts': 0, 'name': 'certname', 'csr': 'csr', 'created_at': 'created_at'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_113_certificate__invalidation_check(self): + def test_117_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - removed by in cert """ cert_entry = {'name': 'certname', 'cert': 'removed by foo-bar', 'foo': 'bar'} timestamp = 159624000 self.assertEqual((False, {'name': 'certname', 'cert': 'removed by foo-bar', 'foo': 'bar'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_114_certificate__invalidation_check(self): + def test_118_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - removed by in cert """ cert_entry = {'name': 'certname', 'cert': 'removed by foo-bar', 'foo': 'bar'} timestamp = 159624000 self.assertEqual((True, {'name': 'certname', 'cert': 'removed by foo-bar', 'foo': 'bar'}), self.certificate._invalidation_check(cert_entry, timestamp, True)) - def test_115_certificate__invalidation_check(self): + def test_119_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - removed by in cert but in upper-cases """ cert_entry = {'name': 'certname', 'cert': 'ReMoved By foo-bar', 'foo': 'bar'} timestamp = 159624000 self.assertEqual((False, {'name': 'certname', 'cert': 'ReMoved By foo-bar', 'foo': 'bar'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_116_certificate__invalidation_check(self): + def test_120_certificate__invalidation_check(self): """ test Certificate._invalidation_check() - cert None """ cert_entry = {'name': 'certname', 'cert': None, 'foo': 'bar'} timestamp = 159624000 self.assertEqual((False, {'name': 'certname', 'cert': None, 'foo': 'bar'}), self.certificate._invalidation_check(cert_entry, timestamp)) - def test_117_certificate_poll(self): + def test_121_certificate_poll(self): """ test Certificate.poll - dbstore.order_update() raises an exception """ self.certificate.dbstore.order_update.side_effect = Exception('exc_cert_poll') ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') @@ -919,7 +977,7 @@ def test_117_certificate_poll(self): self.certificate.poll('certificate_name', 'poll_identifier', 'csr', 'order_name') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.poll(): exc_cert_poll', lcm.output) - def test_118_certificate_poll(self): + def test_122_certificate_poll(self): """ test Certificate.poll - dbstore.order_update() raises an exception and certreq rejected """ self.certificate.dbstore.order_update.side_effect = Exception('exc_cert_poll') ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') @@ -929,28 +987,28 @@ def test_118_certificate_poll(self): self.certificate.poll('certificate_name', 'poll_identifier', 'csr', 'order_name') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.poll(): exc_cert_poll', lcm.output) - def test_119_certificate__store_cert(self): + def test_123_certificate__store_cert(self): """ test Certificate.store_cert() - dbstore.certificate_add raises an exception """ self.certificate.dbstore.certificate_add.side_effect = Exception('exc_cert_add') with self.assertLogs('test_a2c', level='INFO') as lcm: self.certificate._store_cert('cert_name', 'cert', 'raw') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate._store_cert(): exc_cert_add', lcm.output) - def test_120_certificate__store_cert_error(self): + def test_124_certificate__store_cert_error(self): """ test Certificate.store_cert_error() - dbstore.certificate_add raises an exception """ self.certificate.dbstore.certificate_add.side_effect = Exception('exc_cert_add_error') with self.assertLogs('test_a2c', level='INFO') as lcm: self.certificate._store_cert_error('cert_name', 'error', 'poll') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate._store_cert(): exc_cert_add_error', lcm.output) - def test_121_certificate__account_check(self): + def test_125_certificate__account_check(self): """ test Certificate._account_check() - dbstore.certificate_account_check raises an exception """ self.certificate.dbstore.certificate_account_check.side_effect = Exception('exc_acc_chk') with self.assertLogs('test_a2c', level='INFO') as lcm: self.certificate._account_check('account_name', 'cert') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate._account_check(): exc_acc_chk', lcm.output) - def test_122_certificate__authorization_check(self): + def test_126_certificate__authorization_check(self): """ test Certificate._authorization_check() - dbstore.certificate_account_check raises an exception """ self.certificate.dbstore.order_lookup.side_effect = Exception('exc_authz_chk') with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -958,7 +1016,7 @@ def test_122_certificate__authorization_check(self): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate._authorization_check(): exc_authz_chk', lcm.output) @patch('acme.certificate.Certificate._info') - def test_123_certificate__csr_check(self, mock_certinfo): + def test_127_certificate__csr_check(self, mock_certinfo): """ csr-check - dbstore.order_lookup() raises an exception """ mock_certinfo.return_value = {'order': 'order'} self.certificate.dbstore.order_lookup.side_effect = Exception('exc_csr_chk') @@ -967,7 +1025,7 @@ def test_123_certificate__csr_check(self, mock_certinfo): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate._csr_check(): exc_csr_chk', lcm.output) # self.certificate.dbstore.order_lookup.side_effect = [] - def test_124_certificate__info(self): + def test_128_certificate__info(self): """ test Certificate._info - dbstore.certificate_lookup() raises an exception """ self.certificate.dbstore.certificate_lookup.side_effect = Exception('exc_cert_info') with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -975,7 +1033,7 @@ def test_124_certificate__info(self): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate._info(): exc_cert_info', lcm.output) @patch('acme.certificate.Certificate._invalidation_check') - def test_125_certificate_cleanup(self, mock_chk): + def test_129_certificate_cleanup(self, mock_chk): """ test Certificate.cleanup - dbstore.certificate_add() raises an exception """ mock_chk.return_value = (True, {'name': 'name', 'expire_uts': 1543640400, 'issue_uts': 1543640400, 'cert_raw': 'cert_raw'}) self.certificate.dbstore.certificates_search.return_value = [{'name', 'name'},] @@ -985,7 +1043,7 @@ def test_125_certificate_cleanup(self, mock_chk): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.cleanup() add: exc_cert_cleanup1', lcm.output) @patch('acme.certificate.Certificate._invalidation_check') - def test_126_certificate_cleanup(self, mock_chk): + def test_130_certificate_cleanup(self, mock_chk): """ test Certificate.cleanup - dbstore.certificate_delete() raises an exception """ mock_chk.return_value = (True, {'id': 2, 'name': 'name', 'expire_uts': 1543640400, 'issue_uts': 1543640400, 'cert_raw': 'cert_raw'}) self.certificate.dbstore.certificates_search.return_value = [{'name', 'name'},] @@ -994,14 +1052,14 @@ def test_126_certificate_cleanup(self, mock_chk): self.certificate.cleanup(1543640400, True) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.cleanup() delete: exc_cert_cleanup2', lcm.output) - def test_127_certificate_cleanup(self): + def test_131_certificate_cleanup(self): """ test Certificate.cleanup - dbstore.certificates_search() raises an exception """ self.certificate.dbstore.certificates_search.side_effect = Exception('exc_cert_cleanup') with self.assertLogs('test_a2c', level='INFO') as lcm: self.certificate.cleanup('timestamp') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.cleanup() search: exc_cert_cleanup', lcm.output) - def test_128_certificate_certlist_search(self): + def test_132_certificate_certlist_search(self): """ test Certificate.certlist_search - dbstore.certificates_search() raises an exception """ self.certificate.dbstore.certificates_search.side_effect = Exception('exc_certlist_search') with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -1009,22 +1067,62 @@ def test_128_certificate_certlist_search(self): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Certificate.certlist_search(): exc_certlist_search', lcm.output) @patch('acme.certificate.load_config') - def test_129_config_load(self, mock_load_cfg): + def test_133_config_load(self, mock_load_cfg): """ test _config_load empty dictionary """ mock_load_cfg.return_value = {} self.certificate._config_load() self.assertFalse(self.certificate.tnauthlist_support) @patch('acme.certificate.load_config') - def test_130_config_load(self, mock_load_cfg): + def test_134_config_load(self, mock_load_cfg): """ test _config_load missing ca_handler """ mock_load_cfg.return_value = {} with self.assertLogs('test_a2c', level='INFO') as lcm: self.certificate._config_load() self.assertIn('ERROR:test_a2c:Certificate._config_load(): CAhandler configuration missing in config file', lcm.output) + @patch('acme.certificate.load_config') + def test_135_config_load(self, mock_load_cfg): + """ test _config_load missing ca_handler """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': False} + mock_load_cfg.return_value = parser + self.certificate._config_load() + self.assertFalse(self.certificate.tnauthlist_support) + + @patch('acme.certificate.load_config') + def test_136_config_load(self, mock_load_cfg): + """ test _config_load missing ca_handler """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': True} + mock_load_cfg.return_value = parser + self.certificate._config_load() + self.assertTrue(self.certificate.tnauthlist_support) + + @patch('acme.certificate.load_config') + def test_137_config_load(self, mock_load_cfg): + """ test _config_load missing ca_handler """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'handler_file': 'foo'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.certificate._config_load() + self.assertIn("CRITICAL:test_a2c:Certificate._config_load(): loading CAhandler configured in cfg failed with err: No module named 'foo'", lcm.output) + # self.assertIn("CRITICAL:test_a2c:Certificate._config_load(): loading default EABHandler failed with err: No module named 'acme.ca_handler'", lcm.output) + + @patch('importlib.import_module') + @patch('acme.certificate.load_config') + def test_138_config_load(self, mock_load_cfg, mock_imp): + """ test _config_load missing ca_handler """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'handler_file': 'foo'} + mock_load_cfg.return_value = parser + mock_imp.return_value = Mock() + self.certificate._config_load() + self.assertTrue(self.certificate.cahandler) + @patch('acme.certificate.cert_san_get') - def test_131_certificate__authorization_check(self, mock_san): + def test_139_certificate__authorization_check(self, mock_san): """ test Certificate.authorization_check - cert_san_get raises exception) """ self.certificate.dbstore.order_lookup.side_effect = None self.certificate.dbstore.order_lookup.return_value = {'identifiers' : 'test'} @@ -1035,7 +1133,7 @@ def test_131_certificate__authorization_check(self, mock_san): @patch('acme.certificate.Certificate._identifer_status_list') @patch('acme.certificate.cert_san_get') - def test_132_certificate__authorization_check(self, mock_san, mock_statlist): + def test_140_certificate__authorization_check(self, mock_san, mock_statlist): """ test Certificate.authorization_check - cert_san_get raises exception) """ self.certificate.dbstore.order_lookup.side_effect = None self.certificate.dbstore.order_lookup.return_value = {'identifiers' : 'test'} @@ -1047,7 +1145,7 @@ def test_132_certificate__authorization_check(self, mock_san, mock_statlist): @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.cert_extensions_get') - def test_133_certificate__authorization_check(self, mock_certext, mock_tnin): + def test_141_certificate__authorization_check(self, mock_certext, mock_tnin): """ test Certificate.authorization_check cert_extensions_get raises exception) """ self.certificate.dbstore.order_lookup.side_effect = None self.certificate.dbstore.order_lookup.return_value = {'identifiers' : 'test'} @@ -1061,7 +1159,7 @@ def test_133_certificate__authorization_check(self, mock_certext, mock_tnin): @patch('acme.certificate.Certificate._identifer_tnauth_list') @patch('acme.certificate.Certificate._tnauth_identifier_check') @patch('acme.certificate.cert_extensions_get') - def test_134_certificate__authorization_check(self, mock_certext, mock_tnin, mock_tnlist): + def test_142_certificate__authorization_check(self, mock_certext, mock_tnin, mock_tnlist): """ test Certificate.authorization_check _identifer_tnauth_list raises exception) """ self.certificate.dbstore.order_lookup.side_effect = None self.certificate.dbstore.order_lookup.return_value = {'identifiers' : 'test'} @@ -1073,5 +1171,17 @@ def test_134_certificate__authorization_check(self, mock_certext, mock_tnin, moc self.assertFalse(self.certificate._authorization_check('cert_name', 'cert')) self.assertIn('WARNING:test_a2c:Certificate._authorization_check() error while loading parsing certifcate. Error: tnauth_in_exc', lcm.output) + @patch('acme.certificate.Certificate.certlist_search') + def test_143_dates_update(self, mock_search): + """ dates update """ + mock_search.return_value = [{'foo': 'bar'}, {'foo1': 'bar1'}] + self.certificate.dates_update() + + @patch('acme.certificate.Certificate.certlist_search') + def test_144_dates_update(self, mock_search): + """ dates update """ + mock_search.return_value = [{'issue_uts': 0, 'expire_uts': 0, 'cert_raw': 'cert_raw'}, {'foo1': 'bar1'}] + self.certificate.dates_update() + if __name__ == '__main__': unittest.main() diff --git a/test/test_directory.py b/test/test_directory.py index 1fdf681d..349f24f1 100644 --- a/test/test_directory.py +++ b/test/test_directory.py @@ -155,5 +155,12 @@ def test_015_config_load(self, mock_load_cfg): self.assertEqual('tos_url', self.directory.tos_url) self.assertTrue(self.directory.eab) + @patch('acme.directory.Directory._config_load') + def test_016__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.directory.__enter__() + self.assertTrue(mock_cfg.called) + if __name__ == '__main__': unittest.main() diff --git a/test/test_error.py b/test/test_error.py index 4cf824f1..e3d8880d 100644 --- a/test/test_error.py +++ b/test/test_error.py @@ -77,5 +77,11 @@ def test_012_error_enrich_error(self): """ Error.enrich_error for valid message, no detail and nothing in error_hash hash """ self.assertFalse(self.error.enrich_error('urn:ietf:params:acme:error:badCSR', None)) + @patch('acme.error.Error._acme_errormessage') + def test_013_error_enrich_error(self, mock_error): + """ Error.enrich_error for valid message, no detail and nothing in error_hash hash """ + mock_error.return_value = 'foo' + self.assertEqual('foo', self.error.enrich_error(None, '')) + if __name__ == '__main__': unittest.main() diff --git a/test/test_nonce.py b/test/test_nonce.py index 02d0d487..158aa9eb 100644 --- a/test/test_nonce.py +++ b/test/test_nonce.py @@ -71,5 +71,9 @@ def test_008_nonce__check_and_delete(self): self.nonce._check_and_delete('nonce') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Nonce._check_and_delete(): exc_nonce_check', lcm.output) + def test_009__enter_(self): + """ test enter """ + self.nonce.__enter__() + if __name__ == '__main__': unittest.main() From 180067afb3f072828030d2acb92e9b5627f73abf Mon Sep 17 00:00:00 2001 From: grindsa Date: Fri, 14 May 2021 17:37:06 +0200 Subject: [PATCH 04/51] [tst] unittests --- acme/helper.py | 4 +- examples/ca_handler/xca_ca_handler.py | 144 ++++---- test/test_challenge.py | 350 ++++++++++++++++-- test/test_helper.py | 500 ++++++++++++++++++++------ test/test_xca_ca_handler.py | 408 +++++++++++++++++++++ 5 files changed, 1200 insertions(+), 206 deletions(-) diff --git a/acme/helper.py b/acme/helper.py index 46077970..2e7e6cd3 100644 --- a/acme/helper.py +++ b/acme/helper.py @@ -304,6 +304,7 @@ def decode_message(logger, message): signature = jwstoken.objects['signature'] result = True except BaseException as err: + logger.error('decode_message() err: {0}'.format(err)) error = str(err) protected = {} payload = {} @@ -464,7 +465,8 @@ def jwk_thumbprint_get(logger, pub_key): try: jwkey = jwk.JWK(**pub_key) thumbprint = jwkey.thumbprint() - except BaseException: + except BaseException as err: + logger.error('jwk_thumbprint_get(): error: {0}'.format(err)) jwkey = None thumbprint = None else: diff --git a/examples/ca_handler/xca_ca_handler.py b/examples/ca_handler/xca_ca_handler.py index 54e31ec2..8895993e 100644 --- a/examples/ca_handler/xca_ca_handler.py +++ b/examples/ca_handler/xca_ca_handler.py @@ -484,6 +484,7 @@ def _stub_func(self, parameter): """" load config from file """ self.logger.debug('CAhandler._stub_func({0})'.format(parameter)) self.logger.debug('CAhandler._stub_func() ended') + return parameter def _subject_modify(self, subject, dn_dic): """ modify subject name """ @@ -598,85 +599,88 @@ def _validity_calculate(self, template_dic): def enroll(self, csr): """ enroll certificate """ - # pylint: disable=R0914 + # pylint: disable=R0914 self.logger.debug('CAhandler.enroll()') cert_bundle = None cert_raw = None - error = self._config_check() if not error: - request_name = self._requestname_get(csr) - - # import CSR to database - _csr_info = self._csr_import(csr, request_name) - - # prepare the CSR to be signed - csr = build_pem_file(self.logger, None, b64_url_recode(self.logger, csr), None, True) - - # load ca cert and key - (ca_key, ca_cert, ca_id) = self._ca_load() - - if ca_key and ca_cert: - # load request - req = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr) - - # copy cn of request - subject = req.get_subject() - # rewrite CN if required - if not subject.CN: - self.logger.debug('rewrite CN to {0}'.format(request_name)) - subject.CN = request_name - - # create certificate object - cert = crypto.X509() - cert.set_pubkey(req.get_pubkey()) - cert.set_version(2) - cert.set_serial_number(uuid.uuid4().int & (1<<63)-1) - cert.set_issuer(ca_cert.get_subject()) - - # load template if configured - if self.template_name: - (dn_dic, template_dic) = self._template_load() - else: - dn_dic = {} - template_dic = {} - - # set cert_validity - if 'validity' in template_dic: - # take validity from template - cert_validity = template_dic['validity'] + if request_name: + # import CSR to database + _csr_info = self._csr_import(csr, request_name) + + # prepare the CSR to be signed + csr = build_pem_file(self.logger, None, b64_url_recode(self.logger, csr), None, True) + + # load ca cert and key + (ca_key, ca_cert, ca_id) = self._ca_load() + + if ca_key and ca_cert and ca_id: + # load request + req = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr) + + # copy cn of request + subject = req.get_subject() + # rewrite CN if required + if not subject.CN: + self.logger.info('rewrite CN to {0}'.format(request_name)) + subject.CN = request_name + + # create certificate object + cert = crypto.X509() + cert.set_pubkey(req.get_pubkey()) + cert.set_version(2) + cert.set_serial_number(uuid.uuid4().int & (1<<63)-1) + cert.set_issuer(ca_cert.get_subject()) + + # load template if configured + if self.template_name: + (dn_dic, template_dic) = self._template_load() + else: + dn_dic = {} + template_dic = {} + + # set cert_validity + if 'validity' in template_dic: + self.logger.info('take validity from template: {0}'.format(template_dic['validity'])) + # take validity from template + cert_validity = template_dic['validity'] + else: + cert_validity = self.cert_validity_days + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(cert_validity * 86400) + + # get extension list + extension_list = self._extension_list_generate(template_dic, cert, ca_cert) + # add extensions (copy from CSR and take the ones we constructed) + cert.add_extensions(req.get_extensions()) + cert.add_extensions(extension_list) + + if dn_dic: + self.logger.info('modify subject with template data') + subject = self._subject_modify(subject, dn_dic) + cert.set_subject(subject) + + # sign csr + cert.sign(ca_key, 'sha256') + serial = cert.get_serial_number() + + # get hsshes + issuer_hash = ca_cert.subject_name_hash() & 0x7fffffff + name_hash = cert.subject_name_hash() & 0x7fffffff + + # store certificate + self._store_cert(ca_id, request_name, '{:X}'.format(serial), convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))), name_hash, issuer_hash) + + cert_bundle = self._pemcertchain_generate(convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)), convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, ca_cert))) + cert_raw = convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))) else: - cert_validity = self.cert_validity_days - cert.gmtime_adj_notBefore(0) - cert.gmtime_adj_notAfter(cert_validity * 86400) - - # get extension list - extension_list = self._extension_list_generate(template_dic, cert, ca_cert) - # add extensions (copy from CSR and take the ones we constructed) - cert.add_extensions(req.get_extensions()) - cert.add_extensions(extension_list) - - if dn_dic: - subject = self._subject_modify(subject, dn_dic) - cert.set_subject(subject) - - # sign csr - cert.sign(ca_key, 'sha256') - serial = cert.get_serial_number() - - # get hsshes - issuer_hash = ca_cert.subject_name_hash() & 0x7fffffff - name_hash = cert.subject_name_hash() & 0x7fffffff - - # store certificate - self._store_cert(ca_id, request_name, '{:X}'.format(serial), convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))), name_hash, issuer_hash) - - cert_bundle = self._pemcertchain_generate(convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)), convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, ca_cert))) - cert_raw = convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))) - + error = 'ca lookup failed' + else: + error = 'request_name lookup failed' self.logger.debug('Certificate.enroll() ended') return(error, cert_bundle, cert_raw, None) diff --git a/test/test_challenge.py b/test/test_challenge.py index 59bcf17a..72671f29 100644 --- a/test/test_challenge.py +++ b/test/test_challenge.py @@ -4,6 +4,7 @@ # pylint: disable=C0302, C0415, R0904, R0913, R0914, R0915, W0212 import unittest import sys +import configparser from unittest.mock import patch, MagicMock sys.path.insert(0, '.') @@ -306,9 +307,31 @@ def test_036_challenge__check(self): self.challenge.dbstore.jwk_load.return_value = None self.assertEqual((False, False), self.challenge._check('name', 'payload')) - @patch('acme.challenge.Challenge._validate_http_challenge') + @patch('acme.challenge.Challenge._validate_alpn_challenge') @patch('acme.challenge.jwk_thumbprint_get') def test_037_challenge__check(self, mock_jwk, mock_chall): + """ challenge check with with failed tls-alpn challenge """ + self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'tls-alpn-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} + self.challenge.dbstore.jwk_load.return_value = 'pub_key' + mock_chall.return_value = (False, 'foo') + mock_jwk.return_value = 'jwk_thumbprint' + self.assertEqual((False, 'foo'), self.challenge._check('name', 'payload')) + self.assertTrue(mock_chall.called) + + @patch('acme.challenge.Challenge._validate_alpn_challenge') + @patch('acme.challenge.jwk_thumbprint_get') + def test_038_challenge__check(self, mock_jwk, mock_chall): + """ challenge check with with succ tls-alpn challenge """ + self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'tls-alpn-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} + self.challenge.dbstore.jwk_load.return_value = 'pub_key' + mock_chall.return_value = (True, 'foo') + mock_jwk.return_value = 'jwk_thumbprint' + self.assertEqual((True, 'foo'), self.challenge._check('name', 'payload')) + self.assertTrue(mock_chall.called) + + @patch('acme.challenge.Challenge._validate_http_challenge') + @patch('acme.challenge.jwk_thumbprint_get') + def test_039_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with failed http challenge """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'http-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -318,7 +341,7 @@ def test_037_challenge__check(self, mock_jwk, mock_chall): @patch('acme.challenge.Challenge._validate_http_challenge') @patch('acme.challenge.jwk_thumbprint_get') - def test_038_challenge__check(self, mock_jwk, mock_chall): + def test_040_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with succ http challenge """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'http-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -328,7 +351,7 @@ def test_038_challenge__check(self, mock_jwk, mock_chall): @patch('acme.challenge.Challenge._validate_dns_challenge') @patch('acme.challenge.jwk_thumbprint_get') - def test_039_challenge__check(self, mock_jwk, mock_chall): + def test_041_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with failed dns challenge """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'dns-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -338,7 +361,7 @@ def test_039_challenge__check(self, mock_jwk, mock_chall): @patch('acme.challenge.Challenge._validate_dns_challenge') @patch('acme.challenge.jwk_thumbprint_get') - def test_040_challenge__check(self, mock_jwk, mock_chall): + def test_042_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with succ http challenge """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'dns-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -348,7 +371,7 @@ def test_040_challenge__check(self, mock_jwk, mock_chall): @patch('acme.challenge.Challenge._validate_tkauth_challenge') @patch('acme.challenge.jwk_thumbprint_get') - def test_041_challenge__check(self, mock_jwk, mock_chall): + def test_043_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with failed tkauth challenge tnauthlist_support not configured """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'tkauth-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -358,7 +381,7 @@ def test_041_challenge__check(self, mock_jwk, mock_chall): @patch('acme.challenge.Challenge._validate_tkauth_challenge') @patch('acme.challenge.jwk_thumbprint_get') - def test_042_challenge__check(self, mock_jwk, mock_chall): + def test_044_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with failed tkauth challenge tnauthlist_support True """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'tkauth-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -369,7 +392,7 @@ def test_042_challenge__check(self, mock_jwk, mock_chall): @patch('acme.challenge.Challenge._validate_tkauth_challenge') @patch('acme.challenge.jwk_thumbprint_get') - def test_043_challenge__check(self, mock_jwk, mock_chall): + def test_045_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with succ tkauth challenge and tnauthlist_support unset """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'tkauth-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -380,7 +403,7 @@ def test_043_challenge__check(self, mock_jwk, mock_chall): @patch('acme.challenge.Challenge._validate_tkauth_challenge') @patch('acme.challenge.jwk_thumbprint_get') - def test_044_challenge__check(self, mock_jwk, mock_chall): + def test_046_challenge__check(self, mock_jwk, mock_chall): """ challenge check with with succ tkauth challenge and tnauthlist support set """ self.challenge.dbstore.challenge_lookup.return_value = {'authorization__value' : 'authorization__value', 'type' : 'tkauth-01', 'token' : 'token', 'authorization__order__account__name' : 'authorization__order__account__name'} self.challenge.dbstore.jwk_load.return_value = 'pub_key' @@ -389,29 +412,45 @@ def test_044_challenge__check(self, mock_jwk, mock_chall): mock_jwk.return_value = 'jwk_thumbprint' self.assertEqual((True, 'foo'), self.challenge._check('name', 'payload')) - def test_045_challenge__wcd_manipulate(self): + def test_047_challenge__wcd_manipulate(self): """ get fqdn wc manipulation """ fqdn = 'foo.bar' self.assertEqual('foo.bar', self.challenge._wcd_manipulate(fqdn)) - def test_046_challenge__wcd_manipulate(self): + def test_048_challenge__wcd_manipulate(self): """ get fqdn wc manipulation """ fqdn = '*.foo.bar' self.assertEqual('foo.bar', self.challenge._wcd_manipulate(fqdn)) - def test_047_challenge__wcd_manipulate(self): + def test_049_challenge__wcd_manipulate(self): """ get fqdn wc manipulation """ fqdn = 'foo*.foo.bar' self.assertEqual('foo*.foo.bar', self.challenge._wcd_manipulate(fqdn)) - def test_048_challenge__challengelist_search(self): + def test_050_challenge__challengelist_search(self): + """ test Challenge._challengelist_search - one challenge """ + self.challenge.dbstore.challenges_search.return_value = [{'token': 'token', 'type': 'type', 'name': 'name'}] + self.challenge.path_dic = {'chall_path': '/chall_path/'} + self.challenge.server_name = 'server_name' + result = [{'name': 'name', 'token': 'token', 'type': 'type', 'url': 'server_name/chall_path/name'}] + self.assertEqual(result, self.challenge._challengelist_search('key', 'value')) + + def test_051_challenge__challengelist_search(self): + """ test Challenge._challengelist_search - two challenges """ + self.challenge.dbstore.challenges_search.return_value = [{'token': 'token1', 'type': 'type1', 'name': 'name1'}, {'token': 'token2', 'type': 'type2', 'name': 'name2'}] + self.challenge.path_dic = {'chall_path': '/chall_path/'} + self.challenge.server_name = 'server_name' + result = [{'name': 'name1', 'token': 'token1', 'type': 'type1', 'url': 'server_name/chall_path/name1'}, {'name': 'name2', 'token': 'token2', 'type': 'type2', 'url': 'server_name/chall_path/name2'}] + self.assertEqual(result, self.challenge._challengelist_search('key', 'value')) + + def test_052_challenge__challengelist_search(self): """ test Challenge._challengelist_search - dbstore.challenges_search() raises an exception """ self.challenge.dbstore.challenges_search.side_effect = Exception('exc_chall_search') with self.assertLogs('test_a2c', level='INFO') as lcm: self.challenge._challengelist_search('key', 'value') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._challengelist_search(): exc_chall_search', lcm.output) - def test_049_challenge__check(self): + def test_053_challenge__check(self): """ test Challenge._check - dbstore.jwk_load() raises an exception """ self.challenge.dbstore.jwk_load.side_effect = Exception('exc_jkw_load') self.challenge.dbstore.challenge_lookup.return_value = {'type': 'type', 'authorization__value': 'authorization__value', 'token': 'token', 'authorization__order__account__name': 'authorization__order__account__name'} @@ -419,35 +458,35 @@ def test_049_challenge__check(self): self.challenge._check('name', 'payload') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._check() jwk: exc_jkw_load', lcm.output) - def test_050_challenge__check(self): + def test_054_challenge__check(self): """ test Challenge._check - dbstore.challenge_lookup() raises an exception """ self.challenge.dbstore.challenge_lookup.side_effect = Exception('exc_chall_chk') with self.assertLogs('test_a2c', level='INFO') as lcm: self.challenge._check('name', 'payload') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._check() lookup: exc_chall_chk', lcm.output) - def test_051_challenge__info(self): + def test_055_challenge__info(self): """ test Challenge._info - dbstore.challenge_lookup() raises an exception """ self.challenge.dbstore.challenge_lookup.side_effect = Exception('exc_chall_info') with self.assertLogs('test_a2c', level='INFO') as lcm: self.challenge._info('name') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._info(): exc_chall_info', lcm.output) - def test_052_challenge__new(self): + def test_056_challenge__new(self): """ test Challenge._new - dbstore.challenge_add() raises an exception """ self.challenge.dbstore.challenge_add.side_effect = Exception('exc_chall_add') with self.assertLogs('test_a2c', level='INFO') as lcm: self.challenge._new('authz_name', 'mtype', 'token') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._new(): exc_chall_add', lcm.output) - def test_053_challenge__update(self): + def test_057_challenge__update(self): """ test Challenge._update - dbstore.challenge_update() raises an exception """ self.challenge.dbstore.challenge_update.side_effect = Exception('exc_chall_upd') with self.assertLogs('test_a2c', level='INFO') as lcm: self.challenge._update({'foo': 'bar'}) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._update(): exc_chall_upd', lcm.output) - def test_054_challenge__update_authz(self): + def test_058_challenge__update_authz(self): """ test Challenge._update_authz - dbstore.authorization_update() raises an exception """ self.challenge.dbstore.authorization_update.side_effect = Exception('exc_chall_autz_upd') self.challenge.dbstore.challenge_lookup.return_value = {'authorization__name': 'authorization__name', 'authorization': 'authorization'} @@ -455,7 +494,7 @@ def test_054_challenge__update_authz(self): self.challenge._update_authz('name', {'foo': 'bar'}) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._update_authz() upd: exc_chall_autz_upd', lcm.output) - def test_055_challenge__update_authz(self): + def test_059_challenge__update_authz(self): """ test Challenge._update_authz - dbstore.authorization_update() raises an exception """ self.challenge.dbstore.challenge_lookup.side_effect = Exception('exc_chall_lookup_foo') with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -463,14 +502,14 @@ def test_055_challenge__update_authz(self): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Challenge._update_authz() lookup: exc_chall_lookup_foo', lcm.output) @patch('acme.challenge.fqdn_resolve') - def test_056_challenge__validate_alpn_challenge(self, mock_resolve): + def test_060_challenge__validate_alpn_challenge(self, mock_resolve): """ test validate_alpn_challenge fqdn_resolve returned Invalid """ mock_resolve.return_value = (None, True) self.assertEqual((False, True), self.challenge._validate_alpn_challenge('cert_name', 'fqdn', 'token', 'jwk_thumbprint')) @patch('acme.challenge.servercert_get') @patch('acme.challenge.fqdn_resolve') - def test_057_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv): + def test_061_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv): """ test validate_alpn_challenge no certificate returned """ mock_resolve.return_value = ('foo', False) mock_srv.return_value = None @@ -480,7 +519,7 @@ def test_057_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv): @patch('acme.challenge.cert_san_get') @patch('acme.challenge.servercert_get') @patch('acme.challenge.fqdn_resolve') - def test_058_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mock_sanget, mock_sanchk): + def test_062_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mock_sanget, mock_sanchk): """ test validate_alpn_challenge sancheck returned false """ mock_resolve.return_value = ('foo', False) mock_sanget.return_value = ['foo', 'bar'] @@ -494,7 +533,7 @@ def test_058_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mo @patch('acme.challenge.cert_san_get') @patch('acme.challenge.servercert_get') @patch('acme.challenge.fqdn_resolve') - def test_059_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mock_sanget, mock_sanchk, mock_encode, mock_ext): + def test_063_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mock_sanget, mock_sanchk, mock_encode, mock_ext): """ test validate_alpn_challenge extension check failed """ mock_resolve.return_value = ('foo', False) mock_sanget.return_value = ['foo', 'bar'] @@ -510,7 +549,7 @@ def test_059_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mo @patch('acme.challenge.cert_san_get') @patch('acme.challenge.servercert_get') @patch('acme.challenge.fqdn_resolve') - def test_060_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mock_sanget, mock_sanchk, mock_encode, mock_ext): + def test_064_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mock_sanget, mock_sanchk, mock_encode, mock_ext): """ test validate_alpn_challenge extension sucessful """ mock_resolve.return_value = ('foo', False) mock_sanget.return_value = ['foo', 'bar'] @@ -520,5 +559,268 @@ def test_060_challenge__validate_alpn_challenge(self, mock_resolve, mock_srv, mo mock_ext.return_value = ['foobar', 'bar', 'foo'] self.assertEqual((True, False), self.challenge._validate_alpn_challenge('cert_name', 'fqdn', 'token', 'jwk_thumbprint')) + @patch('acme.challenge.Challenge._validate') + def test_065__existing_challenge_validate(self, mock_validate): + """ validate challenge with empty challenge list """ + challenge_list = [] + self.challenge._existing_challenge_validate(challenge_list) + self.assertFalse(mock_validate.called) + + @patch('acme.challenge.Challenge._validate') + def test_066__existing_challenge_validate(self, mock_validate): + """ validate challenge with challenge list """ + challenge_list = ['foo'] + self.challenge._existing_challenge_validate(challenge_list) + self.assertTrue(mock_validate.called) + + @patch('acme.challenge.load_config') + def test_067_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + # parser['Account'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + self.challenge._config_load() + self.assertFalse(self.challenge.challenge_validation_disable) + self.assertFalse(self.challenge.tnauthlist_support) + self.assertFalse(self.challenge.dns_server_list ) + + @patch('acme.challenge.load_config') + def test_068_config_load(self, mock_load_cfg): + """ test _config_load challenge_validation_disable False """ + parser = configparser.ConfigParser() + parser['Challenge'] = {'challenge_validation_disable': False} + mock_load_cfg.return_value = parser + self.challenge._config_load() + self.assertFalse(self.challenge.challenge_validation_disable) + self.assertFalse(self.challenge.tnauthlist_support) + self.assertFalse(self.challenge.dns_server_list) + + @patch('acme.challenge.load_config') + def test_069_config_load(self, mock_load_cfg): + """ test _config_load challenge_validation_disable True """ + parser = configparser.ConfigParser() + parser['Challenge'] = {'challenge_validation_disable': True} + mock_load_cfg.return_value = parser + self.challenge._config_load() + self.assertTrue(self.challenge.challenge_validation_disable) + self.assertFalse(self.challenge.tnauthlist_support) + self.assertFalse(self.challenge.dns_server_list) + + @patch('acme.challenge.load_config') + def test_070_config_load(self, mock_load_cfg): + """ test _config_load tnauthlist_support False """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': False} + mock_load_cfg.return_value = parser + self.challenge._config_load() + self.assertFalse(self.challenge.challenge_validation_disable) + self.assertFalse(self.challenge.tnauthlist_support) + self.assertFalse(self.challenge.dns_server_list) + + @patch('acme.challenge.load_config') + def test_071_config_load(self, mock_load_cfg): + """ test _config_load tnauthlist_support True """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': True} + mock_load_cfg.return_value = parser + self.challenge._config_load() + self.assertFalse(self.challenge.challenge_validation_disable) + self.assertTrue(self.challenge.tnauthlist_support) + self.assertFalse(self.challenge.dns_server_list) + + @patch('acme.challenge.load_config') + def test_072_config_load(self, mock_load_cfg): + """ test _config_load one DNS """ + parser = configparser.ConfigParser() + parser['Challenge'] = {'dns_server_list': '["10.10.10.10"]'} + mock_load_cfg.return_value = parser + self.challenge._config_load() + self.assertFalse(self.challenge.challenge_validation_disable) + self.assertFalse(self.challenge.tnauthlist_support) + self.assertEqual(['10.10.10.10'], self.challenge.dns_server_list) + + @patch('acme.challenge.load_config') + def test_073_config_load(self, mock_load_cfg): + """ test _config_load two DNS """ + parser = configparser.ConfigParser() + parser['Challenge'] = {'dns_server_list': '["10.10.10.10", "10.0.0.1"]'} + mock_load_cfg.return_value = parser + self.challenge._config_load() + self.assertFalse(self.challenge.challenge_validation_disable) + self.assertFalse(self.challenge.tnauthlist_support) + self.assertEqual(['10.10.10.10', '10.0.0.1'], self.challenge.dns_server_list) + + @patch('json.loads') + @patch('acme.challenge.load_config') + def test_074_config_load(self, mock_load_cfg, mock_json): + """ test _config_load two DNS """ + parser = configparser.ConfigParser() + parser['Challenge'] = {'dns_server_list': '["10.10.10.10", "10.0.0.1"]'} + mock_load_cfg.return_value = parser + mock_json.side_effect = Exception('exc_mock_json') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.challenge._config_load() + self.assertIn('WARNING:test_a2c:Challenge._config_load() failed with error: exc_mock_json', lcm.output) + self.assertFalse(self.challenge.challenge_validation_disable) + self.assertFalse(self.challenge.tnauthlist_support) + self.assertFalse(self.challenge.dns_server_list) + + + def test_075__name_get(self): + """ test name get no touch""" + url = 'foo' + self.assertEqual('foo', self.challenge._name_get(url)) + + @patch('acme.challenge.parse_url') + def test_076__name_get(self, mock_parse): + """ test name get urlparse""" + mock_parse.return_value = {'path': 'path'} + url = 'foo' + self.assertEqual('path', self.challenge._name_get(url)) + + @patch('acme.challenge.parse_url') + def test_077__name_get(self, mock_parse): + """ test name get challenge_path replace """ + mock_parse.return_value = {'path': 'foo/my_path'} + self.challenge.path_dic = {'chall_path': 'foo/'} + url = 'foo' + self.assertEqual('my_path', self.challenge._name_get(url)) + + @patch('acme.challenge.parse_url') + def test_078__name_get(self, mock_parse): + """ test name get challenge_path replace """ + mock_parse.return_value = {'path': 'foo/my/path'} + self.challenge.path_dic = {'chall_path': 'foo/'} + url = 'foo' + self.assertEqual('my', self.challenge._name_get(url)) + + @patch('acme.challenge.Challenge._update_authz') + @patch('acme.challenge.Challenge._update') + def test_079__validate(self, mock_update, mock_aupdate): + """ test validate """ + challenge_name = 'challenge_name' + payload = 'payload' + mock_update.return_value = True + mock_aupdate.return_value = True + self.challenge.challenge_validation_disable = True + self.assertTrue(self.challenge._validate(challenge_name, payload)) + self.assertTrue(mock_update.called) + self.assertTrue(mock_aupdate.called) + + @patch('acme.challenge.Challenge._check') + @patch('acme.challenge.Challenge._update_authz') + @patch('acme.challenge.Challenge._update') + def test_080__validate(self, mock_update, mock_aupdate, mock_check): + """ test validate check returned ch:False/inv:False """ + challenge_name = 'challenge_name' + payload = 'payload' + mock_update.return_value = True + mock_aupdate.return_value = True + mock_check.return_value = (False, False) + self.assertFalse(self.challenge._validate(challenge_name, payload)) + self.assertFalse(mock_update.called) + self.assertFalse(mock_aupdate.called) + + @patch('acme.challenge.Challenge._check') + @patch('acme.challenge.Challenge._update_authz') + @patch('acme.challenge.Challenge._update') + def test_081__validate(self, mock_update, mock_aupdate, mock_check): + """ test validate check returned ch:False/inv:True """ + challenge_name = 'challenge_name' + payload = 'payload' + mock_update.return_value = True + mock_aupdate.return_value = True + mock_check.return_value = (False, True) + self.assertFalse(self.challenge._validate(challenge_name, payload)) + self.assertTrue(mock_update.called) + self.assertTrue(mock_aupdate.called) + + @patch('acme.challenge.Challenge._check') + @patch('acme.challenge.Challenge._update_authz') + @patch('acme.challenge.Challenge._update') + def test_082__validate(self, mock_update, mock_aupdate, mock_check): + """ test validate check returned ch:True/inv:False """ + challenge_name = 'challenge_name' + payload = 'payload' + mock_update.return_value = True + mock_aupdate.return_value = True + mock_check.return_value = (True, False) + self.assertTrue(self.challenge._validate(challenge_name, payload)) + self.assertTrue(mock_update.called) + self.assertTrue(mock_aupdate.called) + + @patch('acme.challenge.Challenge._check') + @patch('acme.challenge.Challenge._update_authz') + @patch('acme.challenge.Challenge._update') + def test_083__validate(self, mock_update, mock_aupdate, mock_check): + """ test validate check returned ch:True/inv:True """ + challenge_name = 'challenge_name' + payload = 'payload' + mock_update.return_value = True + mock_aupdate.return_value = True + mock_check.return_value = (True, True) + self.assertTrue(self.challenge._validate(challenge_name, payload)) + self.assertTrue(mock_update.called) + self.assertTrue(mock_aupdate.called) + + @patch('acme.challenge.Challenge._check') + @patch('acme.challenge.Challenge._update_authz') + @patch('acme.challenge.Challenge._update') + def test_084__validate(self, mock_update, mock_aupdate, mock_check): + """ test validate check returned ch:True/inv:False """ + challenge_name = 'challenge_name' + payload = {'keyAuthorization': 'keyAuthorization'} + mock_update.return_value = True + mock_aupdate.return_value = True + mock_check.return_value = (True, False) + self.assertTrue(self.challenge._validate(challenge_name, payload)) + self.assertTrue(mock_update.called) + self.assertTrue(mock_aupdate.called) + + @patch('acme.challenge.Challenge._name_get') + @patch('acme.challenge.Challenge._info') + def test_085_get(self, mock_info, mock_name): + """ test get """ + mock_info.return_value = 'chall_info' + mock_name.return_value = 'foo' + self.assertEqual({'code': 200, 'data': 'chall_info'}, self.challenge.get('url')) + self.assertTrue(mock_name.called) + + @patch('acme.challenge.Challenge.new_set') + @patch('acme.challenge.Challenge._existing_challenge_validate') + @patch('acme.challenge.Challenge._challengelist_search') + def test_086_challengeset_get(self, mock_chsearch, mock_val, mock_set): + """ test challengeset_get - no challenge_list returned """ + mock_chsearch.return_value = [] + mock_val.return_value = True + mock_set.return_value = 'new_set' + self.assertEqual('new_set', self.challenge.challengeset_get('authz_name', 'auth_status', 'token', 'tnauth')) + self.assertTrue(mock_set.called) + self.assertFalse(mock_val.called) + + @patch('acme.challenge.Challenge.new_set') + @patch('acme.challenge.Challenge._existing_challenge_validate') + @patch('acme.challenge.Challenge._challengelist_search') + def test_087_challengeset_get(self, mock_chsearch, mock_val, mock_set): + """ test challengeset_get - challenge_list returned """ + mock_chsearch.return_value = [{'name': 'name1', 'foo': 'bar'}] + mock_val.return_value = True + mock_set.return_value = 'new_set' + self.assertEqual([{'foo': 'bar'}], self.challenge.challengeset_get('authz_name', 'auth_status', 'token', 'tnauth')) + self.assertFalse(mock_set.called) + self.assertFalse(mock_val.called) + + @patch('acme.challenge.Challenge.new_set') + @patch('acme.challenge.Challenge._existing_challenge_validate') + @patch('acme.challenge.Challenge._challengelist_search') + def test_088_challengeset_get(self, mock_chsearch, mock_val, mock_set): + """ test challengeset_get - challenge_list returned autzstatus pending """ + mock_chsearch.return_value = [{'name': 'name1', 'foo': 'bar'}] + mock_val.return_value = True + mock_set.return_value = 'new_set' + self.assertEqual([{'foo': 'bar'}], self.challenge.challengeset_get('authz_name', 'pending', 'token', 'tnauth')) + self.assertFalse(mock_set.called) + self.assertTrue(mock_val.called) + if __name__ == '__main__': unittest.main() diff --git a/test/test_helper.py b/test/test_helper.py index 73ecbf01..8966a561 100644 --- a/test/test_helper.py +++ b/test/test_helper.py @@ -5,6 +5,7 @@ import unittest import sys import datetime +import socket from unittest.mock import patch, MagicMock, Mock import dns.resolver @@ -27,8 +28,9 @@ def setUp(self): patch.dict('sys.modules', modules).start() import logging logging.basicConfig(level=logging.CRITICAL) - from acme.helper import b64decode_pad, b64_decode, b64_encode, b64_url_encode, b64_url_recode, ca_handler_get, convert_string_to_byte, convert_byte_to_string, decode_message, decode_deserialize, get_url, generate_random_string, signature_check, validate_email, uts_to_date_utc, date_to_uts_utc, load_config, cert_serial_get, cert_san_get, cert_dates_get, build_pem_file, date_to_datestr, datestr_to_date, dkeys_lower, csr_cn_get, cert_pubkey_get, csr_pubkey_get, url_get, url_get_with_own_dns, dns_server_list_load, csr_san_get, csr_extensions_get, fqdn_resolve, fqdn_in_san_check, sha256_hash, sha256_hash_hex + from acme.helper import b64decode_pad, b64_decode, b64_encode, b64_url_encode, b64_url_recode, ca_handler_get, convert_string_to_byte, convert_byte_to_string, decode_message, decode_deserialize, get_url, generate_random_string, signature_check, validate_email, uts_to_date_utc, date_to_uts_utc, load_config, cert_serial_get, cert_san_get, cert_dates_get, build_pem_file, date_to_datestr, datestr_to_date, dkeys_lower, csr_cn_get, cert_pubkey_get, csr_pubkey_get, url_get, url_get_with_own_dns, dns_server_list_load, csr_san_get, csr_extensions_get, fqdn_resolve, fqdn_in_san_check, sha256_hash, sha256_hash_hex, cert_der2pem, cert_pem2der, cert_extensions_get, csr_dn_get, logger_setup, logger_info, print_debug, jwk_thumbprint_get, allowed_gai_family, patched_create_connection, validate_csr, servercert_get, txt_get self.logger = logging.getLogger('test_a2c') + self.allowed_gai_family = allowed_gai_family self.b64_decode = b64_decode self.b64_encode = b64_encode self.b64_url_encode = b64_url_encode @@ -37,12 +39,16 @@ def setUp(self): self.build_pem_file = build_pem_file self.ca_handler_get = ca_handler_get self.cert_dates_get = cert_dates_get + self.cert_extensions_get = cert_extensions_get self.cert_pubkey_get = cert_pubkey_get self.cert_san_get = cert_san_get self.cert_serial_get = cert_serial_get + self.cert_pem2der = cert_pem2der + self.cert_der2pem = cert_der2pem self.convert_byte_to_string = convert_byte_to_string self.convert_string_to_byte = convert_string_to_byte self.csr_cn_get = csr_cn_get + self.csr_dn_get = csr_dn_get self.csr_extensions_get = csr_extensions_get self.csr_pubkey_get = csr_pubkey_get self.csr_san_get = csr_san_get @@ -57,12 +63,20 @@ def setUp(self): self.fqdn_in_san_check = fqdn_in_san_check self.generate_random_string = generate_random_string self.get_url = get_url + self.jwk_thumbprint_get = jwk_thumbprint_get self.load_config = load_config + self.logger_setup = logger_setup + self.logger_info = logger_info + self.patched_create_connection = patched_create_connection + self.print_debug = print_debug + self.servercert_get = servercert_get self.signature_check = signature_check + self.txt_get = txt_get self.url_get = url_get self.url_get_with_own_dns = url_get_with_own_dns self.uts_to_date_utc = uts_to_date_utc self.validate_email = validate_email + self.validate_csr = validate_csr self.sha256_hash = sha256_hash self.sha256_hash_hex = sha256_hash_hex @@ -242,13 +256,40 @@ def test_036_helper_b64_url_recode(self): """ test base64url replace _ with / and pad""" self.assertEqual('fafa/f==', self.b64_url_recode(self.logger, b'fafa_f')) - def test_037_helper_decode_message(self): + @patch('__main__.sys') + def test_037_helper_b64_url_recode(self, mock_sys): + """ test base64url replace _ with / and pad""" + mock_sys.version_info = (2,7,11) + self.assertEqual('fafa/f==', self.b64_url_recode(self.logger, b'fafa_f')) + + def test_038_helper_decode_message(self): """ decode message with empty payload - certbot issue""" data_dic = '{"protected": "eyJub25jZSI6ICIyNmU2YTQ2ZWZhZGQ0NzdkOTA4ZDdjMjAxNGU0OWIzNCIsICJ1cmwiOiAiaHR0cDovL2xhcHRvcC5uY2xtLXNhbWJhLmxvY2FsL2FjbWUvYXV0aHovUEcxODlGRnpmYW8xIiwgImtpZCI6ICJodHRwOi8vbGFwdG9wLm5jbG0tc2FtYmEubG9jYWwvYWNtZS9hY2N0L3l1WjFHVUpiNzZaayIsICJhbGciOiAiUlMyNTYifQ", "payload": "", "signature": "ZW5jb2RlZF9zaWduYXR1cmU="}' e_result = (True, None, {u'nonce': u'26e6a46efadd477d908d7c2014e49b34', u'url': u'http://laptop.nclm-samba.local/acme/authz/PG189FFzfao1', u'alg': u'RS256', u'kid': u'http://laptop.nclm-samba.local/acme/acct/yuZ1GUJb76Zk'}, {}, b'encoded_signature') self.assertEqual(e_result, self.decode_message(self.logger, data_dic)) - def test_038_helper_cert_serial_get(self): + def test_039_helper_decode_message(self): + """ decode message with empty payload - certbot issue""" + data_dic = '{"protected": "eyJub25jZSI6ICIyNmU2YTQ2ZWZhZGQ0NzdkOTA4ZDdjMjAxNGU0OWIzNCIsICJ1cmwiOiAiaHR0cDovL2xhcHRvcC5uY2xtLXNhbWJhLmxvY2FsL2FjbWUvYXV0aHovUEcxODlGRnpmYW8xIiwgImtpZCI6ICJodHRwOi8vbGFwdG9wLm5jbG0tc2FtYmEubG9jYWwvYWNtZS9hY2N0L3l1WjFHVUpiNzZaayIsICJhbGciOiAiUlMyNTYifQ", "payload": "eyJmb28iOiAiYmFyMSJ9", "signature": "ZW5jb2RlZF9zaWduYXR1cmU="}' + e_result = (True, None, {u'nonce': u'26e6a46efadd477d908d7c2014e49b34', u'url': u'http://laptop.nclm-samba.local/acme/authz/PG189FFzfao1', u'alg': u'RS256', u'kid': u'http://laptop.nclm-samba.local/acme/acct/yuZ1GUJb76Zk'}, {'foo': 'bar1'}, b'encoded_signature') + self.assertEqual(e_result, self.decode_message(self.logger, data_dic)) + + @patch('json.loads') + def test_040_helper_decode_message(self, mock_json): + """ decode message with with exception during decoding """ + mock_json.side_effect = Exception('exc_mock_json') + data_dic = '{"protected": "eyJub25jZSI6ICIyNmU2YTQ2ZWZhZGQ0NzdkOTA4ZDdjMjAxNGU0OWIzNCIsICJ1cmwiOiAiaHR0cDovL2xhcHRvcC5uY2xtLXNhbWJhLmxvY2FsL2FjbWUvYXV0aHovUEcxODlGRnpmYW8xIiwgImtpZCI6ICJodHRwOi8vbGFwdG9wLm5jbG0tc2FtYmEubG9jYWwvYWNtZS9hY2N0L3l1WjFHVUpiNzZaayIsICJhbGciOiAiUlMyNTYifQ", "payload": "", "signature": "ZW5jb2RlZF9zaWduYXR1cmU="}' + if int('%i%i' % (sys.version_info[0], sys.version_info[1])) < 37: + result = 'ERROR:test_a2c:decode_message() err: Invalid JWS Object [Invalid format] {Exception(\'exc_mock_json\',)}' + e_result = (False, "Invalid JWS Object [Invalid format] {Exception('exc_mock_json',)}", {}, {}, None) + else: + result = 'ERROR:test_a2c:decode_message() err: Invalid JWS Object [Invalid format] {Exception(\'exc_mock_json\')}' + e_result = (False, "Invalid JWS Object [Invalid format] {Exception('exc_mock_json')}", {}, {}, None) + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(e_result, self.decode_message(self.logger, data_dic)) + self.assertIn(result, lcm.output) + + def test_041_helper_cert_serial_get(self): """ test cert_serial_get """ cert = """MIIDDTCCAfWgAwIBAgIBCjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9mb28u ZXhhbXBsZS5jb20wHhcNMTkwMTIwMTY1OTIwWhcNMTkwMjE5MTY1OTIwWjAaMRgw @@ -269,7 +310,7 @@ def test_038_helper_cert_serial_get(self): t+eRUDECE+0UnjyeCjTn3EU=""" self.assertEqual(10, self.cert_serial_get(self.logger, cert)) - def test_039_helper_cert_san_get(self): + def test_042_helper_cert_san_get(self): """ test cert_san_get for a single SAN """ cert = """MIIDDTCCAfWgAwIBAgIBCjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9mb28u ZXhhbXBsZS5jb20wHhcNMTkwMTIwMTY1OTIwWhcNMTkwMjE5MTY1OTIwWjAaMRgw @@ -290,7 +331,7 @@ def test_039_helper_cert_san_get(self): t+eRUDECE+0UnjyeCjTn3EU=""" self.assertEqual(['DNS:foo.example.com'], self.cert_san_get(self.logger, cert)) - def test_040_helper_cert_san_get(self): + def test_043_helper_cert_san_get(self): """ test cert_san_get for a multiple SAN of type DNS""" cert = """MIIDIzCCAgugAwIBAgICBZgwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UEAxMPZm9v LmV4YW1wbGUuY29tMB4XDTE5MDEyMDE3MDkxMVoXDTE5MDIxOTE3MDkxMVowGjEY @@ -311,7 +352,7 @@ def test_040_helper_cert_san_get(self): NWQddOR8IHg+v6lWc9BtuuKK5ubsg6XOiEjhhr42AKViKalX1i4+""" self.assertEqual(['DNS:foo-2.example.com', 'DNS:foo-1.example.com'], self.cert_san_get(self.logger, cert)) - def test_041_helper_cert_serial_get(self): + def test_044_helper_cert_serial_get(self): """ test cert_serial for a multiple SAN of different types""" cert = """MIIDIzCCAgugAwIBAgICBZgwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UEAxMPZm9v LmV4YW1wbGUuY29tMB4XDTE5MDEyMDE3MDkxMVoXDTE5MDIxOTE3MDkxMVowGjEY @@ -332,7 +373,7 @@ def test_041_helper_cert_serial_get(self): NWQddOR8IHg+v6lWc9BtuuKK5ubsg6XOiEjhhr42AKViKalX1i4+""" self.assertEqual(1432, self.cert_serial_get(self.logger, cert)) - def test_042_helper_cert_san_get(self): + def test_045_helper_cert_san_get(self): """ test cert_san_get for a single SAN and recode = True""" cert = """MIIDDTCCAfWgAwIBAgIBCjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9mb28u ZXhhbXBsZS5jb20wHhcNMTkwMTIwMTY1OTIwWhcNMTkwMjE5MTY1OTIwWjAaMRgw @@ -353,7 +394,7 @@ def test_042_helper_cert_san_get(self): t+eRUDECE+0UnjyeCjTn3EU=""" self.assertEqual(['DNS:foo.example.com'], self.cert_san_get(self.logger, cert, recode=True)) - def test_043_helper_cert_san_get(self): + def test_046_helper_cert_san_get(self): """ test cert_san_get for a single SAN and recode = False""" cert = """-----BEGIN CERTIFICATE-----\nMIIDDTCCAfWgAwIBAgIBCjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9mb28u ZXhhbXBsZS5jb20wHhcNMTkwMTIwMTY1OTIwWhcNMTkwMjE5MTY1OTIwWjAaMRgw @@ -375,31 +416,38 @@ def test_043_helper_cert_san_get(self): self.assertEqual(['DNS:foo.example.com'], self.cert_san_get(self.logger, cert, recode=False)) - def test_044_helper_build_pem_file(self): + def test_047_helper_build_pem_file(self): """ test build_pem_file without exsting content """ existing = None cert = 'cert' self.assertEqual('-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n', self.build_pem_file(self.logger, existing, cert, True)) - def test_045_helper_build_pem_file(self): + def test_048_helper_build_pem_file(self): """ test build_pem_file with exsting content """ existing = 'existing' cert = 'cert' self.assertEqual('existing-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n', self.build_pem_file(self.logger, existing, cert, True)) - def test_046_helper_build_pem_file(self): + def test_049_helper_build_pem_file(self): """ test build_pem_file with long cert (to test wrap) """ existing = None cert = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' self.assertEqual('-----BEGIN CERTIFICATE-----\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\naaaaaaaaa\n-----END CERTIFICATE-----\n', self.build_pem_file(self.logger, existing, cert, True)) - def test_047_helper_build_pem_file(self): + def test_050_helper_build_pem_file(self): """ test build_pem_file with long cert (to test wrap) """ existing = None cert = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' self.assertEqual('-----BEGIN CERTIFICATE-----\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n-----END CERTIFICATE-----\n', self.build_pem_file(self.logger, existing, cert, False)) - def test_048_helper_build_pem_file(self): + def test_051_helper_build_pem_file(self): + """ test build_pem_file with long cert (to test wrap) """ + existing = 'existing' + cert = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + self.assertEqual('existing-----BEGIN CERTIFICATE-----\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n-----END CERTIFICATE-----\n', self.build_pem_file(self.logger, existing, cert, False)) + + + def test_052_helper_build_pem_file(self): """ test build_pem_file for CSR """ existing = None csr = 'MIIClzCCAX8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBvH7P73CwR7AF/WGeTfIDLlMWD6VZV3CTZBF0AwNMTFU/zbdAX8r63pzElX/5C5ZVsc36XHqdAJcioJlI33uE3RhOSvDyOcDgWlnPK9gj2soQ7enizGqd1u7hf6C3IwFtc4uGNOU3Z/tnTzVdYiCSKS+5lTZfMxn4FtEUN+w90NHBvC+AlTo3Gl0gqbYOZgg/UwWj60u7S2gBzSeb2/w62Z7bz+SknGZbeI4ySo30ET6oCSCAUN42jE+1dHI/Y+tGBtqP3h7W7OezKeLsJjD9r07U0+uMoVCY9oKTyT0gK8+gsde0tpt6QKa93HJGUPAP9ehrKCl335QcJESFw67/AgMBAAGgOTA3BgkqhkiG9w0BCQ4xKjAoMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEAf4cdGpYHLqX+06BFF7+NqXLmKvc7n66vAfevLN75eu/pCXhhRSdpXvcYm+mAVEXJCPaG2kFGt6wfBvVWoVX/91d+OuAtiUHmhY95Oi7g3RF3ThCrvT2mR4zsNiKgC34jXbl9489iIiFRBQXkq2fLwN5JwBYutUENwkDIeApRRbmUzTDbar1xoBAQ3GjVtOAEjHc/3S1yyKkCpM6Qkg8uWOJAXw9INJqH6x55nMZrvTUuXkURc/mvhV+bp2vdKoigGvfa3VVfoAI0BZLQMohQ9QLKoNQsKxEs3JidvpZrl3o23LMGEPoJs3zIuowTa217PHwdBw4UwtD7KxJK/+344A==' @@ -422,59 +470,59 @@ def test_048_helper_build_pem_file(self): """ self.assertEqual(result, self.build_pem_file(self.logger, existing, csr, False, True)) - def test_049_helper_b64_decode(self): + def test_053_helper_b64_decode(self): """ test bas64 decoder for string value""" self.assertEqual('test', self.b64_decode(self.logger, 'dGVzdA==')) - def test_050_helper_b64_decode(self): + def test_054_helper_b64_decode(self): """ test bas64 decoder for byte value """ self.assertEqual('test', self.b64_decode(self.logger, b'dGVzdA==')) - def test_051_helper_date_to_datestr(self): + def test_055_helper_date_to_datestr(self): """ convert dateobj to date-string with default format""" self.assertEqual('2019-10-27T00:00:00Z', self.date_to_datestr(datetime.date(2019, 10, 27))) - def test_052_helper_date_to_datestr(self): + def test_056_helper_date_to_datestr(self): """ convert dateobj to date-string with a predefined format""" self.assertEqual('2019.10.27', self.date_to_datestr(datetime.date(2019, 10, 27), '%Y.%m.%d')) - def test_053_helper_date_to_datestr(self): + def test_057_helper_date_to_datestr(self): """ convert dateobj to date-string for an knvalid date""" self.assertEqual(None, self.date_to_datestr('foo', '%Y.%m.%d')) - def test_054_helper_datestr_to_date(self): + def test_058_helper_datestr_to_date(self): """ convert datestr to date with default format""" self.assertEqual(datetime.datetime(2019, 11, 27, 0, 1, 2), self.datestr_to_date('2019-11-27T00:01:02')) - def test_055_helper_datestr_to_date(self): + def test_059_helper_datestr_to_date(self): """ convert datestr to date with predefined format""" self.assertEqual(datetime.datetime(2019, 11, 27, 0, 0, 0), self.datestr_to_date('2019.11.27', '%Y.%m.%d')) - def test_056_helper_datestr_to_date(self): + def test_060_helper_datestr_to_date(self): """ convert datestr to date with invalid format""" self.assertEqual(None, self.datestr_to_date('foo', '%Y.%m.%d')) - def test_057_helper_dkeys_lower(self): + def test_061_helper_dkeys_lower(self): """ dkeys_lower with a simple string """ tree = 'fOo' self.assertEqual('fOo', self.dkeys_lower(tree)) - def test_058_helper_dkeys_lower(self): + def test_062_helper_dkeys_lower(self): """ dkeys_lower with a simple list """ tree = ['fOo', 'bAr'] self.assertEqual(['fOo', 'bAr'], self.dkeys_lower(tree)) - def test_059_helper_dkeys_lower(self): + def test_063_helper_dkeys_lower(self): """ dkeys_lower with a simple dictionary """ tree = {'kEy': 'vAlUe'} self.assertEqual({'key': 'vAlUe'}, self.dkeys_lower(tree)) - def test_060_helper_dkeys_lower(self): + def test_064_helper_dkeys_lower(self): """ dkeys_lower with a nested dictionary containg strings, list and dictionaries""" tree = {'kEy1': 'vAlUe2', 'keys2': ['lIsT2', {'kEyS3': 'vAlUe3', 'kEyS4': 'vAlUe3'}], 'keys4': {'kEyS4': 'vAluE5', 'kEyS5': 'vAlUE6'}} self.assertEqual({'key1': 'vAlUe2', 'keys2': ['lIsT2', {'keys3': 'vAlUe3', 'keys4': 'vAlUe3'}], 'keys4': {'keys5': 'vAlUE6', 'keys4': 'vAluE5'}}, self.dkeys_lower(tree)) - def test_061_helper_cert_pubkey_get(self): + def test_065_helper_cert_pubkey_get(self): """ test get public_key from certificate """ cert = """ -----BEGIN X509 CERTIFICATE----- @@ -518,7 +566,7 @@ def test_061_helper_cert_pubkey_get(self): """ self.assertEqual(pub_key, self.cert_pubkey_get(self.logger, cert)) - def test_062_helper_csr_pubkey_get(self): + def test_066_helper_csr_pubkey_get(self): """ test get public_key from certificate """ csr = """MIIClzCCAX8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBvH7P73CwR7AF/WGeTfIDLlMWD6VZV3CTZBF0AwNMTFU/zbdAX8r63pzElX/5C5ZVsc36XHqdAJcioJlI33uE3RhOSvDyOcDgWlnPK9gj2soQ7enizGqd1u7hf6C3IwFtc4uGNOU3Z/tnTzVdYiCSKS+5lTZfMxn4FtEUN+w90NHBvC+AlTo3Gl0gqbYOZgg/UwWj60u7S2gBzSeb2/w62Z7bz+SknGZbeI4ySo30ET6oCSCAUN42jE+1dHI/Y+tGBtqP3h7W7OezKeLsJjD9r07U0+uMoVCY9oKTyT0gK8+gsde0tpt6QKa93HJGUPAP9ehrKCl335QcJESFw67/AgMBAAGgOTA3BgkqhkiG9w0BCQ4xKjAoMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEAf4cdGpYHLqX+06BFF7+NqXLmKvc7n66vAfevLN75eu/pCXhhRSdpXvcYm+mAVEXJCPaG2kFGt6wfBvVWoVX/91d+OuAtiUHmhY95Oi7g3RF3ThCrvT2mR4zsNiKgC34jXbl9489iIiFRBQXkq2fLwN5JwBYutUENwkDIeApRRbmUzTDbar1xoBAQ3GjVtOAEjHc/3S1yyKkCpM6Qkg8uWOJAXw9INJqH6x55nMZrvTUuXkURc/mvhV+bp2vdKoigGvfa3VVfoAI0BZLQMohQ9QLKoNQsKxEs3JidvpZrl3o23LMGEPoJs3zIuowTa217PHwdBw4UwtD7KxJK/+344A==""" @@ -534,131 +582,153 @@ def test_062_helper_csr_pubkey_get(self): """ self.assertEqual(pub_key, self.csr_pubkey_get(self.logger, csr)) - def test_063_helper_convert_byte_to_string(self): + def test_067_helper_convert_byte_to_string(self): """ convert byte2string for a string value """ self.assertEqual('foo', self.convert_byte_to_string('foo')) - def test_064_helper_convert_byte_to_string(self): + def test_068_helper_convert_byte_to_string(self): """ convert byte2string for a string value """ self.assertEqual('foo', self.convert_byte_to_string('foo')) - def test_065_helper_convert_byte_to_string(self): + def test_069_helper_convert_byte_to_string(self): """ convert byte2string for a string value """ self.assertNotEqual('foo', self.convert_byte_to_string('foobar')) - def test_066_helper_convert_byte_to_string(self): + def test_070_helper_convert_byte_to_string(self): """ convert byte2string for a string value """ self.assertNotEqual('foo', self.convert_byte_to_string(b'foobar')) - def test_067_helper_b64_url_encode(self): + def test_071_helper_b64_url_encode(self): """ test b64_url_encode of string """ self.assertEqual(b'c3RyaW5n', self.b64_url_encode(self.logger, 'string')) - def test_068_helper_b64_url_encode(self): + def test_072_helper_b64_url_encode(self): """ test b64_url_encode of byte """ self.assertEqual(b'Ynl0ZQ', self.b64_url_encode(self.logger, b'byte')) - def test_069_helper_csr_cn_get(self): + def test_073_helper_csr_cn_get(self): """ get cn of csr """ csr = 'MIIClzCCAX8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0lk4lyEIa0VL/u5ic01Zo/o+gyYqFpU7xe+nbFgiKA+R1rqrzP/sR6xjHqS0Rkv/BcBXf81sp/+iDmwIQLVlBTkKdimqVHCJMAbTL8ZNpcLDaRUce4liyX1cmczPTSqI/kcyEr8tKpYN+KzvKZZsNx2Pbgu7y7/70P2uSywiW+sqYZ+X28KGFxq6wwENzJtweDVsbWql9LLtw6daF41UQg10auNlRL1nhW0SlWZh1zPPW/0sa6C3xX28jjVh843b4ekkRNLXSEYQMTi0qYR2LomQ5aTlQ/hellf17UknfN2aA2RH5D7Ek+mndj/rH21bxQg26KRmHlaJld9K1IfvJAgMBAAGgOTA3BgkqhkiG9w0BCQ4xKjAoMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEAl3egrkO3I94IpxxfSJmVetd7s9uW3lSBqh9OiypFevQO7ZgUxau+k05NKTUNpSq3W9H/lRr5AG5x3/VX8XZVbcLKXQ0d6e38uXBAUFQQJmjBVYqd8KcMfqLeFFUBsLcG04yek2tNIbhXZfBtw9UYO27Y5ktMgWjAz2VskIXl3E2L0b8tGnSKDoMB07IVpYB9bHfHX4o+ccIgq1HxyYT1d+eVIQuSHHxR7j7Wkgb8RG9bCWpVWaYWKWU0Inh3gMnP06kPBJ9nOB4adgC3Hz37ab/0KpmBuQBEgmMfINwV/OpJVv2Su1FYK+uX7E1qUGae6QDsfg0Yor9uP0Vkv4b1NA==' self.assertEqual('foo1.bar.local', self.csr_cn_get(self.logger, csr)) - def test_070_helper_csr_cn_get(self): + def test_074_helper_csr_cn_get(self): """ get cn of csr """ csr = b'MIIClzCCAX8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0lk4lyEIa0VL/u5ic01Zo/o+gyYqFpU7xe+nbFgiKA+R1rqrzP/sR6xjHqS0Rkv/BcBXf81sp/+iDmwIQLVlBTkKdimqVHCJMAbTL8ZNpcLDaRUce4liyX1cmczPTSqI/kcyEr8tKpYN+KzvKZZsNx2Pbgu7y7/70P2uSywiW+sqYZ+X28KGFxq6wwENzJtweDVsbWql9LLtw6daF41UQg10auNlRL1nhW0SlWZh1zPPW/0sa6C3xX28jjVh843b4ekkRNLXSEYQMTi0qYR2LomQ5aTlQ/hellf17UknfN2aA2RH5D7Ek+mndj/rH21bxQg26KRmHlaJld9K1IfvJAgMBAAGgOTA3BgkqhkiG9w0BCQ4xKjAoMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEAl3egrkO3I94IpxxfSJmVetd7s9uW3lSBqh9OiypFevQO7ZgUxau+k05NKTUNpSq3W9H/lRr5AG5x3/VX8XZVbcLKXQ0d6e38uXBAUFQQJmjBVYqd8KcMfqLeFFUBsLcG04yek2tNIbhXZfBtw9UYO27Y5ktMgWjAz2VskIXl3E2L0b8tGnSKDoMB07IVpYB9bHfHX4o+ccIgq1HxyYT1d+eVIQuSHHxR7j7Wkgb8RG9bCWpVWaYWKWU0Inh3gMnP06kPBJ9nOB4adgC3Hz37ab/0KpmBuQBEgmMfINwV/OpJVv2Su1FYK+uX7E1qUGae6QDsfg0Yor9uP0Vkv4b1NA==' self.assertEqual('foo1.bar.local', self.csr_cn_get(self.logger, csr)) - def test_071_helper_convert_string_to_byte(self): + @patch('OpenSSL.crypto.load_certificate_request') + def test_075_helper_csr_cn_get(self, mock_csrload): + """ get cn of csr """ + csr = 'csr' + obj1 = Mock() + obj1.get_components = Mock(return_value={'CN': 'foo'}) + obj2 = Mock() + obj2.get_subject = Mock(return_value=obj1) + mock_csrload.return_value = obj2 + self.assertEqual('foo', self.csr_cn_get(self.logger, csr)) + + @patch('OpenSSL.crypto.load_certificate_request') + def test_076_helper_csr_cn_get(self, mock_csrload): + """ get cn of csr """ + csr = 'csr' + obj1 = Mock() + obj1.get_components = Mock(return_value={b'CN': 'foo'}) + obj2 = Mock() + obj2.get_subject = Mock(return_value=obj1) + mock_csrload.return_value = obj2 + self.assertEqual('foo', self.csr_cn_get(self.logger, csr)) + + def test_077_helper_convert_string_to_byte(self): """ convert string value to byte """ value = 'foo.bar' self.assertEqual(b'foo.bar', self.convert_string_to_byte(value)) - def test_072_helper_convert_string_to_byte(self): + def test_078_helper_convert_string_to_byte(self): """ convert string value to byte """ value = b'foo.bar' self.assertEqual(b'foo.bar', self.convert_string_to_byte(value)) - def test_073_helper_convert_string_to_byte(self): + def test_079_helper_convert_string_to_byte(self): """ convert string value to byte """ value = b'' self.assertEqual(b'', self.convert_string_to_byte(value)) - def test_074_helper_convert_string_to_byte(self): + def test_080_helper_convert_string_to_byte(self): """ convert string value to byte """ value = '' self.assertEqual(b'', self.convert_string_to_byte(value)) - def test_075_helper_convert_string_to_byte(self): + def test_081_helper_convert_string_to_byte(self): """ convert string value to byte """ value = None self.assertFalse(self.convert_string_to_byte(value)) - def test_076_helper_get_url(self): + def test_082_helper_get_url(self): """ get_url https """ data_dic = {'HTTP_HOST': 'http_host', 'SERVER_PORT': 443, 'PATH_INFO': 'path_info'} self.assertEqual('https://http_host', self.get_url(data_dic, False)) - def test_077_helper_get_url(self): + def test_083_helper_get_url(self): """ get_url http """ data_dic = {'HTTP_HOST': 'http_host', 'SERVER_PORT': 80, 'PATH_INFO': 'path_info'} self.assertEqual('http://http_host', self.get_url(data_dic, False)) - def test_078_helper_get_url(self): + def test_084_helper_get_url(self): """ get_url http wsgi.scheme """ data_dic = {'HTTP_HOST': 'http_host', 'SERVER_PORT': 80, 'PATH_INFO': 'path_info', 'wsgi.url_scheme': 'wsgi.url_scheme'} self.assertEqual('wsgi.url_scheme://http_host', self.get_url(data_dic, False)) - def test_079_helper_get_url(self): + def test_085_helper_get_url(self): """ get_url https include_path true bot no pathinfo""" data_dic = {'HTTP_HOST': 'http_host', 'SERVER_PORT': 443} self.assertEqual('https://http_host', self.get_url(data_dic, True)) - def test_080_helper_get_url(self): + def test_086_helper_get_url(self): """ get_url https and path info""" data_dic = {'HTTP_HOST': 'http_host', 'SERVER_PORT': 443, 'PATH_INFO': 'path_info'} self.assertEqual('https://http_hostpath_info', self.get_url(data_dic, True)) - def test_081_helper_get_url(self): + def test_087_helper_get_url(self): """ get_url wsgi.url and pathinfo """ data_dic = {'HTTP_HOST': 'http_host', 'SERVER_PORT': 80, 'PATH_INFO': 'path_info', 'wsgi.url_scheme': 'wsgi.url_scheme'} self.assertEqual('wsgi.url_scheme://http_hostpath_info', self.get_url(data_dic, True)) - def test_082_helper_get_url(self): + def test_088_helper_get_url(self): """ get_url http and pathinfo""" data_dic = {'HTTP_HOST': 'http_host', 'SERVER_PORT': 80, 'PATH_INFO': 'path_info'} self.assertEqual('http://http_hostpath_info', self.get_url(data_dic, True)) - def test_083_helper_get_url(self): + def test_089_helper_get_url(self): """ get_url without hostinfo """ data_dic = {'SERVER_PORT': 80, 'PATH_INFO': 'path_info'} self.assertEqual('http://localhost', self.get_url(data_dic, False)) - def test_084_helper_get_url(self): + def test_090_helper_get_url(self): """ get_url without SERVER_PORT """ data_dic = {'HTTP_HOST': 'http_host'} self.assertEqual('http://http_host', self.get_url(data_dic, True)) @patch('acme.helper.requests.get') - def test_085_helper_url_get(self, mock_request): + def test_091_helper_url_get(self, mock_request): """ successful url get without dns servers """ mock_request.return_value.text = 'foo' self.assertEqual('foo', self.url_get(self.logger, 'url')) @patch('acme.helper.requests.get') - def test_086_helper_url_get(self, mock_request): + def test_092_helper_url_get(self, mock_request): """ unsuccessful url get without dns servers """ # this is stupid but triggrs an expeption mock_request.return_value = {'foo': 'foo'} self.assertEqual(None, self.url_get(self.logger, 'url')) @patch('acme.helper.url_get_with_own_dns') - def test_087_helper_url_get(self, mock_request): + def test_093_helper_url_get(self, mock_request): """ successful url get with dns servers """ mock_request.return_value = 'foo' self.assertEqual('foo', self.url_get(self.logger, 'url', 'dns')) @patch('acme.helper.requests.get', side_effect=Mock(side_effect=Exception('foo'))) - def test_088_helper_url_get(self, mock_request): + def test_094_helper_url_get(self, mock_request): """ unsuccessful url_get """ # mock_request.return_value.text = 'foo' with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -666,7 +736,7 @@ def test_088_helper_url_get(self, mock_request): self.assertIn('ERROR:test_a2c:url_get error: foo', lcm.output) @patch('acme.helper.requests.get') - def test_089_helper_url_get(self, mock_request): + def test_095_helper_url_get(self, mock_request): """ unsuccessful url_get fallback to v4""" object = Mock() object.text = 'foo' @@ -674,207 +744,219 @@ def test_089_helper_url_get(self, mock_request): self.assertEqual('foo', self.url_get(self.logger, 'url')) @patch('acme.helper.requests.get') - def test_090_helper_url_get_with_own_dns(self, mock_request): + def test_096_helper_url_get_with_own_dns(self, mock_request): """ successful url_get_with_own_dns get with dns servers """ mock_request.return_value.text = 'foo' self.assertEqual('foo', self.url_get_with_own_dns(self.logger, 'url')) @patch('acme.helper.requests.get') - def test_091_helper_url_get_with_own_dns(self, mock_request): + def test_097_helper_url_get_with_own_dns(self, mock_request): """ successful url_get_with_own_dns get with dns servers """ mock_request.return_value = {'foo': 'foo'} self.assertEqual(None, self.url_get_with_own_dns(self.logger, 'url')) @patch('acme.helper.load_config') - def test_092_helper_dns_server_list_load(self, mock_load_config): + def test_098_helper_dns_server_list_load(self, mock_load_config): """ successful dns_server_list_load with empty config file """ mock_load_config.return_value = {} self.assertEqual(['9.9.9.9', '8.8.8.8'], self.dns_server_list_load()) @patch('acme.helper.load_config') - def test_093_helper_dns_server_list_load(self, mock_load_config): + def test_099_helper_dns_server_list_load(self, mock_load_config): """ successful dns_server_list_load with empty Challenge section """ mock_load_config.return_value = {'Challenge': {}} self.assertEqual(['9.9.9.9', '8.8.8.8'], self.dns_server_list_load()) @patch('acme.helper.load_config') - def test_094_helper_dns_server_list_load(self, mock_load_config): + def test_100_helper_dns_server_list_load(self, mock_load_config): """ successful dns_server_list_load with wrong Challenge section """ mock_load_config.return_value = {'Challenge': {'foo': 'bar'}} self.assertEqual(['9.9.9.9', '8.8.8.8'], self.dns_server_list_load()) @patch('acme.helper.load_config') - def test_095_helper_dns_server_list_load(self, mock_load_config): + def test_101_helper_dns_server_list_load(self, mock_load_config): """ successful dns_server_list_load with wrong json format """ mock_load_config.return_value = {'Challenge': {'dns_server_list': 'bar'}} self.assertEqual(['9.9.9.9', '8.8.8.8'], self.dns_server_list_load()) @patch('acme.helper.load_config') - def test_096_helper_dns_server_list_load(self, mock_load_config): + def test_102_helper_dns_server_list_load(self, mock_load_config): """ successful dns_server_list_load with wrong json format """ mock_load_config.return_value = {'Challenge': {'dns_server_list': '["foo", "bar"]'}} self.assertEqual(['foo', 'bar'], self.dns_server_list_load()) - def test_097_helper_csr_san_get(self): + def test_103_helper_csr_san_get(self): """ get sans but no csr """ csr = None self.assertEqual([], self.csr_san_get(self.logger, csr)) - def test_098_helper_csr_san_get(self): + def test_104_helper_csr_san_get(self): """ get sans but one san with == """ csr = 'MIIClzCCAX8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMwfxxbCCTsZY8mTFZkoQ5cAJyQZLUiz34sDDRvEpI9ZzdNNm2AEZR7AgKNuBkLwzUzY5iQ182huNzYJYZZEvYX++ocF2ngapTMQgfB+bWS5bpWIdjnAcz1/86jmJgTciwL25dSnEWL17Yn3pAWweoewr730rq/PMyIbviQrasksnSo7abe2mctxkHjHb5sZ+Z1yRTN6ir/bObXmxr+vHeeD2vLRv4Hd5XaA1d+k31J2FVMnrn5OpWbxGHo49zd0xdy2mgTdZ9UraLaQnyGlkjYzV0rqHIAIm8HOUjGN5U75/rlOPF0x62FCICZU/z1AgRvugaA5eO8zTSQJiMiBe3AgMBAAGgOTA3BgkqhkiG9w0BCQ4xKjAoMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEANAXOIkv0CovmdzyoAv1dsiK0TK2XHBdBTEPFDsrT7MnrIXOFS4FnDrg8zpn7QBzBRTl3HaKN8fnpIHkA/6ZRDqaEJq0AeskjxIg9LKDBBx5TEdgPh1CwruRWLlXtrqU7XXQmk0wLIo/kfaDRcTjyJ3yHTEK06mCAaws0sTKlTw2D4pIiDRp8zbLHeSEUX5UKOSGbLSSUY/F2XwgPB8nC2BCD/gkvHRR+dMQSdOCiS9GLwZdYAAyESw6WhmGPjmVbeTRgSt/9//yx3JKQgkFYmpSMLKR2G525M+l1qfku/4b0iMOa4vQjFRj5AXZH0SBpAKtvnFxUpP6P9mTE7+akOQ==' self.assertEqual(['DNS:foo1.bar.local'], self.csr_san_get(self.logger, csr)) - def test_099_helper_csr_san_get(self): + def test_105_helper_csr_san_get(self): """ get sans but one san without == """ csr = 'MIIClzCCAX8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMwfxxbCCTsZY8mTFZkoQ5cAJyQZLUiz34sDDRvEpI9ZzdNNm2AEZR7AgKNuBkLwzUzY5iQ182huNzYJYZZEvYX++ocF2ngapTMQgfB+bWS5bpWIdjnAcz1/86jmJgTciwL25dSnEWL17Yn3pAWweoewr730rq/PMyIbviQrasksnSo7abe2mctxkHjHb5sZ+Z1yRTN6ir/bObXmxr+vHeeD2vLRv4Hd5XaA1d+k31J2FVMnrn5OpWbxGHo49zd0xdy2mgTdZ9UraLaQnyGlkjYzV0rqHIAIm8HOUjGN5U75/rlOPF0x62FCICZU/z1AgRvugaA5eO8zTSQJiMiBe3AgMBAAGgOTA3BgkqhkiG9w0BCQ4xKjAoMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEANAXOIkv0CovmdzyoAv1dsiK0TK2XHBdBTEPFDsrT7MnrIXOFS4FnDrg8zpn7QBzBRTl3HaKN8fnpIHkA/6ZRDqaEJq0AeskjxIg9LKDBBx5TEdgPh1CwruRWLlXtrqU7XXQmk0wLIo/kfaDRcTjyJ3yHTEK06mCAaws0sTKlTw2D4pIiDRp8zbLHeSEUX5UKOSGbLSSUY/F2XwgPB8nC2BCD/gkvHRR+dMQSdOCiS9GLwZdYAAyESw6WhmGPjmVbeTRgSt/9//yx3JKQgkFYmpSMLKR2G525M+l1qfku/4b0iMOa4vQjFRj5AXZH0SBpAKtvnFxUpP6P9mTE7+akOQ' self.assertEqual(['DNS:foo1.bar.local'], self.csr_san_get(self.logger, csr)) - def test_100_helper_csr_san_get(self): + def test_106_helper_csr_san_get(self): """ get sans but two sans """ csr = 'MIICpzCCAY8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMwfxxbCCTsZY8mTFZkoQ5cAJyQZLUiz34sDDRvEpI9ZzdNNm2AEZR7AgKNuBkLwzUzY5iQ182huNzYJYZZEvYX++ocF2ngapTMQgfB+bWS5bpWIdjnAcz1/86jmJgTciwL25dSnEWL17Yn3pAWweoewr730rq/PMyIbviQrasksnSo7abe2mctxkHjHb5sZ+Z1yRTN6ir/bObXmxr+vHeeD2vLRv4Hd5XaA1d+k31J2FVMnrn5OpWbxGHo49zd0xdy2mgTdZ9UraLaQnyGlkjYzV0rqHIAIm8HOUjGN5U75/rlOPF0x62FCICZU/z1AgRvugaA5eO8zTSQJiMiBe3AgMBAAGgSTBHBgkqhkiG9w0BCQ4xOjA4MAsGA1UdDwQEAwIF4DApBgNVHREEIjAggg5mb28xLmJhci5sb2NhbIIOZm9vMi5iYXIubG9jYWwwDQYJKoZIhvcNAQELBQADggEBADeuf4J8Xziw2OuvLNnLOSgHQl2HdMFtRdgJoun7zPobsP3L3qyXLvvhJcQsIJggu5ZepnHGrCxroSbtRSO65GtLQA0Rq3DCGcPIC1fe9AYrqoynx8bWt2Hd+PyDrBppHVoQzj6yNCt6XNSDs04BMtjs9Pu4DD6DDHmxFMVNdHXea2Rms7C5nLQvXgw7yOF3Zk1vEu7Kue7d3zZMhN+HwwrNEA7RGAEzHHlCv5LL4Mw+kf6OJ8nf/WDiLDKEQIh6bnOuB42Y2wUMpzui8Uur0VJO+twY46MvjiVMMBZE3aPJU33eNPAQVC7GinStn+zQIJA5AADdcO8Lk1qdtaDiGp8' self.assertEqual(['DNS:foo1.bar.local', 'DNS:foo2.bar.local'], self.csr_san_get(self.logger, csr)) - def test_101_helper_csr_san_get(self): + def test_107_helper_csr_san_get(self): """ get sans but three sans """ csr = 'MIICtzCCAZ8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMwfxxbCCTsZY8mTFZkoQ5cAJyQZLUiz34sDDRvEpI9ZzdNNm2AEZR7AgKNuBkLwzUzY5iQ182huNzYJYZZEvYX++ocF2ngapTMQgfB+bWS5bpWIdjnAcz1/86jmJgTciwL25dSnEWL17Yn3pAWweoewr730rq/PMyIbviQrasksnSo7abe2mctxkHjHb5sZ+Z1yRTN6ir/bObXmxr+vHeeD2vLRv4Hd5XaA1d+k31J2FVMnrn5OpWbxGHo49zd0xdy2mgTdZ9UraLaQnyGlkjYzV0rqHIAIm8HOUjGN5U75/rlOPF0x62FCICZU/z1AgRvugaA5eO8zTSQJiMiBe3AgMBAAGgWTBXBgkqhkiG9w0BCQ4xSjBIMAsGA1UdDwQEAwIF4DA5BgNVHREEMjAwgg5mb28xLmJhci5sb2NhbIIOZm9vMi5iYXIubG9jYWyCDmZvbzMuYmFyLmxvY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQAQRkub6G4uijaXOYpCkoz40I+SVRsbRDgnMNjsooZz1+7DVglFjrr6Pb0PPTOvOxtmbHP2KK0WokDn4LqOD2t0heuI+KPQy7m/ROpOB/YZOzTWEB8yS4vjkf/RFiJ7fnCAc8vA+3K/mBVb+89F8w/KlyPmpg1GK7UNgjEa5bnznTox8q12CocCJVykPEiC8AT/VPWUOPfg6gs+V6LO8R73VRPMVy0ttYKGX80ob+KczDTMUhoxXg8OG+G+bXXU+4Tu4l+nQWf2lFejECi/vNKzUT90IbcGJwyk7rc4Q7BJ/t/5nMo+vuV9f+2HI7qakHcw6u9RGylL4OYDf1CrqF1R' self.assertEqual(['DNS:foo1.bar.local', 'DNS:foo2.bar.local', 'DNS:foo3.bar.local'], self.csr_san_get(self.logger, csr)) - def test_102_helper_csr_extensions_get(self): + def test_108_helper_csr_extensions_get(self): """ get sns in hex """ csr = 'MIIClzCCAX8CAQAwGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMwfxxbCCTsZY8mTFZkoQ5cAJyQZLUiz34sDDRvEpI9ZzdNNm2AEZR7AgKNuBkLwzUzY5iQ182huNzYJYZZEvYX++ocF2ngapTMQgfB+bWS5bpWIdjnAcz1/86jmJgTciwL25dSnEWL17Yn3pAWweoewr730rq/PMyIbviQrasksnSo7abe2mctxkHjHb5sZ+Z1yRTN6ir/bObXmxr+vHeeD2vLRv4Hd5XaA1d+k31J2FVMnrn5OpWbxGHo49zd0xdy2mgTdZ9UraLaQnyGlkjYzV0rqHIAIm8HOUjGN5U75/rlOPF0x62FCICZU/z1AgRvugaA5eO8zTSQJiMiBe3AgMBAAGgOTA3BgkqhkiG9w0BCQ4xKjAoMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDANBgkqhkiG9w0BAQsFAAOCAQEANAXOIkv0CovmdzyoAv1dsiK0TK2XHBdBTEPFDsrT7MnrIXOFS4FnDrg8zpn7QBzBRTl3HaKN8fnpIHkA/6ZRDqaEJq0AeskjxIg9LKDBBx5TEdgPh1CwruRWLlXtrqU7XXQmk0wLIo/kfaDRcTjyJ3yHTEK06mCAaws0sTKlTw2D4pIiDRp8zbLHeSEUX5UKOSGbLSSUY/F2XwgPB8nC2BCD/gkvHRR+dMQSdOCiS9GLwZdYAAyESw6WhmGPjmVbeTRgSt/9//yx3JKQgkFYmpSMLKR2G525M+l1qfku/4b0iMOa4vQjFRj5AXZH0SBpAKtvnFxUpP6P9mTE7+akOQ' self.assertEqual(['AwIF4A==', 'MBCCDmZvbzEuYmFyLmxvY2Fs'], self.csr_extensions_get(self.logger, csr)) - def test_103_helper_csr_extensions_get(self): + def test_109_helper_csr_extensions_get(self): """ get tnauth identifier """ csr = 'MIICuzCCAaMCAQAwHjEcMBoGA1UEAwwTY2VydC5zdGlyLmJhci5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALsLm4zgkl2lEx2EHy1ENfh3cYB79Xb5sD3ehkY+1pXphIWoM9KYVqHKOurModjsh75YjRBSilRfTFSk6kCUahTJyeCbM6Vzl75CcZy7poUxiK+u80JMU/xymUsrqY4GZlh2/XtFMxXHUSf3bhKZAIjBNugsvR/sHtEvJ6RJiuYqHMWUzZ/Vby5L0ywNl+LPSY7AVTUAZ0lKrnUCP4dHnbjwjf+nPi7vT6G0yrEg0qPOYXtJOXdf7vvjLi8J+ap758NtG2qapLdbToIPr0uOEvMO6zs8z1bIyjOHU3kzlpKHzDsPYy8txxKC/3Rae7sKB9gWm8WUxFBmuA7gaFDGQAECAwEAAaBYMFYGCSqGSIb3DQEJDjFJMEcwCwYDVR0PBAQDAgXgMB4GA1UdEQQXMBWCE2NlcnQuc3Rpci5iYXIubG9jYWwwGAYIKwYBBQUHARoEDDAKoAgWBjEyMzQ1NjANBgkqhkiG9w0BAQsFAAOCAQEAjyhJfgb/zJBMYp6ylRtEXgtBpsX9ePUL/iLgIDMcGtwaFm3pkQOSBr4xiTxftnqN77SlC8UEu7PDR73JX6iqLNJWucPlhAXVrr367ygO8GGLrtGddClZmo0lhRBRErgpagWB/jFkbL8afPGJwgQQXF0KWFMcajAPiIl1l6M0w11KqJ23Pwrmi7VJHzIgh4ys0D2UrX7KuV4PIOOmG0s7jTfBSB+yUH2zwVzOAzbr3wrD1WubD7hRaHDUi4bn4DRbquQOzbqfTI6QhetUcNpq4DwhBRcnZwUMJUIcxLAsFnDgGSW+dmJe6JH8MsS+8ZmOLllyQxWzYEVquQQvxFVTZA' self.assertEqual(['AwIF4A==', 'MBWCE2NlcnQuc3Rpci5iYXIubG9jYWw=', 'MAqgCBYGMTIzNDU2'], self.csr_extensions_get(self.logger, csr)) - def test_104_helper_validate_email(self): + def test_110_helper_validate_email(self): """ validate email containing "-" in domain """ self.assertTrue(self.validate_email(self.logger, 'foo@example-example.com')) - def test_105_helper_validate_email(self): + def test_111_helper_validate_email(self): """ validate email containing "-" in user""" self.assertTrue(self.validate_email(self.logger, 'foo-foo@example.com')) - def test_106_helper_get_url(self): + def test_112_helper_get_url(self): """ get_url with xforwarded https """ data_dic = {'HTTP_X_FORWARDED_PROTO': 'https', 'HTTP_HOST': 'http_host', 'SERVER_PORT': 443, 'PATH_INFO': 'path_info'} self.assertEqual('https://http_host', self.get_url(data_dic, False)) - def test_107_helper_get_url(self): + def test_113_helper_get_url(self): """ get_url with xforwarded http """ data_dic = {'HTTP_X_FORWARDED_PROTO': 'http', 'HTTP_HOST': 'http_host', 'SERVER_PORT': 443, 'PATH_INFO': 'path_info'} self.assertEqual('http://http_host', self.get_url(data_dic, False)) - def test_108_helper_validate_email(self): + def test_114_helper_validate_email(self): """ validate email containing first letter of domain cannot be a number""" self.assertFalse(self.validate_email(self.logger, 'foo@1example.com')) - def test_109_helper_validate_email(self): + def test_115_helper_validate_email(self): """ validate email containing last letter of domain cannot - """ self.assertFalse(self.validate_email(self.logger, 'foo@example-.com')) - def test_110_helper_cert_dates_get(self): + def test_116_helper_cert_dates_get(self): """ get issuing and expiration date from rsa certificate """ cert = 'MIIElTCCAn2gAwIBAgIRAKD_ulfqPUn-ggOUHOxjp40wDQYJKoZIhvcNAQELBQAwSDELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEXMBUGA1UECgwOQWNtZTJDZXJ0aWZpZXIxDzANBgNVBAMMBnN1Yi1jYTAeFw0yMDA1MjcxMjMwMjNaFw0yMDA2MjYxMjMwMjNaMBkxFzAVBgNVBAMMDmZvbzEuYmFyLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwbx-z-9wsEewBf1hnk3yAy5TFg-lWVdwk2QRdAMDTExVP823QF_K-t6cxJV_-QuWVbHN-lx6nQCXIqCZSN97hN0YTkrw8jnA4FpZzyvYI9rKEO3p4sxqndbu4X-gtyMBbXOLhjTlN2f7Z081XWIgkikvuZU2XzMZ-BbRFDfsPdDRwbwvgJU6NxpdIKm2DmYIP1MFo-tLu0toAc0nm9v8Otme28_kpJxmW3iOMkqN9BE-qAkggFDeNoxPtXRyP2PrRgbaj94e1uznsyni7CYw_a9O1NPrjKFQmPaCk8k9ICvPoLHXtLabekCmvdxyRlDwD_Xoaygpd9-UHCREhcOu_wIDAQABo4GoMIGlMAsGA1UdDwQEAwIF4DAZBgNVHREEEjAQgg5mb28xLmJhci5sb2NhbDAdBgNVHQ4EFgQUqy5KOBlkyX29l4EHTCSzhZuDg-EwDgYDVR0PAQH_BAQDAgWgMB8GA1UdIwQYMBaAFBs0P896R0FUZHfnxMJL52ftKQOkMAwGA1UdEwEB_wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQB7pQpILzxqcU2RKlr17rcne6NSJTUJnNXALeUFy5PrnjjJY1_B1cKaWluk3p7AMFvUjBpcucGCfEDudW290AQxYjrvl8_ePkzRzEkAo76L7ZqED5upYBZVn_3lA5Alr8L67UC0bDMhKTsy8WJzhWHQlMb37_YFUvtNPoI_MI09Q842VXeNQz5UDZmW9qhyeDIkf6fwOAO66VnGTLuUm2LGQZ-St2GauxR0ZUcRtMJoc-c7WOdHs8DlUCoFtglrzVH98501Sx749CG4nkJr4QNDpkw2hAhlo4Cxzp6PlljPNSgM9MsqqVdrgqDteDM_n-yrVFGezCik4QexDkWARPutRLQtpbhudExVnoFM68ihZ0y3oeDjgUBLybBQpcBAsBqiJ66Q8HTZRSqO9zlKW5Vm1KwAVDh_qgELxvqd0wIVkyxBKPta2l1fvb5YBiVqo4JyNcCTnoBS1emO4vk8XjroKijwLnU0cEXwHrY4JF1uU_kOtoZMGPul5EuBMcODLs7JJ3_IqJd8quI7Vf5zSsaB6nSzQ8XmiQiVogKflBeLl7AWmYCiL-FLP_q4dSJmvdr6fPMNy4-cfDO4Awc8RNfv-VjF5Mq57X1IXJrWKkat4lCEoPMq5WRJV8uVm6XNdwvUJxgCYR9mfol7T6imODDd7BNV4dKYvyteoS0auC0iww' self.assertEqual((1590582623, 1593174623), self.cert_dates_get(self.logger, cert)) - def test_111_helper_cert_dates_get(self): + def test_117_helper_cert_dates_get(self): """ get issuing and expiration date no certificate """ cert = None self.assertEqual((0, 0), self.cert_dates_get(self.logger, cert)) - def test_112_helper_cert_dates_get(self): + def test_118_helper_cert_dates_get(self): """ get issuing and expiration date damaged certificate """ cert = 'foo' self.assertEqual((0, 0), self.cert_dates_get(self.logger, cert)) - def test_113_helper_cert_dates_get(self): + def test_119_helper_cert_dates_get(self): """ get issuing and expiration date ecc certificate """ cert = 'MIIDozCCAYugAwIBAgIIMMxkE7mRR+YwDQYJKoZIhvcNAQELBQAwKjEXMBUGA1UECxMOYWNtZTJjZXJ0aWZpZXIxDzANBgNVBAMTBnN1Yi1jYTAeFw0yMDA3MTEwNDUzMTFaFw0yMTA3MTEwNDUzMTFaMBkxFzAVBgNVBAMMDmZvbzEuYmFyLmxvY2FsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAER/KMoV5+zQgegqYue2ztPK2nZVpK2vxb02UzwyHw4ebhJ2gBobI23lSBRa1so1ug0kej7U+ohm5aGFdNxLM0G6OBqDCBpTALBgNVHQ8EBAMCBeAwGQYDVR0RBBIwEIIOZm9vMS5iYXIubG9jYWwwHQYDVR0OBBYEFCSaU743wU8jMETIO381r13tVLdMMA4GA1UdDwEB/wQEAwIFoDAfBgNVHSMEGDAWgBS/3o6OBiIiq61DyN3UT6irSEE+1TAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAgEAmmhHuBhXNM2Azv53rCKY72yTQIoDVHjYrAvTmS6NsJzYflEOMkI7FCes64dWp54BerSD736Yax67b4XmLXc/+T41d7QAcnhY5xvLJiMpSsW37icHcLZpjlOrYDoRmny2U7n6t1aQ03nwgV+BgdaUQYLkUZuczs4kdqH1c9Ot9CCRTHpqSWlmWzGeRgt2uT4gKhFESP9lzx37YwKBHulBGthv1kcAaz8w8iPXBg01OEDiraXCBZFoYDEpDi2w2Y6ChCr7sNsY7aJ3a+2iHGYlktXEntk78S+g00HW61G9oLoRgeqEH3L6qVIpnswPAU/joub0YhNBIUFenCj8c3HMBgMcczzdZL+qStdymhpVkZetzXtMTKtgmxhkRzAOQUBBcHFc+wM97FqC0S4HJAuoHQ4EJ46MxwZH0jBVqcqCPMSaJ88uV902+VGGXrnxMR8RbGWLoCmsYb1ISmBUt+31PjMCYbXKwLmzvbRpO7XAQimvtOqoufl5yeRUJRLcUS6Let0QzU196/nZ789d7Etep7RjDYQm7/QhiWH197yKZ5/mUxqfyHDQ3hk5iX7S/gbo1jQXElEv5tB8Ozs+zVQmB2bXpN8c+8XUaZnwvYC2y+0LAQN4z7xilReCaasxQSsEOLCrlsannkGV704HYnnaKBS2tI948QotHnADHdfHl3o' self.assertEqual((1594443191, 1625979191), self.cert_dates_get(self.logger, cert)) - def test_114_helper_ca_handler_get(self): + def test_120_helper_ca_handler_get(self): """ identifier check none input""" file_name = 'foo' self.assertEqual('foo', self.ca_handler_get(self.logger, file_name)) - def test_115_helper_ca_handler_get(self): + def test_121_helper_ca_handler_get(self): """ identifier check none input""" file_name = 'foo.py' self.assertEqual('foo', self.ca_handler_get(self.logger, file_name)) - def test_116_helper_ca_handler_get(self): + def test_122_helper_ca_handler_get(self): """ identifier check none input""" file_name = 'foo/foo.py' self.assertEqual('foo.foo', self.ca_handler_get(self.logger, file_name)) - def test_117_helper_ca_handler_get(self): + def test_123_helper_ca_handler_get(self): """ identifier check none input""" file_name = 'foo\\foo.py' self.assertEqual('foo.foo', self.ca_handler_get(self.logger, file_name)) @patch('dns.resolver.Resolver') - def test_118_helper_fqdn_resolve(self, mock_resolve): + def test_124_helper_fqdn_resolve(self, mock_resolve): + """ successful dns-query returning covering github """ + mock_resolve.return_value.query.return_value = ['foo'] + self.assertEqual((None, False), self.fqdn_resolve('foo', '10.0.0.1')) + + @patch('dns.resolver.Resolver') + def test_125_helper_fqdn_resolve(self, mock_resolve): + """ successful dns-query returning covering github """ + mock_resolve.return_value.query.return_value = ['foo'] + self.assertEqual((None, False), self.fqdn_resolve('foo')) + + @patch('dns.resolver.Resolver') + def test_126_helper_fqdn_resolve(self, mock_resolve): """ successful dns-query returning one value """ mock_resolve.return_value.query.return_value = ['foo'] self.assertEqual(('foo', False), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver') - def test_119_helper_fqdn_resolve(self, mock_resolve): + def test_127_helper_fqdn_resolve(self, mock_resolve): """ successful dns-query returning two values """ mock_resolve.return_value.query.return_value = ['bar', 'foo'] self.assertEqual(('bar', False), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=Mock(side_effect=dns.resolver.NXDOMAIN)) - def test_120_helper_fqdn_resolve(self, mock_resolve): + def test_128_helper_fqdn_resolve(self, mock_resolve): """ catch NXDOMAIN """ self.assertEqual((None, True), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=Mock(side_effect=dns.resolver.NoAnswer)) - def test_121_helper_fqdn_resolve(self, mock_resolve): + def test_129_helper_fqdn_resolve(self, mock_resolve): """ catch NoAnswer """ self.assertEqual((None, True), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=Mock(side_effect=dns.resolver.NoNameservers)) - def test_122_helper_fqdn_resolve(self, mock_resolve): + def test_130_helper_fqdn_resolve(self, mock_resolve): """ catch other dns related execption """ self.assertEqual((None, False), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=Mock(side_effect=Exception('foo'))) - def test_123_helper_fqdn_resolve(self, mock_resolve): + def test_131_helper_fqdn_resolve(self, mock_resolve): """ catch other execption """ self.assertEqual((None, False), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=[Mock(side_effect=dns.resolver.NXDOMAIN), ['foo']]) - def test_124_helper_fqdn_resolve(self, mock_resolve): + def test_132_helper_fqdn_resolve(self, mock_resolve): """ catch NXDOMAIN on v4 and fine in v6 """ self.assertEqual(('foo', False), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=[Mock(side_effect=dns.resolver.NoAnswer), ['foo']]) - def test_125_helper_fqdn_resolve(self, mock_resolve): + def test_133_helper_fqdn_resolve(self, mock_resolve): """ catch NoAnswer on v4 and fine in v6 """ self.assertEqual(('foo', False), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=[Mock(side_effect=dns.resolver.NoNameservers), ['foo']]) - def test_126_helper_fqdn_resolve(self, mock_resolve): + def test_134_helper_fqdn_resolve(self, mock_resolve): """ catch other dns related execption on v4 and fine in v6 """ self.assertEqual(('foo', False), self.fqdn_resolve('foo.bar.local')) @patch('dns.resolver.Resolver.query', side_effect=[Mock(side_effect=Exception('foo')), ['foo']]) - def test_127_helper_fqdn_resolve(self, mock_resolve): + def test_135_helper_fqdn_resolve(self, mock_resolve): """ catch other execption when resolving v4 but fine in v6""" self.assertEqual(('foo', False), self.fqdn_resolve('foo.bar.local')) - def test_128_helper_signature_check(self): + def test_136_helper_signature_check(self): """ sucessful validation symmetric key""" mkey = '{"k": "ZndUSkZvVldvMEFiRzQ5VWNCdERtNkNBNnBTcTl4czNKVEVxdUZiaEdpZXZNUVJBVmRuSFREcDJYX2s3X0NxTA", "kty": "oct"}' message = '{"payload": "eyJlIjogIkFRQUIiLCAia3R5IjogIlJTQSIsICJuIjogIm5kN3ZWUTNraW4zS3BKdTd6RUZNTlVPb0ZIQmVDUWRFRTUyOF9iOHo2djNDNnYtQS0zeUdBcTFWTjZmRTluUXdYSmNlZ2ZNdm1MczlCVVllVjZ2M1FzdGhkVFRCdW5FS1l0TVVZUVRmNkpwaHNEb1pHTkt1dnpCY2ZxSlN2TXpCNHdwa3hORm1Pa2M1QVhwRzhnQWJiTTRuS3JDQkdCQ21lZ2RJUEc3U0g3Mk9tejN6YjIwemZfZlo4dHVoUzk1eUJKdndKRjhZRGtCdDViWUV5ZnQ4aVoyWVFGVmRZZW5FMDhKOGRBUGNVQy1HYld6NmJXUm9Xc0xOT21VNkVjSndsSV9tRXRqazA5aTNlVEhOa2Vna3NrZUJOeXhlSkdtaVRtMHRtS1MwOEVvY0VQTDA1UktxSm9XNnhVcHNITDcwSzdzUVRaUDBHSUY1VXBwSkZXMnlVdyJ9", "protected": "eyJ1cmwiOiAiaHR0cDovL2FjbWUtc3J2LmJhci5sb2NhbC9hY21lL25ld2FjY291bnQiLCAiYWxnIjogIkhTMjU2IiwgImtpZCI6ICJiYXIifQ", "signature": "VXYLfPuoClsn_rhPPV8qjspZV1Q7HyX8rXv6odWYnLI"}' self.assertEqual((True, None), self.signature_check(self.logger, message, mkey, json_=True)) - def test_129_helper_signature_check(self): + def test_137_helper_signature_check(self): """ sucessful validation wrong symmetric key""" mkey = '{"k": "ZndUSkZvVldvMEFiRzQ5VWNCdERtNkNBNnBTcTl4czNKVEVxdUZiaEdpZXZNUVJBVmRuSFREcDJYX2s3X0NxvA", "kty": "oct"}' message = '{"payload": "eyJlIjogIkFRQUIiLCAia3R5IjogIlJTQSIsICJuIjogIm5kN3ZWUTNraW4zS3BKdTd6RUZNTlVPb0ZIQmVDUWRFRTUyOF9iOHo2djNDNnYtQS0zeUdBcTFWTjZmRTluUXdYSmNlZ2ZNdm1MczlCVVllVjZ2M1FzdGhkVFRCdW5FS1l0TVVZUVRmNkpwaHNEb1pHTkt1dnpCY2ZxSlN2TXpCNHdwa3hORm1Pa2M1QVhwRzhnQWJiTTRuS3JDQkdCQ21lZ2RJUEc3U0g3Mk9tejN6YjIwemZfZlo4dHVoUzk1eUJKdndKRjhZRGtCdDViWUV5ZnQ4aVoyWVFGVmRZZW5FMDhKOGRBUGNVQy1HYld6NmJXUm9Xc0xOT21VNkVjSndsSV9tRXRqazA5aTNlVEhOa2Vna3NrZUJOeXhlSkdtaVRtMHRtS1MwOEVvY0VQTDA1UktxSm9XNnhVcHNITDcwSzdzUVRaUDBHSUY1VXBwSkZXMnlVdyJ9", "protected": "eyJ1cmwiOiAiaHR0cDovL2FjbWUtc3J2LmJhci5sb2NhbC9hY21lL25ld2FjY291bnQiLCAiYWxnIjogIkhTMjU2IiwgImtpZCI6ICJiYXIifQ", "signature": "VXYLfPuoClsn_rhPPV8qjspZV1Q7HyX8rXv6odWYnLI"}' @@ -885,7 +967,7 @@ def test_129_helper_signature_check(self): error = "Verification failed for all signatures['Failed: [InvalidJWSSignature(\"Verification failed {InvalidSignature(\\\'Signature did not match digest.\\\')}\")]\']" self.assertEqual((False, error), self.signature_check(self.logger, message, mkey, json_=True)) - def test_130_helper_signature_check(self): + def test_138_helper_signature_check(self): """ sucessful validation wrong symmetric key without json_ flag set """ mkey = '{"k": "ZndUSkZvVldvMEFiRzQ5VWNCdERtNkNBNnBTcTl4czNKVEVxdUZiaEdpZXZNUVJBVmRuSFREcDJYX2s3X0NxvA", "kty": "oct"}' message = '{"payload": "eyJlIjogIkFRQUIiLCAia3R5IjogIlJTQSIsICJuIjogIm5kN3ZWUTNraW4zS3BKdTd6RUZNTlVPb0ZIQmVDUWRFRTUyOF9iOHo2djNDNnYtQS0zeUdBcTFWTjZmRTluUXdYSmNlZ2ZNdm1MczlCVVllVjZ2M1FzdGhkVFRCdW5FS1l0TVVZUVRmNkpwaHNEb1pHTkt1dnpCY2ZxSlN2TXpCNHdwa3hORm1Pa2M1QVhwRzhnQWJiTTRuS3JDQkdCQ21lZ2RJUEc3U0g3Mk9tejN6YjIwemZfZlo4dHVoUzk1eUJKdndKRjhZRGtCdDViWUV5ZnQ4aVoyWVFGVmRZZW5FMDhKOGRBUGNVQy1HYld6NmJXUm9Xc0xOT21VNkVjSndsSV9tRXRqazA5aTNlVEhOa2Vna3NrZUJOeXhlSkdtaVRtMHRtS1MwOEVvY0VQTDA1UktxSm9XNnhVcHNITDcwSzdzUVRaUDBHSUY1VXBwSkZXMnlVdyJ9", "protected": "eyJ1cmwiOiAiaHR0cDovL2FjbWUtc3J2LmJhci5sb2NhbC9hY21lL25ld2FjY291bnQiLCAiYWxnIjogIkhTMjU2IiwgImtpZCI6ICJiYXIifQ", "signature": "VXYLfPuoClsn_rhPPV8qjspZV1Q7HyX8rXv6odWYnLI"}' @@ -895,87 +977,283 @@ def test_130_helper_signature_check(self): error = 'jwcrypto.jwk.JWK() argument after ** must be a mapping, not str' self.assertEqual((False, error), self.signature_check(self.logger, message, mkey)) - def test_131_helper_signature_check(self): + def test_139_helper_signature_check(self): """ sucessful validation invalid key """ mkey = 'invalid key' message = '{"payload": "eyJlIjogIkFRQUIiLCAia3R5IjogIlJTQSIsICJuIjogIm5kN3ZWUTNraW4zS3BKdTd6RUZNTlVPb0ZIQmVDUWRFRTUyOF9iOHo2djNDNnYtQS0zeUdBcTFWTjZmRTluUXdYSmNlZ2ZNdm1MczlCVVllVjZ2M1FzdGhkVFRCdW5FS1l0TVVZUVRmNkpwaHNEb1pHTkt1dnpCY2ZxSlN2TXpCNHdwa3hORm1Pa2M1QVhwRzhnQWJiTTRuS3JDQkdCQ21lZ2RJUEc3U0g3Mk9tejN6YjIwemZfZlo4dHVoUzk1eUJKdndKRjhZRGtCdDViWUV5ZnQ4aVoyWVFGVmRZZW5FMDhKOGRBUGNVQy1HYld6NmJXUm9Xc0xOT21VNkVjSndsSV9tRXRqazA5aTNlVEhOa2Vna3NrZUJOeXhlSkdtaVRtMHRtS1MwOEVvY0VQTDA1UktxSm9XNnhVcHNITDcwSzdzUVRaUDBHSUY1VXBwSkZXMnlVdyJ9", "protected": "eyJ1cmwiOiAiaHR0cDovL2FjbWUtc3J2LmJhci5sb2NhbC9hY21lL25ld2FjY291bnQiLCAiYWxnIjogIkhTMjU2IiwgImtpZCI6ICJiYXIifQ", "signature": "VXYLfPuoClsn_rhPPV8qjspZV1Q7HyX8rXv6odWYnLI"}' self.assertEqual((False, 'Expecting value: line 1 column 1 (char 0)'), self.signature_check(self.logger, message, mkey, json_=True)) - def test_132_fqdn_in_san_check(self): + def test_140_fqdn_in_san_check(self): """ successful check one entry one match """ fqdn = 'foo.bar.local' san_list = ['DNS:foo.bar.local'] self.assertTrue(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_133_fqdn_in_san_check(self): + def test_141_fqdn_in_san_check(self): """ successful check two entries one match """ fqdn = 'foo.bar.local' san_list = ['DNS:foo1.bar.local', 'DNS:foo.bar.local'] self.assertTrue(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_134_fqdn_in_san_check(self): + def test_142_fqdn_in_san_check(self): """ successful check two entries no DNS one match """ fqdn = 'foo.bar.local' san_list = ['IP: 10.0.0.l', 'DNS:foo.bar.local'] self.assertTrue(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_135_fqdn_in_san_check(self): + def test_143_fqdn_in_san_check(self): """ successful check no fqdn """ fqdn = None san_list = ['IP: 10.0.0.l', 'DNS:foo.bar.local'] self.assertFalse(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_136_fqdn_in_san_check(self): + def test_144_fqdn_in_san_check(self): """ successful check no fqdn """ fqdn = '' san_list = ['IP: 10.0.0.l', 'DNS:foo.bar.local'] self.assertFalse(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_137_fqdn_in_san_check(self): + def test_145_fqdn_in_san_check(self): """ successful check blank fqdn """ fqdn = ' ' san_list = ['IP: 10.0.0.l', 'DNS:foo.bar.local'] self.assertFalse(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_138_fqdn_in_san_check(self): + def test_146_fqdn_in_san_check(self): """ successful check empty san_list """ fqdn = 'foo.bar.local' san_list = [] self.assertFalse(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_139_fqdn_in_san_check(self): + def test_147_fqdn_in_san_check(self): """ successful check two entries one match """ fqdn = 'foo.bar.local' san_list = ['foo1.bar.local', 'DNS:foo.bar.local'] self.assertTrue(self.fqdn_in_san_check(self.logger, san_list, fqdn)) - def test_140_sha256_hash_hex(self): + def test_148_sha256_hash_hex(self): """ sha256 digest as hex file """ self.assertEqual('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', self.sha256_hash_hex(self.logger, 'foo')) - def test_141_sha256_hash_hex(self): + def test_149_sha256_hash_hex(self): """ sha256 digest as hex file """ self.assertEqual('fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9', self.sha256_hash_hex(self.logger, 'bar')) - def test_142_sha256_hash(self): + def test_150_sha256_hash(self): """ sha256 digest """ self.assertEqual(b'LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564', self.b64_url_encode(self.logger, self.sha256_hash(self.logger, 'foo'))) - def test_143_sha256_hash(self): + def test_151_sha256_hash(self): """ sha256 digest """ self.assertEqual(b'_N4rLtula_QIYB-3If6bXDONEO5CnqBPrlURto-_j7k', self.b64_url_encode(self.logger, self.sha256_hash(self.logger, 'bar'))) - def test_144_b64_encode(self): + def test_152_b64_encode(self): """ base64 encode string """ self.assertEqual('Zm9v', self.b64_encode(self.logger, b'foo')) - def test_145_b64_encode(self): + def test_153_b64_encode(self): """ base64 encode string """ self.assertEqual('YmFyMQ==', self.b64_encode(self.logger, b'bar1')) - def test_146_b64_encode(self): + def test_154_b64_encode(self): """ base64 encode string """ self.assertEqual('YmFyMTI=', self.b64_encode(self.logger, b'bar12')) + @patch('OpenSSL.crypto.load_certificate') + @patch('OpenSSL.crypto.dump_certificate') + def test_155_cert_der2pem(self, mock_load, mock_dump): + """ test cert_der2pem """ + mock_load.return_value = 'load' + mock_dump.return_value = 'dump' + self.assertEqual('load', self.cert_der2pem('foo')) + + @patch('OpenSSL.crypto.load_certificate') + @patch('OpenSSL.crypto.dump_certificate') + def test_156_cert_pem2der(self, mock_load, mock_dump): + """ test cert_der2pem """ + mock_load.return_value = 'load' + mock_dump.return_value = 'dump' + self.assertEqual('load', self.cert_pem2der('foo')) + + def test_157_helper_cert_extensions_get(self): + """ test cert_san_get for a single SAN and recode = False""" + cert = """-----BEGIN CERTIFICATE----- +MIIEZDCCAkygAwIBAgIIe941mx0FQtAwDQYJKoZIhvcNAQELBQAwKjEXMBUGA1UE +CxMOYWNtZTJjZXJ0aWZpZXIxDzANBgNVBAMTBnN1Yi1jYTAeFw0yMTA0MDkxNTUy +MDBaFw0yNjA0MDkxNTUyMDBaMBgxFjAUBgNVBAMTDWVzdGNsaWVudC5lc3QwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAn6IqwTE1RvZUm3gelpu4tmrd +Fj8Ub98J1YeQz7qrew5iA81NeH9tR484edjcY0ieOt3e1MfxJoziWtaeqxpsfytm +VB/i+850kVZmvRCR1jhW/4AzidkVBMQiCR5erPmmheeCxbKkto0rHb7ziRA+F8/f +ZLKfLNsahEQPxDuMItyQFCOQFHh8Hfuend2NgsQKeZ1r5Czf3n5Q6NFff7HG+MDe +NDNdPB3ShgcvvNCFUS1z615/GIItfSqcWTAVaJ7436cA7yy5y4+0SvjfXYtHYfyt +hBj/5UqlUmjni8Irj5K8uEtb1YUujmvlTTbzPkhYqIkSoyr7t21Dz+gcYn49AgMB +AAGjgZ8wgZwwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUN3Z0iLv1FE17DCDBfpxW +2P+5+kIwCwYDVR0PBAQDAgO4MBMGA1UdJQQMMAoGCCsGAQUFBwMCMBgGA1UdEQQR +MA+CDWVzdGNsaWVudC5lc3QwEQYJYIZIAYb4QgEBBAQDAgWgMB4GCWCGSAGG+EIB +DQQRFg94Y2EgY2VydGlmaWNhdGUwDQYJKoZIhvcNAQELBQADggIBACMAHHH4/0eA +XbS/uKsIjLN1QPnnzgjxC0xoUon8UVM0PUMH+FMg6rs21Xyl5tn5iItmvKI9c3ak +AZ00RUQKVdmJVFRUKywmfF7n5epBpXtWJrSH817NT9GOp+PO5VUTDV5VkvpVLoy7 +WzThrheLKz1nC1dWowRz86tcBLAsC1zT17fsNZXQDuv4LiQQXs7QKhUU75r1Ixrd +BPeBQSP5skGpWxm8sapQSfOALoXu1pSoGIr6tqvNGuEoZGvUuWeQHG/G8c2ufL+6 +lEzZBBCd6e2tErkqD/vqfCRzbLcGgSPX0HVWdkjH09nHWXI5UhNr2YgGF7YvSTKW +JfbDVlTql1BuSn2yTQtDk4E8k9BLr8WfqFSZvYrivT9Ax1n3BD9jvQL5+QRdioH1 +kqNGMme0Pb43pHciX4hu9L5rGenZRmxeGXZ78uSOR+n2bGxAMw1OY7Rx/lsNSKWD +SN+7xIrwjjXO5Uthev1ecrLAK2+EpjITa6Y85ms39V4ypCEdujkKEBeVxuN8DdMJ +2GaFGluSRZeYZ0LAPfYr5sp6G6904WF+PcT0WjGenH4PJLXrAttbhhvQxXU0Q8s2 +CUwUHy5OT/DW3POq7WETc+zmFGwZqiP3W9gmN0hHXsKqkNmz2RYgoH57lPS1PJb0 +klGUNHG98CtsmlhrivhSTJWqSIOfyKGF +-----END CERTIFICATE-----""" + self.assertEqual(['MAA=', 'BBQ3dnSIu/UUTXsMIMF+nFbY/7n6Qg==', 'AwIDuA==', 'MAoGCCsGAQUFBwMC', 'MA+CDWVzdGNsaWVudC5lc3Q=', 'AwIFoA==', 'Fg94Y2EgY2VydGlmaWNhdGU='], self.cert_extensions_get(self.logger, cert, recode=False)) + + def test_158_helper_cert_extensions_get(self): + """ test cert_san_get for a single SAN and recode = True""" + cert = "MIIEZDCCAkygAwIBAgIIe941mx0FQtAwDQYJKoZIhvcNAQELBQAwKjEXMBUGA1UECxMOYWNtZTJjZXJ0aWZpZXIxDzANBgNVBAMTBnN1Yi1jYTAeFw0yMTA0MDkxNTUyMDBaFw0yNjA0MDkxNTUyMDBaMBgxFjAUBgNVBAMTDWVzdGNsaWVudC5lc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAn6IqwTE1RvZUm3gelpu4tmrdFj8Ub98J1YeQz7qrew5iA81NeH9tR484edjcY0ieOt3e1MfxJoziWtaeqxpsfytmVB/i+850kVZmvRCR1jhW/4AzidkVBMQiCR5erPmmheeCxbKkto0rHb7ziRA+F8/fZLKfLNsahEQPxDuMItyQFCOQFHh8Hfuend2NgsQKeZ1r5Czf3n5Q6NFff7HG+MDeNDNdPB3ShgcvvNCFUS1z615/GIItfSqcWTAVaJ7436cA7yy5y4+0SvjfXYtHYfythBj/5UqlUmjni8Irj5K8uEtb1YUujmvlTTbzPkhYqIkSoyr7t21Dz+gcYn49AgMBAAGjgZ8wgZwwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUN3Z0iLv1FE17DCDBfpxW2P+5+kIwCwYDVR0PBAQDAgO4MBMGA1UdJQQMMAoGCCsGAQUFBwMCMBgGA1UdEQQRMA+CDWVzdGNsaWVudC5lc3QwEQYJYIZIAYb4QgEBBAQDAgWgMB4GCWCGSAGG+EIBDQQRFg94Y2EgY2VydGlmaWNhdGUwDQYJKoZIhvcNAQELBQADggIBACMAHHH4/0eAXbS/uKsIjLN1QPnnzgjxC0xoUon8UVM0PUMH+FMg6rs21Xyl5tn5iItmvKI9c3akAZ00RUQKVdmJVFRUKywmfF7n5epBpXtWJrSH817NT9GOp+PO5VUTDV5VkvpVLoy7WzThrheLKz1nC1dWowRz86tcBLAsC1zT17fsNZXQDuv4LiQQXs7QKhUU75r1IxrdBPeBQSP5skGpWxm8sapQSfOALoXu1pSoGIr6tqvNGuEoZGvUuWeQHG/G8c2ufL+6lEzZBBCd6e2tErkqD/vqfCRzbLcGgSPX0HVWdkjH09nHWXI5UhNr2YgGF7YvSTKWJfbDVlTql1BuSn2yTQtDk4E8k9BLr8WfqFSZvYrivT9Ax1n3BD9jvQL5+QRdioH1kqNGMme0Pb43pHciX4hu9L5rGenZRmxeGXZ78uSOR+n2bGxAMw1OY7Rx/lsNSKWDSN+7xIrwjjXO5Uthev1ecrLAK2+EpjITa6Y85ms39V4ypCEdujkKEBeVxuN8DdMJ2GaFGluSRZeYZ0LAPfYr5sp6G6904WF+PcT0WjGenH4PJLXrAttbhhvQxXU0Q8s2CUwUHy5OT/DW3POq7WETc+zmFGwZqiP3W9gmN0hHXsKqkNmz2RYgoH57lPS1PJb0klGUNHG98CtsmlhrivhSTJWqSIOfyKGF" + self.assertEqual(['MAA=', 'BBQ3dnSIu/UUTXsMIMF+nFbY/7n6Qg==', 'AwIDuA==', 'MAoGCCsGAQUFBwMC', 'MA+CDWVzdGNsaWVudC5lc3Q=', 'AwIFoA==', 'Fg94Y2EgY2VydGlmaWNhdGU='], self.cert_extensions_get(self.logger, cert, recode=True)) + + def test_159_csr_dn_get(self): + """" test csr_dn_get """ + csr = 'MIICjDCCAXQCAQAwFzEVMBMGA1UEAwwMdGVzdF9yZXF1ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy6VRYaXuLS/DPa+pf5IEwycpjPfZ2vTFlvjvhwu9A3yaQQn4kD33Fu4p+zorIVmsjgpkUel2104lxFeSV081YKGzOtsajzaIRZhF7mHG5aVA8cahVPHlnxT06kO8F545ZsxE6T22tCbrLJpZk4hcaQUmGcZDWZqI7CXhbi1LSuIVIAAF0lTGMsanIM97ZEtA9mhtxFd7TsLlJpmls1l8MTavFcBtAZXqAsi4LnzEbozSjaLnuXsTe7tPmOS0uOLX+EcTAH/SxkbIg3whehTzC/sVmz5STbpklq3QuudtUl/509fpSa/UQ+WFOUUC3GhiiMM813ZsbAnt1BJepKtrfQIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHREEFjAUghJ0ZXN0X3JlcXVlc3QubG9jYWwwDQYJKoZIhvcNAQELBQADggEBAFcKxjJXHBVjzqF3e6fCkDbF1JnVtNyDxZB+h4b5lI7SIuA9O/+0hcl/njeFB1gJbRODws10kKkiAYLXvS/fsLJg1gdyFPmDiCd2nJhDUCBcGmVYraGhV45x67jcUmoeqSSj5KyUY9zI+v3nANvZMf+g31ORtW8PuspkiiLJiyuGzFS67DGovbcBRrM67IApO7p04VwLA0hssFUa+wF9PUWIyu9TLx+w0rNYcp3d1wkJ905TB8gwOKXeB0RwkporlOF3KEcT+ueKZE04867bjZ/ZpiuIDFnO23MsUKLKU9ebWgwYN/xzxA8sroM69y+Acpt9Zwn3vRjVlT92Ztl218Q=' + self.assertEqual('/CN=test_request', self.csr_dn_get(self.logger, csr)) + + def test_160_logger_setup(self): + """ logger setup """ + self.assertTrue(self.logger_setup(False)) + + def test_161_logger_setup(self): + """ logger setup """ + self.assertTrue(self.logger_setup(True)) + + def test_162_logger_info(self): + """ logger info """ + addr = 'addr' + url = 'url' + data_dic = {'foo': 'bar'} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.logger_info(self.logger, addr, url, data_dic) + self.assertIn("INFO:test_a2c:addr url {'foo': 'bar'}", lcm.output) + + def test_163_logger_info(self): + """ logger info replace remove Nonce in header """ + addr = 'addr' + url = 'url' + data_dic = {'foo': 'bar', 'header': {'Replay-Nonce': 'Replay-Nonce'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.logger_info(self.logger, addr, url, data_dic) + self.assertIn("INFO:test_a2c:addr url {'foo': 'bar', 'header': {'Replay-Nonce': '- modified -'}}", lcm.output) + + def test_164_logger_info(self): + """ logger info replace remnove cert """ + addr = 'addr' + url = '/acme/cert/secret' + data_dic = {'foo': 'bar', 'data': {'Replay-Nonce': 'Replay-Nonce'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.logger_info(self.logger, addr, url, data_dic) + self.assertIn("INFO:test_a2c:addr /acme/cert/secret {'foo': 'bar', 'data': ' - certificate - '}", lcm.output) + + def test_165_logger_info(self): + """ logger info replace remove token """ + addr = 'addr' + url = 'url' + data_dic = {'foo': 'bar', 'data': {'token': 'token'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.logger_info(self.logger, addr, url, data_dic) + self.assertIn("INFO:test_a2c:addr url {'foo': 'bar', 'data': {'token': '- modified -'}}", lcm.output) + + def test_166_logger_info(self): + """ logger info replace remove single token in challenges """ + addr = 'addr' + url = 'url' + data_dic = {'foo': 'bar', 'data': {'challenges': [{'foo1': 'bar1', 'token': 'token1'}]}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.logger_info(self.logger, addr, url, data_dic) + self.assertIn("INFO:test_a2c:addr url {'foo': 'bar', 'data': {'challenges': [{'foo1': 'bar1', 'token': '- modified - '}]}}", lcm.output) + + def test_167_logger_info(self): + """ logger info replace remove two token in challenges """ + addr = 'addr' + url = 'url' + data_dic = {'foo': 'bar', 'data': {'challenges': [{'foo1': 'bar1', 'token': 'token1'}, {'foo2': 'bar2', 'token': 'token1'}]}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.logger_info(self.logger, addr, url, data_dic) + self.assertIn("INFO:test_a2c:addr url {'foo': 'bar', 'data': {'challenges': [{'foo1': 'bar1', 'token': '- modified - '}, {'foo2': 'bar2', 'token': '- modified - '}]}}", lcm.output) + + @patch('builtins.print') + def test_168_print_debug(self, mock_print): + """ test print_debug """ + self.print_debug(False, 'test') + self.assertFalse(mock_print.called) + + @patch('builtins.print') + def test_169_print_debug(self, mock_print): + """ test print_debug """ + self.print_debug(True, 'test') + self.assertTrue(mock_print.called) + + def test_170_jwk_thumbprint_get(self): + """ test jwk_thumbprint_get with empty pubkey """ + pub_key = None + self.assertFalse(self.jwk_thumbprint_get(self.logger, pub_key)) + + @patch('jwcrypto.jwk.JWK') + def test_171_jwk_thumbprint_get(self, mock_jwk): + """ test jwk_thumbprint_get with pubkey """ + pub_key = {'pub_key': 'pub_key'} + mock_jwk = Mock() + self.assertTrue(self.jwk_thumbprint_get(self.logger, pub_key)) + + @patch('jwcrypto.jwk.JWK') + def test_172_jwk_thumbprint_get(self, mock_jwk): + """ test jwk_thumbprint_get with pubkey """ + pub_key = {'pub_key': 'pub_key'} + mock_jwk.side_effect = Exception('exc_jwk_jwk') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertFalse(self.jwk_thumbprint_get(self.logger, pub_key)) + self.assertIn('ERROR:test_a2c:jwk_thumbprint_get(): error: exc_jwk_jwk', lcm.output) + + @patch('socket.AF_INET') + def test_173_allowed_gai_family(self, mock_sock): + """ test allowed_gai_family """ + self.assertTrue(self.allowed_gai_family()) + + def test_174_validate_csr(self): + """ patched_create_connection """ + self.assertTrue(self.validate_csr(self.logger, 'oder_dic', 'csr')) + + @patch('ssl.DER_cert_to_PEM_cert') + @patch('ssl.create_default_context') + @patch('socket.create_connection') + def test_175_servercert_get(self, mock_sock, mock_context, mock_cert): + """ test servercert get """ + mock_sock = Mock() + mock_context = Mock() + mock_cert.return_value = 'foo' + self.assertEqual('foo', self.servercert_get(self.logger, 'hostname')) + + @patch('dns.resolver.query') + def test_176_txt_get(self, mock_resolve): + """ successful dns-query returning one txt record """ + resp_obj = Mock() + resp_obj.strings = ['foo', 'bar'] + mock_resolve.return_value = [resp_obj] + self.assertEqual(['foo'], self.txt_get(self.logger, 'foo')) + + @patch('dns.resolver.query') + def test_177_txt_get(self, mock_resolve): + """ successful dns-query returning one txt record """ + resp_obj1 = Mock() + resp_obj1.strings = ['foo1', 'bar1'] + resp_obj2 = Mock() + resp_obj2.strings = ['foo2', 'bar2'] + mock_resolve.return_value = [resp_obj1, resp_obj2] + self.assertEqual(['foo1', 'foo2'], self.txt_get(self.logger, 'foo')) + + @patch('dns.resolver.query') + def test_178_txt_get(self, mock_resolve): + """ successful dns-query returning one txt record """ + mock_resolve.side_effect = Exception('mock_resolve') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertFalse(self.txt_get(self.logger, 'foo')) + self.assertIn('ERROR:test_a2c:txt_get() error: mock_resolve', lcm.output) + if __name__ == '__main__': unittest.main() diff --git a/test/test_xca_ca_handler.py b/test/test_xca_ca_handler.py index d7a98761..b6d6a357 100644 --- a/test/test_xca_ca_handler.py +++ b/test/test_xca_ca_handler.py @@ -150,6 +150,27 @@ def test_016_ca_key_load(self): # self.cahandler.passphrase = 'wrongpw' self.assertFalse(self.cahandler._ca_key_load()) + @patch('OpenSSL.crypto.load_privatekey') + def test_018_ca_key_load(self, mock_key): + """ CAhandler._ca_key_load """ + self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' + self.cahandler.issuing_ca_key = 'sub-ca' + self.cahandler.passphrase = 'test1234' + mock_key.side_effect = Exception('exc_key_load') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._ca_key_load() + self.assertIn('ERROR:test_a2c:CAhandler._ca_key_load() failed with error: exc_key_load', lcm.output) + + @patch('OpenSSL.crypto.load_certificate') + def test_019_ca_cert_load(self, mock_certload): + """ CAhandler._ca_cert_load """ + self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' + self.cahandler.issuing_ca_name = 'sub-ca' + mock_certload.side_effect = Exception('exc_cert_load') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, None, None), self.cahandler._ca_load()) + self.assertIn('ERROR:test_a2c:CAhandler._ca_cert_load() failed with error: exc_cert_load', lcm.output) + def test_017_csr_insert(self): """ CAhandler._csr_insert empty item dic """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' @@ -343,6 +364,19 @@ def test_047_cert_insert(self): cert_dic = {'item': 1, 'serial': 'serial', 'issuer': 2, 'ca': 3, 'cert': 'cert', 'iss_hash': 4, 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') + def test_050_cert_insert(self, mock_open, mock_close): + """ CAhandler._csr_import with hash not int """ + cert_dic = {'item': 1, 'serial': 'serial', 'issuer': 2, 'ca': 3, 'cert': 'cert', 'iss_hash': 4, 'hash': 5} + mock_open.return_value = True + mock_close.return_value = True + self.cahandler.cursor = Mock() + self.cahandler.cursor.lastrowid = 5 + self.assertEqual(5, self.cahandler._cert_insert(cert_dic)) + self.assertTrue(mock_open.called) + self.assertTrue(mock_close.called) + def test_048_pemcertchain_generate(self): """ CAhandler._pemcertchain_generate no certificates """ ee_cert = None @@ -494,6 +528,18 @@ def test_067_cert_insert(self): rev_dic = {'caID': 0, 'serial': 'serial', 'date': 'date', 'invaldate': 'invaldate', 'reasonBit': '0'} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') + def test_071_rev_insert(self, mock_open, mock_close): + """ CAhandler._revocation_insert with caID is not inall okt """ + mock_close.return_value = True + self.cahandler.cursor = Mock() + self.cahandler.cursor.lastrowid = 5 + rev_dic = {'caID': 0, 'serial': 'serial', 'date': 'date', 'invaldate': 'invaldate', 'reasonBit': 0} + self.assertEqual(5, self.cahandler._revocation_insert(rev_dic)) + self.assertTrue(mock_open.called) + self.assertTrue(mock_close.called) + @patch('examples.ca_handler.xca_ca_handler.uts_to_date_utc') def test_068_revoke(self, mock_date): """ CAhandler.revocation without xdb file """ @@ -599,6 +645,34 @@ def test_078_config_load(self, mock_load_cfg): self.cahandler._config_load() self.assertEqual('foo', self.cahandler.template_name) + @patch('examples.ca_handler.xca_ca_handler.load_config') + def test_083_config_load(self, mock_load_cfg): + """ test _config_load - load template """ + mock_load_cfg.return_value = {'CAhandler': {'xdb_file': 'foo'}} + self.cahandler._config_load() + self.assertEqual('foo', self.cahandler.xdb_file) + + @patch('examples.ca_handler.xca_ca_handler.load_config') + def test_084_config_load(self, mock_load_cfg): + """ test _config_load - load template """ + mock_load_cfg.return_value = {'CAhandler': {'passphrase': 'foo'}} + self.cahandler._config_load() + self.assertEqual('foo', self.cahandler.passphrase) + + @patch('examples.ca_handler.xca_ca_handler.load_config') + def test_085_config_load(self, mock_load_cfg): + """ test _config_load - load template """ + mock_load_cfg.return_value = {'CAhandler': {'issuing_ca_name': 'foo'}} + self.cahandler._config_load() + self.assertEqual('foo', self.cahandler.issuing_ca_name) + + @patch('examples.ca_handler.xca_ca_handler.load_config') + def test_086_config_load(self, mock_load_cfg): + """ test _config_load - load template """ + mock_load_cfg.return_value = {'CAhandler': {'issuing_ca_key': 'foo'}} + self.cahandler._config_load() + self.assertEqual('foo', self.cahandler.issuing_ca_key) + def test_079_stream_split(self): """ test stream_split - all ok """ byte_stream = b'before\x00\x00\x00\x0cafter' @@ -1212,6 +1286,340 @@ def test_149__extension_list_generate(self, mock_crypto): result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always')] self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_load') + def test_150__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.cahandler.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_load') + def test_151__enter__(self, mock_cfg): + """ test enter """ + self.cahandler.xdb_file = self.dir_path + '/ca/est_proxy.xdb' + mock_cfg.return_value = True + self.cahandler.__enter__() + self.assertFalse(mock_cfg.called) + + def test_152_trigger(self): + """ test trigger """ + self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) + + def test_153_poll(self): + """ test poll """ + self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier','csr')) + + def test_154_stub_func(self): + """ test stubfunc """ + self.assertEqual('parameter', self.cahandler._stub_func('parameter')) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_insert') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._item_insert') + def test_155__store_cert(self, mock_i_insert, mock_c_insert): + """ test insert """ + mock_i_insert.return_value = 1 + mock_c_insert.return_value = 2 + self.cahandler._store_cert('ca_id', 'cert_name', 'serial', 'cert', 'name_hash', 'issuer_hash') + self.assertTrue(mock_i_insert.called) + self.assertTrue(mock_c_insert.called) + + @patch('examples.ca_handler.xca_ca_handler.dict_from_row') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') + def test_156_revocation_search(self, mock_open, mock_close, mock_dicfrow): + """ revocation search """ + mock_dicfrow.return_value = {'foo': 'bar'} + mock_open.return_value = True + mock_close.return_value = True + self.cahandler.cursor = Mock() + self.assertEqual({'foo': 'bar'}, self.cahandler._revocation_search('column', 'value')) + self.assertTrue(mock_open.called) + self.assertTrue(mock_close.called) + self.assertTrue(mock_dicfrow.called) + + @patch('examples.ca_handler.xca_ca_handler.dict_from_row') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') + def test_157_revocation_search(self, mock_open, mock_close, mock_dicfrow): + """ revocation search dicfromrow throws exception """ + mock_dicfrow.side_effect = Exception('exc_dicfromrow') + mock_open.return_value = True + mock_close.return_value = True + self.cahandler.cursor = Mock() + self.assertFalse(self.cahandler._revocation_search('column', 'value')) + self.assertTrue(mock_open.called) + self.assertTrue(mock_close.called) + self.assertTrue(mock_dicfrow.called) + + @patch('examples.ca_handler.xca_ca_handler.dict_from_row') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') + def test_166_revocation_search(self, mock_open, mock_close, mock_dicfrow): + """ revocation search """ + mock_dicfrow.return_value = {'foo': 'bar'} + mock_open.return_value = True + mock_close.return_value = True + self.cahandler.cursor = Mock() + self.assertEqual({'foo': 'bar'}, self.cahandler._revocation_search('column', 'value')) + self.assertTrue(mock_open.called) + self.assertTrue(mock_close.called) + self.assertTrue(mock_dicfrow.called) + + @patch('examples.ca_handler.xca_ca_handler.dict_from_row') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') + def test_167_revocation_search(self, mock_open, mock_close, mock_dicfrow): + """ revocation search dicfromrow throws exception """ + mock_dicfrow.side_effect = Exception('exc_dicfromrow') + mock_open.return_value = True + mock_close.return_value = True + self.cahandler.cursor = Mock() + self.assertFalse(self.cahandler._revocation_search('column', 'value')) + self.assertTrue(mock_open.called) + self.assertTrue(mock_close.called) + self.assertTrue(mock_dicfrow.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_insert') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._item_insert') + def test_165__store_cert(self, mock_i_insert, mock_c_insert): + """ test insert """ + mock_i_insert.return_value = 1 + mock_c_insert.return_value = 2 + self.cahandler._store_cert('ca_id', 'cert_name', 'serial', 'cert', 'name_hash', 'issuer_hash') + self.assertTrue(mock_i_insert.called) + self.assertTrue(mock_c_insert.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_168_enroll(self, mock_chk): + """ enroll test error returned from config_check""" + mock_chk.return_value = 'error' + self.assertEqual(('error', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_169_enroll(self, mock_chk, mock_nameget): + """ enroll test error returned no request name returned """ + mock_chk.return_value = None + mock_nameget.return_value = None + self.assertEqual(('request_name lookup failed', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_170_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + """ enroll test error returned from ca_load failed """ + mock_chk.return_value = None + mock_nameget.return_value = 'name' + mock_csrinfo.return_value = {'foo': 'bar'} + mock_ca_load.return_value = (None, None, None) + self.assertEqual(('ca lookup failed', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_171_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + """ enroll test error returned from ca_load failed """ + mock_chk.return_value = None + mock_nameget.return_value = 'name' + mock_csrinfo.return_value = {'foo': 'bar'} + mock_ca_load.return_value = ('ca_key', None, None) + self.assertEqual(('ca lookup failed', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_172_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + """ enroll test error returned from ca_load failed """ + mock_chk.return_value = None + mock_nameget.return_value = 'name' + mock_csrinfo.return_value = {'foo': 'bar'} + mock_ca_load.return_value = ('ca_key', 'ca_cert', None) + self.assertEqual(('ca lookup failed', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.xca_ca_handler.b64_encode') + @patch('examples.ca_handler.xca_ca_handler.convert_byte_to_string') + @patch('OpenSSL.crypto.dump_certificate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._store_cert') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extension_list_generate') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_173_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + """ enroll test """ + mock_chk.return_value = None + mock_nameget.return_value = 'name' + mock_csrinfo.return_value = {'foo': 'bar'} + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_ca_load.return_value = ('ca_key', ca_obj, 5) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csr_load.return_value = Mock() + mock_csr_load.return_value.get_subject = Mock(return_value=dn_obj) + mock_ext_get.return_value = ['ext1', 'ext2'] + mock_509.return_value = Mock() + mock_509.return_value.get_serial_number = Mock(return_value=42) + mock_509.return_value.subject_name_hash = Mock(return_value=42) + mock_store.return_value = 'foo' + mock_dump.return_value = 'foo' + mock_cbs.return_value = 'foo' + mock_b64e.return_value = 'foo' + self.assertEqual((None, 'foofoo', 'foo', None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.xca_ca_handler.b64_encode') + @patch('examples.ca_handler.xca_ca_handler.convert_byte_to_string') + @patch('OpenSSL.crypto.dump_certificate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._store_cert') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extension_list_generate') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_175_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + """ enroll test - default cert validity """ + mock_chk.return_value = None + mock_nameget.return_value = 'name' + mock_csrinfo.return_value = {'foo': 'bar'} + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_ca_load.return_value = ('ca_key', ca_obj, 5) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csr_load.return_value = Mock() + mock_csr_load.return_value.get_subject = Mock(return_value=dn_obj) + mock_ext_get.return_value = ['ext1', 'ext2'] + mock_509.return_value = Mock() + mock_509.return_value.get_serial_number = Mock(return_value=42) + mock_509.return_value.subject_name_hash = Mock(return_value=42) + mock_store.return_value = 'foo' + mock_dump.return_value = 'foo' + mock_cbs.return_value = 'foo' + mock_b64e.return_value = 'foo' + self.assertEqual((None, 'foofoo', 'foo', None), self.cahandler.enroll('csr')) + self.assertEqual(365, self.cahandler.cert_validity_days) + + @patch('examples.ca_handler.xca_ca_handler.b64_encode') + @patch('examples.ca_handler.xca_ca_handler.convert_byte_to_string') + @patch('OpenSSL.crypto.dump_certificate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._store_cert') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extension_list_generate') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_174_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + """ enroll test - rewrite CN """ + mock_chk.return_value = None + mock_nameget.return_value = 'reqname' + mock_csrinfo.return_value = {'foo': 'bar'} + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_ca_load.return_value = ('ca_key', ca_obj, 5) + dn_obj = Mock() + dn_obj.CN = None + mock_csr_load.return_value = Mock() + mock_csr_load.return_value.get_subject = Mock(return_value=dn_obj) + mock_ext_get.return_value = ['ext1', 'ext2'] + mock_509.return_value = Mock() + mock_509.return_value.get_serial_number = Mock(return_value=42) + mock_509.return_value.subject_name_hash = Mock(return_value=42) + mock_store.return_value = 'foo' + mock_dump.return_value = 'foo' + mock_cbs.return_value = 'foo' + mock_b64e.return_value = 'foo' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, 'foofoo', 'foo', None), self.cahandler.enroll('csr')) + self.assertIn('INFO:test_a2c:rewrite CN to reqname', lcm.output) + + @patch('examples.ca_handler.xca_ca_handler.b64_encode') + @patch('examples.ca_handler.xca_ca_handler.convert_byte_to_string') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._template_load') + @patch('OpenSSL.crypto.dump_certificate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._store_cert') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extension_list_generate') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_176_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): + """ enroll test - template load validity """ + mock_chk.return_value = None + mock_nameget.return_value = 'name' + mock_csrinfo.return_value = {'foo': 'bar'} + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_ca_load.return_value = ('ca_key', ca_obj, 5) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csr_load.return_value = Mock() + mock_csr_load.return_value.get_subject = Mock(return_value=dn_obj) + mock_ext_get.return_value = ['ext1', 'ext2'] + mock_509.return_value = Mock() + mock_509.return_value.get_serial_number = Mock(return_value=42) + mock_509.return_value.subject_name_hash = Mock(return_value=42) + mock_store.return_value = 'foo' + mock_dump.return_value = 'foo' + mock_cbs.return_value = 'foo' + mock_b64e.return_value = 'foo' + dn_dic = {'foo': 'bar'} + template_dic = {'validity': 500} + mock_tmp_load.return_value = (dn_dic, template_dic) + self.cahandler.template_name = 'template' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, 'foofoo', 'foo', None), self.cahandler.enroll('csr')) + self.assertIn('INFO:test_a2c:take validity from template: 500', lcm.output) + + @patch('examples.ca_handler.xca_ca_handler.b64_encode') + @patch('examples.ca_handler.xca_ca_handler.convert_byte_to_string') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._template_load') + @patch('OpenSSL.crypto.dump_certificate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._store_cert') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extension_list_generate') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') + def test_177_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): + """ enroll test - template load validity """ + mock_chk.return_value = None + mock_nameget.return_value = 'name' + mock_csrinfo.return_value = {'foo': 'bar'} + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_ca_load.return_value = ('ca_key', ca_obj, 5) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csr_load.return_value = Mock() + mock_csr_load.return_value.get_subject = Mock(return_value=dn_obj) + mock_ext_get.return_value = ['ext1', 'ext2'] + mock_509.return_value = Mock() + mock_509.return_value.get_serial_number = Mock(return_value=42) + mock_509.return_value.subject_name_hash = Mock(return_value=42) + mock_store.return_value = 'foo' + mock_dump.return_value = 'foo' + dn_dic = {'foo': 'bar'} + template_dic = {} + mock_tmp_load.return_value = (dn_dic, template_dic) + self.cahandler.template_name = 'template' + mock_cbs.return_value = 'foo' + mock_b64e.return_value = 'foo' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, 'foofoo', 'foo', None), self.cahandler.enroll('csr')) + self.assertIn('INFO:test_a2c:modify subject with template data', lcm.output) if __name__ == '__main__': From 0abfcf9b69c4b9974b67ec37fb2a7d1411ac0c60 Mon Sep 17 00:00:00 2001 From: grindsa Date: Fri, 14 May 2021 17:58:08 +0200 Subject: [PATCH 05/51] [fix] typo --- examples/ca_handler/certifier_ca_handler.py | 18 +++++- examples/ca_handler/xca_ca_handler.py | 2 +- test/test_certifier_handler.py | 62 +++++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/examples/ca_handler/certifier_ca_handler.py b/examples/ca_handler/certifier_ca_handler.py index 7fafe8af..f37e3efe 100644 --- a/examples/ca_handler/certifier_ca_handler.py +++ b/examples/ca_handler/certifier_ca_handler.py @@ -258,7 +258,13 @@ def _request_poll(self, request_url): poll_identifier = request_url rejected = False - request_dic = requests.get(request_url, auth=self.auth, verify=self.ca_bundle).json() + try: + request_dic = requests.get(request_url, auth=self.auth, verify=self.ca_bundle).json() + except BaseException as err: + self.logger.error('CAhandler._request.poll() returned: {0}'.format(err)) + request_dic = {} + error = err + # check response if 'status' in request_dic: if request_dic['status'] == 'accepted': @@ -270,10 +276,18 @@ def _request_poll(self, request_url): error = None cert_bundle = self._pem_cert_chain_generate(cert_dic) cert_raw = cert_dic['certificateBase64'] + else: + error = 'certificateBase64 is missing in cert request response' + else: + error = 'No certificate structure in request response' elif request_dic['status'] == 'rejected': error = 'Request rejected by operator' rejected = True - + else: + error = 'Unknown request status: {0}'.format(request_dic['status']) + else: + error = '"status" field not found in response.' + self.logger.debug('CAhandler._request_poll() ended with error: {0}'.format(error)) return(error, cert_bundle, cert_raw, poll_identifier, rejected) diff --git a/examples/ca_handler/xca_ca_handler.py b/examples/ca_handler/xca_ca_handler.py index 8895993e..58d6933f 100644 --- a/examples/ca_handler/xca_ca_handler.py +++ b/examples/ca_handler/xca_ca_handler.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -""" handler for an openssl ca """ +""" handler for xca handler """ from __future__ import print_function import os import sqlite3 diff --git a/test/test_certifier_handler.py b/test/test_certifier_handler.py index 642432b0..e660712a 100644 --- a/test/test_certifier_handler.py +++ b/test/test_certifier_handler.py @@ -733,6 +733,68 @@ def test_072__pem_cert_chain_generate(self, mock_get): mock_get.side_effect = [mockresponse1, mockresponse2] self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) + def test_066__enter__(self): + """ test __enter__ """ + self.cahandler.__enter__() + + @patch('requests.get') + def test_074_request_poll(self, mock_get): + """ test request poll request returned exception """ + mock_get.side_effect = Exception('exc_api_get') + result = ('"status" field not found in response.', None, None, 'url', False) + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(result, self.cahandler._request_poll('url')) + self.assertIn('ERROR:test_a2c:CAhandler._request.poll() returned: exc_api_get', lcm.output) + + @patch('requests.get') + def test_075_request_poll(self, mock_get): + """ test request poll request returned unknown status """ + mockresponse = Mock() + mockresponse.json = lambda: {'status': 'unknown'} + mock_get.return_value = mockresponse + result = ('Unknown request status: unknown', None, None, 'url', False) + self.assertEqual(result, self.cahandler._request_poll('url')) + + @patch('requests.get') + def test_076_request_poll(self, mock_get): + """ test request poll request returned status rejected """ + mockresponse = Mock() + mockresponse.json = lambda: {'status': 'rejected'} + mock_get.return_value = mockresponse + result = ('Request rejected by operator', None, None, 'url', True) + self.assertEqual(result, self.cahandler._request_poll('url')) + + @patch('requests.get') + def test_077_request_poll(self, mock_get): + """ test request poll request returned status accepted but no certinformation in """ + mockresponse = Mock() + mockresponse.json = lambda: {'status': 'accepted', 'foo': 'bar'} + mock_get.return_value = mockresponse + result = ('No certificate structure in request response', None, None, 'url', False) + self.assertEqual(result, self.cahandler._request_poll('url')) + + @patch('requests.get') + def test_077_request_poll(self, mock_get): + """ test request poll request returned status accepted but no certinformation in """ + mockresponse = Mock() + mockresponse.json = lambda: {'status': 'accepted', 'certificate': 'certificate'} + mock_get.return_value = mockresponse + result = ('certificateBase64 is missing in cert request response', None, None, 'url', False) + self.assertEqual(result, self.cahandler._request_poll('url')) + + @patch('examples.ca_handler.certifier_ca_handler.CAhandler._pem_cert_chain_generate') + @patch('requests.get') + def test_078_request_poll(self, mock_get, mock_pemgen): + """ test request poll request returned status accepted but no certinformation in """ + mockresponse = Mock() + mockresponse.json = lambda: {'status': 'accepted', 'certificate': 'certificate', 'certificateBase64': 'certificateBase64'} + mock_get.return_value = mockresponse + mock_pemgen.return_value = 'bundle' + result = (None, 'bundle', 'certificateBase64', 'url', False) + self.assertEqual(result, self.cahandler._request_poll('url')) + + + if __name__ == '__main__': if os.path.exists('acme_test.db'): From 1d454af21583e24aa5a210768f5f22bee03851b2 Mon Sep 17 00:00:00 2001 From: grindsa Date: Fri, 14 May 2021 23:16:09 +0200 Subject: [PATCH 06/51] [tst] unittests --- test/test_account.py | 208 ++++++++++++++++----------------- test/test_authorization.py | 18 +-- test/test_certifier_handler.py | 138 +++++++++++----------- test/test_message.py | 68 ++++++++++- 4 files changed, 249 insertions(+), 183 deletions(-) diff --git a/test/test_account.py b/test/test_account.py index 84360531..e47a0dc8 100644 --- a/test/test_account.py +++ b/test/test_account.py @@ -287,35 +287,35 @@ def test_031_account_parse(self, mock_mcheck, mock_del, mock_nnonce, mock_keycha message = '{"foo" : "bar"}' self.assertEqual({'code': 200, 'data': {}, 'header': {'Replay-Nonce': 'new_nonce'}}, self.account.parse(message)) - def test_030_account__onlyreturnexisting(self): + def test_032_account__onlyreturnexisting(self): """ test onlyReturnExisting with False """ # self.signature.dbstore.jwk_load.return_value = 1 protected = {} payload = {'onlyreturnexisting' : False} self.assertEqual((400, 'urn:ietf:params:acme:error:userActionRequired', 'onlyReturnExisting must be true'), self.account._onlyreturnexisting(protected, payload)) - def test_031_account__onlyreturnexisting(self): + def test_033_account__onlyreturnexisting(self): """ test onlyReturnExisting without jwk structure """ # self.signature.dbstore.jwk_load.return_value = 1 protected = {} payload = {'onlyreturnexisting' : True} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'jwk structure missing'), self.account._onlyreturnexisting(protected, payload)) - def test_032_account__onlyreturnexisting(self): + def test_034_account__onlyreturnexisting(self): """ test onlyReturnExisting fucntion without onlyReturnExisting structure """ # self.signature.dbstore.jwk_load.return_value = 1 protected = {} payload = {} self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'onlyReturnExisting without payload'), self.account._onlyreturnexisting(protected, payload)) - def test_033_account__onlyreturnexisting(self): + def test_035_account__onlyreturnexisting(self): """ test onlyReturnExisting for existing account """ self.signature.dbstore.account_lookup.return_value = {'name' : 'foo', 'alg' : 'RS256'} protected = {'jwk' : {'n' : 'foo'}} payload = {'onlyreturnexisting' : True} self.assertEqual((200, 'foo', None), self.account._onlyreturnexisting(protected, payload)) - def test_034_account__onlyreturnexisting(self): + def test_036_account__onlyreturnexisting(self): """ test onlyReturnExisting for non existing account """ self.signature.dbstore.account_lookup.return_value = False protected = {'jwk' : {'n' : 'foo'}} @@ -323,7 +323,7 @@ def test_034_account__onlyreturnexisting(self): self.assertEqual((400, 'urn:ietf:params:acme:error:accountDoesNotExist', None), self.account._onlyreturnexisting(protected, payload)) @patch('acme.account.Account._contact_check') - def test_035_account__contacts_update(self, mock_contact_chk,): + def test_037_account__contacts_update(self, mock_contact_chk,): """ Account.contact_update() failed contact_check failed """ mock_contact_chk.return_value = (400, 'message', 'detail') payload = '{"foo" : "bar"}' @@ -331,7 +331,7 @@ def test_035_account__contacts_update(self, mock_contact_chk,): self.assertEqual((400, 'message', 'detail'), self.account._contacts_update(aname, payload)) @patch('acme.account.Account._contact_check') - def test_036_account__contacts_update(self, mock_contact_chk,): + def test_038_account__contacts_update(self, mock_contact_chk,): """ Account.contact_update() failed bcs account update failed """ mock_contact_chk.return_value = (200, 'message', 'detail') self.account.dbstore.account_update.return_value = None @@ -340,7 +340,7 @@ def test_036_account__contacts_update(self, mock_contact_chk,): self.assertEqual((400, 'urn:ietf:params:acme:error:accountDoesNotExist', 'update failed'), self.account._contacts_update(aname, payload)) @patch('acme.account.Account._contact_check') - def test_037_account__contacts_update(self, mock_contact_chk,): + def test_039_account__contacts_update(self, mock_contact_chk,): """ Account.contact_update() succ """ mock_contact_chk.return_value = (200, 'message', 'detail') self.account.dbstore.account_update.return_value = 'foo' @@ -350,7 +350,7 @@ def test_037_account__contacts_update(self, mock_contact_chk,): @patch('acme.account.Account._contacts_update') @patch('acme.message.Message.check') - def test_038_account_parse(self, mock_mcheck, mock_contact_upd): + def test_040_account_parse(self, mock_mcheck, mock_contact_upd): """ test failed account parse for contacts update as contact updated failed """ mock_mcheck.return_value = (200, None, None, 'protected', {"contact" : "deactivated"}, 'account_name') mock_contact_upd.return_value = (400, 'message', 'detail') @@ -362,7 +362,7 @@ def test_038_account_parse(self, mock_mcheck, mock_contact_upd): @patch('acme.account.Account._lookup') @patch('acme.account.Account._contacts_update') @patch('acme.message.Message.check') - def test_039_account_parse(self, mock_mcheck, mock_contact_upd, mock_account_lookup, mock_datestr, mock_nnonce): + def test_041_account_parse(self, mock_mcheck, mock_contact_upd, mock_account_lookup, mock_datestr, mock_nnonce): """ test succ account parse for reqeust with succ contacts update """ mock_mcheck.return_value = (200, None, None, 'protected', {"contact" : "deactivated"}, 'account_name') mock_contact_upd.return_value = (200, None, None) @@ -372,158 +372,158 @@ def test_039_account_parse(self, mock_mcheck, mock_contact_upd, mock_account_loo message = 'message' self.assertEqual({'code': 200, 'data': {'contact': [u'foo@bar', u'foo1@bar'], 'createdAt': 'foo_date', 'key': {u'foo1': u'bar1', u'foo2': u'bar2'}, 'status': 'valid'}, 'header': {'Replay-Nonce': 'new_nonce'}}, self.account.parse(message)) - def test_040_account__key_compare(self): + def test_042_account__key_compare(self): """ Account.key_compare() with two empty dictionaries""" self.account.dbstore.jwk_load.return_value = {} aname = 'foo' okey = {} self.assertEqual((401, 'urn:ietf:params:acme:error:unauthorized', 'wrong public key'), self.account._key_compare(aname, okey)) - def test_041_account__key_compare(self): + def test_043_account__key_compare(self): """ Account.key_compare() with empty pub_key and existing old_key""" self.account.dbstore.jwk_load.return_value = {} aname = 'foo' okey = {'foo': 'bar'} self.assertEqual((401, 'urn:ietf:params:acme:error:unauthorized', 'wrong public key'), self.account._key_compare(aname, okey)) - def test_042_account__key_compare(self): + def test_044_account__key_compare(self): """ Account.key_compare() with existing pub_key and empty old_key""" self.account.dbstore.jwk_load.return_value = {'foo': 'bar'} aname = 'foo' okey = {} self.assertEqual((401, 'urn:ietf:params:acme:error:unauthorized', 'wrong public key'), self.account._key_compare(aname, okey)) - def test_043_account__key_compare(self): + def test_045_account__key_compare(self): """ Account.key_compare() with similar pub_key empty old_key""" self.account.dbstore.jwk_load.return_value = {'foo1': 'bar1', 'foo2': 'bar2', 'foo3': None} aname = 'foo' okey = {'foo1': 'bar1', 'foo2': 'bar2', 'foo3': None} self.assertEqual((200, None, None), self.account._key_compare(aname, okey)) - def test_044_account__key_compare(self): + def test_046_account__key_compare(self): """ Account.key_compare() with similar pub_key empty old_key but different order""" self.account.dbstore.jwk_load.return_value = {'foo1': 'bar1', 'foo2': 'bar2', 'foo3': None} aname = 'foo' okey = {'foo3': None, 'foo2': 'bar2', 'foo1': 'bar1'} self.assertEqual((200, None, None), self.account._key_compare(aname, okey)) - def test_045_account__key_compare(self): + def test_047_account__key_compare(self): """ Account.key_compare() pub_key alg rewrite""" self.account.dbstore.jwk_load.return_value = {'foo1': 'bar1', 'foo2': 'bar2', 'alg': 'ESfoo'} aname = 'foo' okey = {'alg': 'ECDSA', 'foo2': 'bar2', 'foo1': 'bar1'} self.assertEqual((200, None, None), self.account._key_compare(aname, okey)) - def test_046_account__key_compare(self): + def test_048_account__key_compare(self): """ Account.key_compare() pub_key failed alg rewrite""" self.account.dbstore.jwk_load.return_value = {'foo1': 'bar1', 'foo2': 'bar2', 'alg': 'foo'} aname = 'foo' okey = {'alg': 'ECDSA', 'foo2': 'bar2', 'foo1': 'bar1'} self.assertEqual((401, 'urn:ietf:params:acme:error:unauthorized', 'wrong public key'), self.account._key_compare(aname, okey)) - def test_047_account__key_compare(self): + def test_049_account__key_compare(self): """ Account.key_compare() pub_key failed alg rewrite""" self.account.dbstore.jwk_load.return_value = {'foo1': 'bar1', 'foo2': 'bar2', 'alg': 'ESfoo'} aname = 'foo' okey = {'alg': 'rsa', 'foo2': 'bar2', 'foo1': 'bar1'} self.assertEqual((401, 'urn:ietf:params:acme:error:unauthorized', 'wrong public key'), self.account._key_compare(aname, okey)) - def test_048_account__key_compare(self): + def test_050_account__key_compare(self): """ Account.key_compare() pub_key failed alg rewrite no alg statement in old_key""" self.account.dbstore.jwk_load.return_value = {'foo1': 'bar1', 'foo2': 'bar2', 'alg': 'ESfoo'} aname = 'foo' okey = {'foo3': None, 'foo2': 'bar2', 'foo1': 'bar1'} self.assertEqual((401, 'urn:ietf:params:acme:error:unauthorized', 'wrong public key'), self.account._key_compare(aname, okey)) - def test_049_account__key_compare(self): + def test_051_account__key_compare(self): """ Account.key_compare() pub_key failed alg rewrite no alg statement in pub_key""" self.account.dbstore.jwk_load.return_value = {'foo1': 'bar1', 'foo2': 'bar2', 'foo3': 'bar3'} aname = 'foo' okey = {'alg': 'ECDSA', 'foo2': 'bar2', 'foo1': 'bar1'} self.assertEqual((401, 'urn:ietf:params:acme:error:unauthorized', 'wrong public key'), self.account._key_compare(aname, okey)) - def test_050_account__inner_jws_check(self): + def test_052_account__inner_jws_check(self): """ Account.inner_jws_check() no jwk in inner header""" outer = {} inner = {'foo': 'bar'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'inner jws is missing jwk'), self.account._inner_jws_check(outer, inner)) - def test_051_account__inner_jws_check(self): + def test_053_account__inner_jws_check(self): """ Account.inner_jws_check() no url in inner header """ outer = {'url' : 'url'} inner = {'jwk': 'jwk'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'inner or outer jws is missing url header parameter'), self.account._inner_jws_check(outer, inner)) - def test_052_account__inner_jws_check(self): + def test_054_account__inner_jws_check(self): """ Account.inner_jws_check() no url in outer header """ outer = {'foo' : 'bar'} inner = {'jwk': 'jwk', 'url': 'url'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'inner or outer jws is missing url header parameter'), self.account._inner_jws_check(outer, inner)) - def test_053_account__inner_jws_check(self): + def test_055_account__inner_jws_check(self): """ Account.inner_jws_check() different url string in inner and outer header """ outer = {'url' : 'url_'} inner = {'jwk': 'jwk', 'url': 'url'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'url parameter differ in inner and outer jws'), self.account._inner_jws_check(outer, inner)) - def test_054_account__inner_jws_check(self): + def test_056_account__inner_jws_check(self): """ Account.inner_jws_check() same url string in inner and outer header """ outer = {'url' : 'url'} inner = {'jwk': 'jwk', 'url': 'url'} self.assertEqual((200, None, None), self.account._inner_jws_check(outer, inner)) - def test_055_account__inner_jws_check(self): + def test_057_account__inner_jws_check(self): """ Account.inner_jws_check() nonce in inner header """ outer = {'url' : 'url'} inner = {'jwk': 'jwk', 'url': 'url', 'nonce': 'nonce'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'inner jws must omit nonce header'), self.account._inner_jws_check(outer, inner)) - def test_056_account__inner_jws_check(self): + def test_058_account__inner_jws_check(self): """ Account.inner_jws_check() nonce in inner header and inner_header_nonce_allow True """ outer = {'url' : 'url'} inner = {'jwk': 'jwk', 'url': 'url', 'nonce': 'nonce'} self.account.inner_header_nonce_allow = True self.assertEqual((200, None, None), self.account._inner_jws_check(outer, inner)) - def test_057_account__inner_payload_check(self): + def test_059_account__inner_payload_check(self): """ Account.inner_payload_check() without kid in outer protected """ outer_protected = {} inner_payload = {} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'kid is missing in outer header'), self.account._inner_payload_check('aname', outer_protected, inner_payload)) - def test_058_account__inner_payload_check(self): + def test_060_account__inner_payload_check(self): """ Account.inner_payload_check() with kid in outer protected but without account object in inner_payload """ outer_protected = {'kid': 'kid'} inner_payload = {} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'account object is missing on inner payload'), self.account._inner_payload_check('aname', outer_protected, inner_payload)) - def test_059_account__inner_payload_check(self): + def test_061_account__inner_payload_check(self): """ Account.inner_payload_check() with different kid and account values """ outer_protected = {'kid': 'kid'} inner_payload = {'account': 'account'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'kid and account objects do not match'), self.account._inner_payload_check('aname', outer_protected, inner_payload)) - def test_060_account__inner_payload_check(self): + def test_062_account__inner_payload_check(self): """ Account.inner_payload_check() with same kid and account values but no old_key""" outer_protected = {'kid': 'kid'} inner_payload = {'account': 'kid'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'old key is missing'), self.account._inner_payload_check('aname', outer_protected, inner_payload)) @patch('acme.account.Account._key_compare') - def test_061_account__inner_payload_check(self, mock_cmp): + def test_063_account__inner_payload_check(self, mock_cmp): """ Account.inner_payload_check() with same kid and account values but no old_key""" outer_protected = {'kid': 'kid'} inner_payload = {'account': 'kid', 'oldkey': 'oldkey'} mock_cmp.return_value = ('code', 'message', 'detail') self.assertEqual(('code', 'message', 'detail'), self.account._inner_payload_check('aname', outer_protected, inner_payload)) - def test_062_account__key_change_validate(self): + def test_064_account__key_change_validate(self): """ Account.key_change_validate() without JWK in inner_protected """ inner_protected = {} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'inner jws is missing jwk'), self.account._key_change_validate('aname', {}, inner_protected, {})) @patch('acme.account.Account._lookup') - def test_063_account__key_change_validate(self, mock_lup): + def test_065_account__key_change_validate(self, mock_lup): """ Account.key_change_validate() for existing key """ inner_protected = {'jwk': 'jwk'} mock_lup.return_value = True @@ -531,7 +531,7 @@ def test_063_account__key_change_validate(self, mock_lup): @patch('acme.account.Account._inner_jws_check') @patch('acme.account.Account._lookup') - def test_064_account__key_change_validate(self, mock_lup, mock_jws_chk): + def test_066_account__key_change_validate(self, mock_lup, mock_jws_chk): """ Account.key_change_validate() inner_jws_check returns 400 """ inner_protected = {'jwk': 'jwk'} mock_lup.return_value = False @@ -541,7 +541,7 @@ def test_064_account__key_change_validate(self, mock_lup, mock_jws_chk): @patch('acme.account.Account._inner_payload_check') @patch('acme.account.Account._inner_jws_check') @patch('acme.account.Account._lookup') - def test_065_account__key_change_validate(self, mock_lup, mock_jws_chk, mock_pl_chk): + def test_067_account__key_change_validate(self, mock_lup, mock_jws_chk, mock_pl_chk): """ Account.key_change_validate() inner_jws_check returns 200 """ inner_protected = {'jwk': 'jwk'} mock_lup.return_value = False @@ -549,18 +549,18 @@ def test_065_account__key_change_validate(self, mock_lup, mock_jws_chk, mock_pl_ mock_pl_chk.return_value = ('code2', 'message2', 'detail2') self.assertEqual(('code2', 'message2', 'detail2'), self.account._key_change_validate('aname', {}, inner_protected, {})) - def test_066_account__key_change(self): + def test_068_account__key_change(self): """ Account.key_change() without URL in protected """ protected = {} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'malformed request'), self.account._key_change('aname', {}, protected)) - def test_067_account__key_change(self): + def test_069_account__key_change(self): """ Account.key_change() with URL in protected without key-change in url""" protected = {'url': 'url'} self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'malformed request. not a key-change'), self.account._key_change('aname', {}, protected)) @patch('acme.message.Message.check') - def test_068_account__key_change(self, mock_mcheck): + def test_070_account__key_change(self, mock_mcheck): """ Account.key_change() message.check() returns non-200""" protected = {'url': 'url/key-change'} mock_mcheck.return_value = ('code1', 'message1', 'detail1', 'prot', 'payload', 'aname') @@ -568,7 +568,7 @@ def test_068_account__key_change(self, mock_mcheck): @patch('acme.account.Account._key_change_validate') @patch('acme.message.Message.check') - def test_069_account__key_change(self, mock_mcheck, moch_kchval): + def test_071_account__key_change(self, mock_mcheck, moch_kchval): """ Account.key_change() with URL in protected without key-change in url""" protected = {'url': 'url/key-change'} mock_mcheck.return_value = (200, 'message1', 'detail1', 'prot', 'payload', 'aname') @@ -577,7 +577,7 @@ def test_069_account__key_change(self, mock_mcheck, moch_kchval): @patch('acme.account.Account._key_change_validate') @patch('acme.message.Message.check') - def test_070_account__key_change(self, mock_mcheck, moch_kchval): + def test_072_account__key_change(self, mock_mcheck, moch_kchval): """ Account.key_change() - account_update returns nothing""" protected = {'url': 'url/key-change'} mock_mcheck.return_value = (200, 'message1', 'detail1', {'jwk': {'h1': 'h1a', 'h2': 'h2a', 'h3': 'h3a'}}, 'payload', 'aname') @@ -587,7 +587,7 @@ def test_070_account__key_change(self, mock_mcheck, moch_kchval): @patch('acme.account.Account._key_change_validate') @patch('acme.message.Message.check') - def test_071_account__key_change(self, mock_mcheck, moch_kchval): + def test_073_account__key_change(self, mock_mcheck, moch_kchval): """ Account.key_change() - account_update returns nothing""" protected = {'url': 'url/key-change'} mock_mcheck.return_value = (200, 'message1', 'detail1', {'jwk': {'h1': 'h1a', 'h2': 'h2a', 'h3': 'h3a'}}, 'payload', 'aname') @@ -596,7 +596,7 @@ def test_071_account__key_change(self, mock_mcheck, moch_kchval): self.assertEqual((200, None, None), self.account._key_change('aname', {}, protected)) @patch('acme.account.generate_random_string') - def test_072_account__add(self, mock_name): + def test_074_account__add(self, mock_name): """ test failed account add due to ecc mandated """ # self.account.dbstore.account_add.return_value = (2, True) self.account.ecc_only = True @@ -606,7 +606,7 @@ def test_072_account__add(self, mock_name): self.assertEqual((403, 'urn:ietf:params:acme:error:badPublicKey', 'Only ECC keys are supported'), self.account._add(content, payload, 'foo@example.com')) @patch('acme.account.generate_random_string') - def test_073_account__add(self, mock_name): + def test_075_account__add(self, mock_name): """ test successful account add for a new account""" self.account.dbstore.account_add.return_value = (2, True) self.account.ecc_only = True @@ -616,7 +616,7 @@ def test_073_account__add(self, mock_name): self.assertEqual((201, 'randowm_string', None), self.account._add(content, payload, 'foo@example.com')) @patch('acme.account.generate_random_string') - def test_074_account__add(self, mock_name): + def test_076_account__add(self, mock_name): """ test account add without contact """ self.account.contact_check_disable = True self.account.dbstore.account_add.return_value = ('foo', False) @@ -626,7 +626,7 @@ def test_074_account__add(self, mock_name): self.assertEqual((200, 'foo', None), self.account._add(content, payload, None)) @patch('acme.account.generate_random_string') - def test_075__account__add(self, mock_name): + def test_077__account__add(self, mock_name): """ test successful account add with eab_check False""" self.account.dbstore.account_add.return_value = (2, True) self.account.ecc_only = True @@ -637,7 +637,7 @@ def test_075__account__add(self, mock_name): self.assertEqual((201, 'randowm_string', None), self.account._add(content, payload, 'foo@example.com')) @patch('acme.account.generate_random_string') - def test_076__account__add(self, mock_name): + def test_078__account__add(self, mock_name): """ test successful account add with eab_check True but no binding information - should never happen""" self.account.dbstore.account_add.return_value = (2, True) self.account.ecc_only = True @@ -649,7 +649,7 @@ def test_076__account__add(self, mock_name): @patch('acme.account.Account._eab_kid_get') @patch('acme.account.generate_random_string') - def test_077__account__add(self, mock_name, mock_eabkid): + def test_079__account__add(self, mock_name, mock_eabkid): """ test successful account add with eab_check True but binding information """ self.account.dbstore.account_add.return_value = (2, True) self.account.ecc_only = True @@ -663,7 +663,7 @@ def test_077__account__add(self, mock_name, mock_eabkid): self.assertIn('INFO:test_a2c:add eab_kid: eab_kid to data_dic', lcm.output) @patch('acme.message.Message.check') - def test_078_account_new(self, mock_mcheck): + def test_080_account_new(self, mock_mcheck): """ Account.new() tos required""" mock_mcheck.return_value = (200, None, None, 'protected', {'contact' : [u'mailto: foo@bar.com']}, None) self.account.tos_check_disable = False @@ -676,7 +676,7 @@ def test_078_account_new(self, mock_mcheck): @patch('acme.account.Account._add') @patch('acme.account.Account._contact_check') @patch('acme.message.Message.check') - def test_079_account_new(self, mock_mcheck, mock_contact, mock_aad, mock_nnonce): + def test_081_account_new(self, mock_mcheck, mock_contact, mock_aad, mock_nnonce): """ Account.new() successful tos disabled no tos url configured""" mock_mcheck.return_value = (200, None, None, 'protected', {'contact' : [u'mailto: foo@bar.com']}, None) self.account.tos_check_disable = True @@ -691,7 +691,7 @@ def test_079_account_new(self, mock_mcheck, mock_contact, mock_aad, mock_nnonce) @patch('acme.account.Account._add') @patch('acme.account.Account._contact_check') @patch('acme.message.Message.check') - def test_080_account_new(self, mock_mcheck, mock_contact, mock_aad, mock_nnonce): + def test_082_account_new(self, mock_mcheck, mock_contact, mock_aad, mock_nnonce): """ Account.new() successful tos disabled tos url configured""" mock_mcheck.return_value = (200, None, None, 'protected', {'contact' : [u'mailto: foo@bar.com']}, None) self.account.tos_check_disable = True @@ -706,7 +706,7 @@ def test_080_account_new(self, mock_mcheck, mock_contact, mock_aad, mock_nnonce) @patch('acme.nonce.Nonce.generate_and_add') @patch('acme.account.Account._add') @patch('acme.message.Message.check') - def test_081_account_new(self, mock_mcheck, mock_aad, mock_nnonce): + def test_083_account_new(self, mock_mcheck, mock_aad, mock_nnonce): """ Account.new() successful tos/email checks_disabled""" mock_mcheck.return_value = (200, None, None, 'protected', {}, None) self.account.tos_check_disable = True @@ -721,7 +721,7 @@ def test_081_account_new(self, mock_mcheck, mock_aad, mock_nnonce): @patch('acme.nonce.Nonce.generate_and_add') @patch('acme.account.Account._add') @patch('acme.message.Message.check') - def test_082_account_new(self, mock_mcheck, mock_aad, mock_nnonce, mock_tos): + def test_084_account_new(self, mock_mcheck, mock_aad, mock_nnonce, mock_tos): """ Account.new() successful email checks_disabled""" mock_mcheck.return_value = (200, None, None, 'protected', {}, None) self.account.contact_check_disable = True @@ -769,21 +769,21 @@ def test_086_account_new(self, mock_mcheck, mock_aad, mock_nnonce, mock_tos, moc self.assertEqual(e_result, self.account.new(message)) @patch('acme.message.Message.check') - def test_083_account_new(self, mock_mcheck): + def test_087_account_new(self, mock_mcheck): """ Account.new() tos check skipped as no tos """ mock_mcheck.return_value = (200, None, None, 'protected', 'payload', None) message = {'foo' : 'bar'} e_result = {'code': 400, 'data': {'detail': 'The provided contact URI was invalid: no contacts specified', 'message': 'urn:ietf:params:acme:error:invalidContact', 'status': 400}, 'header': {}} self.assertEqual(e_result, self.account.new(message)) - def test_084_account__lookup(self): + def test_088_account__lookup(self): """ test Account._lookup() if dbstore.account_lookup raises an exception """ self.account.dbstore.account_lookup.side_effect = Exception('exc_acc_lookup') with self.assertLogs('test_a2c', level='INFO') as lcm: self.account._lookup('foo') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Account._lookup(): exc_acc_lookup', lcm.output) - def test_085_account__onlyreturnexisting(self): + def test_089_account__onlyreturnexisting(self): """ test Account._onlyreturnexisting() if dbstore.account_lookup raises an exception """ self.account.dbstore.account_lookup.side_effect = Exception('exc_acc_returnexit') protected = {'jwk' : {'n' : 'foo'}} @@ -793,7 +793,7 @@ def test_085_account__onlyreturnexisting(self): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Account._onlyreturnexisting(): exc_acc_returnexit', lcm.output) self.account.dbstore.account_lookup.side_effect = None - def test_086_account__key_compare(self): + def test_090_account__key_compare(self): """ test Account._key_compare() if dbstore.jwk_load raises an exception """ self.account.dbstore.jwk_load.side_effect = Exception('exc_key_compare') with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -803,7 +803,7 @@ def test_086_account__key_compare(self): @patch('acme.account.Account._key_change_validate') @patch('acme.message.Message.check') - def test_087_account__key_change(self, mock_mcheck, moch_kchval): + def test_091_account__key_change(self, mock_mcheck, moch_kchval): """ Account.key_change() - if dbstore.account_update raises an exception""" protected = {'url': 'url/key-change'} mock_mcheck.return_value = (200, 'message1', 'detail1', {'jwk': {'h1': 'h1a', 'h2': 'h2a', 'h3': 'h3a'}}, 'payload', 'aname') @@ -813,12 +813,12 @@ def test_087_account__key_change(self, mock_mcheck, moch_kchval): self.account._key_change('aname', {}, protected) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Account._key_change(): exc_key_change', lcm.output) - def test_087_account__delete(self): + def test_092_account__delete(self): """ test Account._delete() if dbstore.account_delete ok """ self.account.dbstore.account_delete.return_value = 200 self.assertEqual((200, None, None), self.account._delete('foo')) - def test_088_account__delete(self): + def test_093_account__delete(self): """ test Account._delete() if dbstore.account_delete raises an exception """ self.account.dbstore.account_delete.side_effect = Exception('exc_delete') with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -826,7 +826,7 @@ def test_088_account__delete(self): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Account._delete(): exc_delete', lcm.output) @patch('acme.account.Account._contact_check') - def test_089_account__contacts_update(self, mock_contact_chk,): + def test_094_account__contacts_update(self, mock_contact_chk,): """ Account.contact_update() - if dbstore.account_update raises an exception""" mock_contact_chk.return_value = (200, 'message', 'detail') self.account.dbstore.account_update.side_effect = Exception('exc_contact_upd') @@ -837,7 +837,7 @@ def test_089_account__contacts_update(self, mock_contact_chk,): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Account._contacts_update(): exc_contact_upd', lcm.output) @patch('acme.account.generate_random_string') - def test_090_account__add(self, mock_name): + def test_095_account__add(self, mock_name): """ test account add - if dbstore.account_add raises an exception""" self.account.dbstore.account_add.side_effect = Exception('exc_acc_add') mock_name.return_value = 'randowm_string' @@ -847,49 +847,49 @@ def test_090_account__add(self, mock_name): self.account._add(content, payload, 'foo@example.com') self.assertIn('CRITICAL:test_a2c:Account.account._add(): Database error: exc_acc_add', lcm.output) - def test_091_eab_check(self): + def test_096_eab_check(self): """ test external account binding No payload and no protected """ payload = None protected = None result = (403, 'urn:ietf:params:acme:error:externalAccountRequired', 'external account binding required') self.assertEqual(result, self.account._eab_check(protected, payload)) - def test_092_eab_check(self): + def test_097_eab_check(self): """ test external account binding No payload and but protected """ payload = None protected = 'protected' result = (403, 'urn:ietf:params:acme:error:externalAccountRequired', 'external account binding required') self.assertEqual(result, self.account._eab_check(protected, payload)) - def test_093_eab_check(self): + def test_098_eab_check(self): """ test external account binding payload and but no protected """ payload = 'payload' protected = None result = (403, 'urn:ietf:params:acme:error:externalAccountRequired', 'external account binding required') self.assertEqual(result, self.account._eab_check(protected, payload)) - def test_094_eab_check(self): + def test_099_eab_check(self): """ test external account binding payload and protected """ payload = 'payload' protected = 'protected' result = (403, 'urn:ietf:params:acme:error:externalAccountRequired', 'external account binding required') self.assertEqual(result, self.account._eab_check(protected, payload)) - def test_095_eab_check(self): + def test_100_eab_check(self): """ test external account binding wrong payload """ payload = {'foo': 'bar'} protected = 'protected' result = (403, 'urn:ietf:params:acme:error:externalAccountRequired', 'external account binding required') self.assertEqual(result, self.account._eab_check(protected, payload)) - def test_096_eab_check(self): + def test_101_eab_check(self): """ test external account binding False """ payload = {'externalaccountbinding': False} protected = 'protected' result = (403, 'urn:ietf:params:acme:error:externalAccountRequired', 'external account binding required') self.assertEqual(result, self.account._eab_check(protected, payload)) - def test_097_eab_check(self): + def test_102_eab_check(self): """ test external account binding True but protected in accountbinding structure is missing """ payload = {'externalaccountbinding': {'payload': 'foo'}} protected = 'protected' @@ -899,7 +899,7 @@ def test_097_eab_check(self): self.assertEqual(result, self.account._eab_check(protected, payload)) @patch('acme.account.Account._eab_jwk_compare') - def test_098_eab_check(self, mock_cmp): + def test_103_eab_check(self, mock_cmp): """ test external account binding False """ payload = {'externalaccountbinding': {'payload': 'payload', 'protected': 'protected'}} protected = 'protected' @@ -911,7 +911,7 @@ def test_098_eab_check(self, mock_cmp): @patch('acme.account.Account._eab_kid_get') @patch('acme.account.Account._eab_jwk_compare') - def test_099_eab_check(self, mock_cmp, mock_kget): + def test_104_eab_check(self, mock_cmp, mock_kget): """ test external _eab_kid_get returns None """ payload = {'externalaccountbinding': {'payload': 'payload', 'protected': 'protected'}} protected = 'protected' @@ -924,7 +924,7 @@ def test_099_eab_check(self, mock_cmp, mock_kget): @patch('acme.account.Account._eab_kid_get') @patch('acme.account.Account._eab_jwk_compare') - def test_100_eab_check(self, mock_cmp, mock_kget): + def test_105_eab_check(self, mock_cmp, mock_kget): """ test external _eab_kid_get returns value but mac lookup failed """ payload = {'externalaccountbinding': {'payload': 'payload', 'protected': 'protected'}} protected = 'protected' @@ -939,7 +939,7 @@ def test_100_eab_check(self, mock_cmp, mock_kget): @patch('acme.account.Account._eab_signature_verify') @patch('acme.account.Account._eab_kid_get') @patch('acme.account.Account._eab_jwk_compare') - def test_101_eab_check(self, mock_cmp, mock_kget, mock_sigvrf): + def test_106_eab_check(self, mock_cmp, mock_kget, mock_sigvrf): """ test external _eab_kid_get returns value but mac lookup successful sig verification failed""" payload = {'externalaccountbinding': {'payload': 'payload', 'protected': 'protected'}} protected = 'protected' @@ -955,7 +955,7 @@ def test_101_eab_check(self, mock_cmp, mock_kget, mock_sigvrf): @patch('acme.account.Account._eab_signature_verify') @patch('acme.account.Account._eab_kid_get') @patch('acme.account.Account._eab_jwk_compare') - def test_102_eab_check(self, mock_cmp, mock_kget, mock_sigvrf): + def test_107_eab_check(self, mock_cmp, mock_kget, mock_sigvrf): """ test external _eab_kid_get returns value but mac lookup successful sig verification failed""" payload = {'externalaccountbinding': {'payload': 'payload', 'protected': 'protected'}} protected = 'protected' @@ -969,7 +969,7 @@ def test_102_eab_check(self, mock_cmp, mock_kget, mock_sigvrf): self.assertEqual(result, self.account._eab_check(protected, payload)) @patch('acme.account.load_config') - def test_103_config_load(self, mock_load_cfg): + def test_108_config_load(self, mock_load_cfg): """ test _config_load empty config """ parser = configparser.ConfigParser() # parser['Account'] = {'foo': 'bar'} @@ -982,7 +982,7 @@ def test_103_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_104_config_load(self, mock_load_cfg): + def test_109_config_load(self, mock_load_cfg): """ test _config_load account with unknown values """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar'} @@ -995,7 +995,7 @@ def test_104_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_105_config_load(self, mock_load_cfg): + def test_110_config_load(self, mock_load_cfg): """ test _config_load account with inner_header_nonce_allow False """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'inner_header_nonce_allow': False} @@ -1008,7 +1008,7 @@ def test_105_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_106_config_load(self, mock_load_cfg): + def test_111_config_load(self, mock_load_cfg): """ test _config_load account with inner_header_nonce_allow True """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'inner_header_nonce_allow': True} @@ -1021,7 +1021,7 @@ def test_106_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_107_config_load(self, mock_load_cfg): + def test_112_config_load(self, mock_load_cfg): """ test _config_load account with ecc_only False """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'ecc_only': False} @@ -1034,7 +1034,7 @@ def test_107_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_108_config_load(self, mock_load_cfg): + def test_113_config_load(self, mock_load_cfg): """ test _config_load account with ecc_only True """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'ecc_only': True} @@ -1047,7 +1047,7 @@ def test_108_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_109_config_load(self, mock_load_cfg): + def test_114_config_load(self, mock_load_cfg): """ test _config_load account with tos_check_disable False """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'tos_check_disable': False} @@ -1060,7 +1060,7 @@ def test_109_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_110_config_load(self, mock_load_cfg): + def test_115_config_load(self, mock_load_cfg): """ test _config_load account with tos_check_disable True """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'tos_check_disable': True} @@ -1073,7 +1073,7 @@ def test_110_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_111_config_load(self, mock_load_cfg): + def test_116_config_load(self, mock_load_cfg): """ test _config_load account with contact_check_disable False """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'contact_check_disable': False} @@ -1086,7 +1086,7 @@ def test_111_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_112_config_load(self, mock_load_cfg): + def test_117_config_load(self, mock_load_cfg): """ test _config_load account with contact_check_disable True """ parser = configparser.ConfigParser() parser['Account'] = {'foo': 'bar', 'contact_check_disable': True} @@ -1099,7 +1099,7 @@ def test_112_config_load(self, mock_load_cfg): self.assertFalse(self.account.eab_check) @patch('acme.account.load_config') - def test_113_config_load(self, mock_load_cfg): + def test_118_config_load(self, mock_load_cfg): """ test _config_load account with contact_check_disable True """ parser = configparser.ConfigParser() parser['EABhandler'] = {'foo': 'bar', 'eab_handler_file': 'foo'} @@ -1117,7 +1117,7 @@ def test_113_config_load(self, mock_load_cfg): @patch('importlib.import_module') @patch('acme.account.load_config') - def test_116_config_load(self, mock_load_cfg, mock_imp): + def test_119_config_load(self, mock_load_cfg, mock_imp): """ test _config_load account with contact_check_disable True """ parser = configparser.ConfigParser() parser['EABhandler'] = {'foo': 'bar', 'eab_handler_file': 'foo'} @@ -1132,7 +1132,7 @@ def test_116_config_load(self, mock_load_cfg, mock_imp): self.assertTrue(self.account.eab_handler) @patch('acme.account.load_config') - def test_114_config_load(self, mock_load_cfg): + def test_120_config_load(self, mock_load_cfg): """ test _config_load account with tos url check """ parser = configparser.ConfigParser() parser['Directory'] = {'foo': 'bar'} @@ -1146,7 +1146,7 @@ def test_114_config_load(self, mock_load_cfg): self.assertFalse(self.account.tos_url) @patch('acme.account.load_config') - def test_115_config_load(self, mock_load_cfg): + def test_121_config_load(self, mock_load_cfg): """ test _config_load account with tos url configured """ parser = configparser.ConfigParser() parser['Directory'] = {'foo': 'bar', 'tos_url': 'tos_url'} @@ -1160,79 +1160,79 @@ def test_115_config_load(self, mock_load_cfg): self.assertEqual('tos_url', self.account.tos_url) @patch('json.loads') - def test_116_eab_kid_get(self, mock_json): + def test_122_eab_kid_get(self, mock_json): """ tes eab_kid all ok """ mock_json.return_value = {'kid': 'foo'} self.assertEqual('foo', self.account._eab_kid_get('Zm9vYmFyMjM')) @patch('json.loads') - def test_117_eab_kid_get(self, mock_json): + def test_123_eab_kid_get(self, mock_json): """ json does not have a kid key """ mock_json.return_value = {'foo': 'bar'} self.assertFalse(self.account._eab_kid_get('Zm9vYmFyMjM')) @patch('json.loads') - def test_118_eab_kid_get(self, mock_json): + def test_124_eab_kid_get(self, mock_json): """ json is empty """ mock_json.return_value = {} self.assertFalse(self.account._eab_kid_get('Zm9vYmFyMjM')) @patch('json.loads') - def test_119_eab_kid_get(self, mock_json): + def test_125_eab_kid_get(self, mock_json): """ json returns a string """ mock_json.return_value = 'nonjson' self.assertFalse(self.account._eab_kid_get('Zm9vYmFyMjM')) - def test_120__eab_jwk_compare(self): + def test_126__eab_jwk_compare(self): """ jwk inner ok """ protected = {'jwk': 'foobar'} payload = 'ImZvb2JhciI=' self.assertTrue(self.account._eab_jwk_compare(protected, payload)) - def test_121__eab_jwk_compare(self): + def test_127__eab_jwk_compare(self): """ jwk inner ok no padding """ protected = {'jwk': 'foobar'} payload = 'ImZvb2JhciI' self.assertTrue(self.account._eab_jwk_compare(protected, payload)) - def test_122__eab_jwk_compare(self): + def test_128__eab_jwk_compare(self): """ jwk inner payload does not match """ protected = {'jwk': 'foobar'} payload = 'ImZvb2Ii' self.assertFalse(self.account._eab_jwk_compare(protected, payload)) - def test_123__eab_jwk_compare(self): + def test_129__eab_jwk_compare(self): """ no jwk in protected """ protected = {'foo': 'bar'} payload = 'Zm9vYg' self.assertFalse(self.account._eab_jwk_compare(protected, payload)) - def test_124__eab_jwk_compare(self): + def test_130__eab_jwk_compare(self): """ protected is a string """ protected = 'protected' payload = 'Zm9vYg' self.assertFalse(self.account._eab_jwk_compare(protected, payload)) - def test_125__eab_jwk_compare(self): + def test_131__eab_jwk_compare(self): """ protected is a string containg jwk """ protected = 'protected-jwk' payload = 'Zm9vYg' self.assertFalse(self.account._eab_jwk_compare(protected, payload)) - def test_126__eab_signature_verify(self): + def test_132__eab_signature_verify(self): """ content and mac_key are missing """ content = None mac_key = None self.assertEqual((False, None), self.account._eab_signature_verify(content, mac_key)) - def test_127__eab_signature_verify(self): + def test_133__eab_signature_verify(self): """ mac_key is issing """ content = 'content' mac_key = None self.assertEqual((False, None), self.account._eab_signature_verify(content, mac_key)) @patch('acme.signature.Signature.eab_check') - def test_128__eab_signature_verify(self, mock_eabchk): + def test_134__eab_signature_verify(self, mock_eabchk): """ result and error returned """ content = 'content' mac_key = 'mac_key' @@ -1240,7 +1240,7 @@ def test_128__eab_signature_verify(self, mock_eabchk): self.assertEqual(('foo', 'bar'), self.account._eab_signature_verify(content, mac_key)) @patch('acme.signature.Signature.eab_check') - def test_129__eab_signature_verify(self, mock_eabchk): + def test_135__eab_signature_verify(self, mock_eabchk): """ result and no error returned """ content = 'content' mac_key = 'mac_key' @@ -1248,7 +1248,7 @@ def test_129__eab_signature_verify(self, mock_eabchk): self.assertEqual((True, None), self.account._eab_signature_verify(content, mac_key)) @patch('acme.signature.Signature.eab_check') - def test_130__eab_signature_verify(self, mock_eabchk): + def test_136__eab_signature_verify(self, mock_eabchk): """ result and no error returned """ content = 'content' mac_key = 'mac_key' @@ -1256,7 +1256,7 @@ def test_130__eab_signature_verify(self, mock_eabchk): self.assertEqual((False, 'error'), self.account._eab_signature_verify(content, mac_key)) @patch('acme.account.Account._config_load') - def test_0131__enter__(self, mock_cfg): + def test_137__enter__(self, mock_cfg): """ test enter """ mock_cfg.return_value = True self.account.__enter__() diff --git a/test/test_authorization.py b/test/test_authorization.py index 32913d00..4c601172 100644 --- a/test/test_authorization.py +++ b/test/test_authorization.py @@ -171,7 +171,7 @@ def test_015_authorization__authz_info(self, mock_name, mock_uts, mock_challenge @patch('acme.challenge.Challenge.new_set') @patch('acme.authorization.uts_now') @patch('acme.authorization.generate_random_string') - def test_015_authorization__authz_info(self, mock_name, mock_uts, mock_challengeset): + def test_016_authorization__authz_info(self, mock_name, mock_uts, mock_challengeset): """ test Authorization.auth_info() - dbstore.authorization lookup raises an exception """ mock_name.return_value = 'randowm_string' mock_uts.return_value = 1543640400 @@ -183,14 +183,14 @@ def test_015_authorization__authz_info(self, mock_name, mock_uts, mock_challenge self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_authz_update', lcm.output) @patch('acme.authorization.Authorization._config_load') - def test_016__enter__(self, mock_cfg): + def test_017__enter__(self, mock_cfg): """ test enter """ mock_cfg.return_value = True self.authorization.__enter__() self.assertTrue(mock_cfg.called) @patch('acme.authorization.load_config') - def test_017_config_load(self, mock_load_cfg): + def test_018_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() mock_load_cfg.return_value = parser @@ -199,7 +199,7 @@ def test_017_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_018_config_load(self, mock_load_cfg): + def test_019_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'foo': 'bar'} @@ -209,7 +209,7 @@ def test_018_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_019_config_load(self, mock_load_cfg): + def test_020_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'expiry_check_disable': False} @@ -219,7 +219,7 @@ def test_019_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_020_config_load(self, mock_load_cfg): + def test_021_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'expiry_check_disable': True} @@ -229,7 +229,7 @@ def test_020_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_021_config_load(self, mock_load_cfg): + def test_022_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'validity': 60} @@ -239,7 +239,7 @@ def test_021_config_load(self, mock_load_cfg): self.assertEqual(60, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_022_config_load(self, mock_load_cfg): + def test_023_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'validity': 'foo'} @@ -251,7 +251,7 @@ def test_022_config_load(self, mock_load_cfg): self.assertIn('WARNING:test_a2c:Authorization._config_load(): failed to parse validity: foo', lcm.output) @patch('acme.authorization.Authorization._authz_info') - def test_023_new_get(self, mock_info): + def test_024_new_get(self, mock_info): """ new get """ mock_info.return_value = 'foo' result = {'code': 200, 'data': 'foo', 'header': {}} diff --git a/test/test_certifier_handler.py b/test/test_certifier_handler.py index e660712a..db3a7a14 100644 --- a/test/test_certifier_handler.py +++ b/test/test_certifier_handler.py @@ -173,14 +173,14 @@ def test_013_config_load(self, mock_load_cfg): self.assertEqual('ca_name', self.cahandler.ca_name) self.assertEqual(120, self.cahandler.polling_timeout) - def test_011_auth_set(self): + def test_014_auth_set(self): """ test _auth_set """ self.cahandler.api_user = 'api_user' self.cahandler.api_password = 'api_password' self.cahandler._auth_set() self.assertTrue(self.cahandler.auth) - def test_012_auth_set(self): + def test_015_auth_set(self): """ test _auth_set without api_user """ self.cahandler.api_user = None self.cahandler.api_password = 'api_password' @@ -189,7 +189,7 @@ def test_012_auth_set(self): self.assertFalse(self.cahandler.auth) self.assertIn('ERROR:test_a2c:CAhandler._auth_set(): auth information incomplete. Either "api_user" or "api_password" parameter is missing in config file', lcm.output) - def test_013_auth_set(self): + def test_016_auth_set(self): """ test _auth_set without api_user """ self.cahandler.api_user = 'api_user' self.cahandler.api_password = None @@ -199,7 +199,7 @@ def test_013_auth_set(self): self.assertIn('ERROR:test_a2c:CAhandler._auth_set(): auth information incomplete. Either "api_user" or "api_password" parameter is missing in config file', lcm.output) @patch.object(requests, 'post') - def test_014__api_post(self, mock_req): + def test_017__api_post(self, mock_req): """ test _api_post successful run """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -207,7 +207,7 @@ def test_014__api_post(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._api_post('url', 'data')) @patch('requests.post') - def test_015__api_post(self, mock_post): + def test_018__api_post(self, mock_post): """ CAhandler.get_ca() returns an http error """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -217,7 +217,7 @@ def test_015__api_post(self, mock_post): self.assertIn('ERROR:test_a2c:CAhandler._api_post() returned error: exc_api_post', lcm.output) @patch.object(requests, 'get') - def test_016__ca_get(self, mock_req): + def test_019__ca_get(self, mock_req): """ test _ca_get successful run """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -226,7 +226,7 @@ def test_016__ca_get(self, mock_req): mockresponse.json = lambda: {'foo': 'bar'} self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get()) - def test_017__api_post(self): + def test_020__api_post(self): """ test _ca_get no api_host""" self.cahandler.auth = 'auth' with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -234,7 +234,7 @@ def test_017__api_post(self): self.assertIn('ERROR:test_a2c:CAhandler._ca_get(): api_host is misisng in configuration', lcm.output) @patch.object(requests, 'get') - def test_018__ca_get(self, mock_req): + def test_021__ca_get(self, mock_req): """ test _ca_get auth none """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -243,7 +243,7 @@ def test_018__ca_get(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get()) @patch('requests.get') - def test_019__api_post(self, mock_get): + def test_022__api_post(self, mock_get): """ CAhandler.get_ca() returns an http error """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -253,62 +253,62 @@ def test_019__api_post(self, mock_get): self.assertIn('ERROR:test_a2c:CAhandler._ca_get() returned error: exc_ca_get', lcm.output) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_020__ca_get_properties(self, mock_caget): + def test_023__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns nothing """ mock_caget.return_value = [] self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_021__ca_get_properties(self, mock_caget): + def test_024__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns wrong information """ mock_caget.return_value = 'foo' self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_022__ca_get_properties(self, mock_caget): + def test_025__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns error message """ mock_caget.return_value = {'status': 'status', 'message': 'message'} self.assertEqual({'message': 'message', 'status': 'status'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_023__ca_get_properties(self, mock_caget): + def test_026__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns empty ca_list """ mock_caget.return_value = {'cas': None} self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_024__ca_get_properties(self, mock_caget): + def test_027__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list but filter does not match """ mock_caget.return_value = {'cas': [{'foo': 'bar'}]} self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_025__ca_get_properties(self, mock_caget): + def test_028__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list but filter matches """ mock_caget.return_value = {'cas': [{'foo': 'bar'}, {'filterkey': 'filtervalue'}, {'foo1': 'bar1'}]} self.assertEqual({'filterkey': 'filtervalue'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_026__ca_get_properties(self, mock_caget): + def test_029__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list another filterkey """ mock_caget.return_value = {'cas': [{'foo': 'bar'}, {'filterkey': 'filtervalue'}, {'foo1': 'bar1'}]} self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get_properties('foo', 'bar')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_027__ca_get_properties(self, mock_caget): + def test_030__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list filterkey check first match""" mock_caget.return_value = {'cas': [{'foo': 'bar_bogus'}, {'foo': 'bar'}, {'foo': 'bar1'}, {'foo': 'bar2'}]} self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get_properties('foo', 'bar')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_028__cert_get(self, mock_caget): + def test_031__cert_get(self, mock_caget): """ CAhandler._ca_get_properties() _ca_get_properties returns empty dic """ mock_caget.return_value = {} self.assertEqual({}, self.cahandler._cert_get('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._api_post') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_020__cert_get(self, mock_caget, mock_post): + def test_032__cert_get(self, mock_caget, mock_post): """ CAhandler._ca_get_properties() _ca_get_properties does returns "href" key """ self.cahandler.api_host = 'api_host' mock_caget.return_value = {'href': 'href'} @@ -317,7 +317,7 @@ def test_020__cert_get(self, mock_caget, mock_post): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._api_post') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_030__cert_get(self, mock_caget, mock_post): + def test_033__cert_get(self, mock_caget, mock_post): """ CAhandler._ca_get_properties() _ca_get_properties returns "href" key but cert_dic is empty """ self.cahandler.api_host = 'api_host' mock_caget.return_value = {'href': 'href'} @@ -325,7 +325,7 @@ def test_030__cert_get(self, mock_caget, mock_post): self.assertEqual({'href': 'href'}, self.cahandler._cert_get('csr')) @patch('requests.get') - def test_031__cert_get_properties(self, mock_req): + def test_034__cert_get_properties(self, mock_req): """ CAhandler._cert_get_properties() all good """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -335,7 +335,7 @@ def test_031__cert_get_properties(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._cert_get_properties('serial', 'link')) @patch('requests.get') - def test_032__cert_get_properties(self, mock_get): + def test_035__cert_get_properties(self, mock_get): """ CAhandler._cert_get_properties() all good """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -344,23 +344,23 @@ def test_032__cert_get_properties(self, mock_get): self.assertEqual({'status': 500, 'message': 'exc_api_get', 'statusMessage': 'Internal Server Error'}, self.cahandler._cert_get_properties('serial', 'link')) self.assertIn('ERROR:test_a2c:CAhandler._cert_get_properties() returned error: exc_api_get', lcm.output) - def test_033_poll(self): + def test_036_poll(self): """ CAhandler.poll() poll_identifier is none """ self.assertEqual((None, None, None, None, False), self.cahandler.poll('cert_name', None, 'csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._request_poll') - def test_034_poll(self, mock_poll): + def test_037_poll(self, mock_poll): """ CAhandler.poll() poll_identifier is none """ mock_poll.return_value = ('error', 'cert_bundle', 'cert_raw', 'poll_identifier', 'rejected') self.assertEqual(('error', 'cert_bundle', 'cert_raw', 'poll_identifier', 'rejected'), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) - def test_035__loop_poll(self): + def test_038__loop_poll(self): """ CAhandler._loop_poll() - no request url""" request_url = None self.assertEqual((None, None, None, None), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_036__loop_poll(self, mock_get): + def test_039__loop_poll(self, mock_get): """ CAhandler._loop_poll() - nothing come back from request get""" self.cahandler.polling_timeout = 5 self.cahandler.timeout = 0 @@ -371,7 +371,7 @@ def test_036__loop_poll(self, mock_get): self.assertEqual((None, None, None, 'request_url'), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_037__loop_poll(self, mock_get): + def test_040__loop_poll(self, mock_get): """ CAhandler._loop_poll() - no status returned from request get""" self.cahandler.polling_timeout = 5 self.cahandler.timeout = 0 @@ -382,7 +382,7 @@ def test_037__loop_poll(self, mock_get): self.assertEqual((None, None, None, 'request_url'), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_038__loop_poll(self, mock_get): + def test_041__loop_poll(self, mock_get): """ CAhandler._loop_poll() - status "rejected" returned from request get""" self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -393,7 +393,7 @@ def test_038__loop_poll(self, mock_get): self.assertEqual(('Request rejected by operator', None, None, None), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_039__loop_poll(self, mock_get): + def test_042__loop_poll(self, mock_get): """ CAhandler._loop_poll() - status "accepted" returned from request get but no certificate in""" self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -404,7 +404,7 @@ def test_039__loop_poll(self, mock_get): self.assertEqual(('Request accepted but no certificate returned', None, None, 'request_url'), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_040__loop_poll(self, mock_get): + def test_043__loop_poll(self, mock_get): """ CAhandler._loop_poll() - status "accepted" returned from request "certifiate" in but no "certificateBase64" in 2dn request """ self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -416,7 +416,7 @@ def test_040__loop_poll(self, mock_get): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._pem_cert_chain_generate') @patch('requests.get') - def test_041__loop_poll(self, mock_get, mock_chain): + def test_044__loop_poll(self, mock_get, mock_chain): """ CAhandler._loop_poll() - status "accepted" returned from request "certifiate" in but no "certificateBase64" in 2dn request """ self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -428,32 +428,32 @@ def test_041__loop_poll(self, mock_get, mock_chain): self.assertEqual((None, 'foo', 'certificateBase64', None), self.cahandler._loop_poll(request_url)) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_042_enroll(self, mock_certget): + def test_045_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns None """ mock_certget.return_value = {} self.assertEqual(('internal error', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_043_enroll(self, mock_certget): + def test_046_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns wrong information """ mock_certget.return_value = {'foo': 'bar'} self.assertEqual(('no certificate information found', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_044_enroll(self, mock_certget): + def test_047_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns status without error message """ mock_certget.return_value = {'foo': 'bar', 'status': 'foo'} self.assertEqual(('unknown errror', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_045_enroll(self, mock_certget): + def test_048_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns status with error message """ mock_certget.return_value = {'foo': 'bar', 'status': 'foo', 'message': 'message'} self.assertEqual(('message', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._pem_cert_chain_generate') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_046_enroll(self, mock_certget, mock_chain): + def test_049_enroll(self, mock_certget, mock_chain): """ CAhandler.enroll() _cert_get returns certb64 """ mock_certget.return_value = {'foo': 'bar', 'certificateBase64': 'certificateBase64'} mock_chain.return_value = 'mock_chain' @@ -461,27 +461,27 @@ def test_046_enroll(self, mock_certget, mock_chain): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._loop_poll') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_047_enroll(self, mock_certget, mock_loop): + def test_050_enroll(self, mock_certget, mock_loop): """ CAhandler.enroll() _cert_get returns certb64 """ mock_certget.return_value = {'foo': 'bar', 'href': 'href'} mock_loop.return_value = ('error', 'cert_bundle', 'cert_raw', 'poll_identifier') self.assertEqual(('error', 'cert_bundle', 'cert_raw', 'poll_identifier'), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_048_revoke(self, mock_getca): + def test_051_revoke(self, mock_getca): """ CAhandler.revoke() _ca_get_properties returns nothing """ mock_getca.return_value = {} self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'CA could not be found'), self.cahandler.revoke('cert')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_049_revoke(self, mock_getca): + def test_052_revoke(self, mock_getca): """ CAhandler.revoke() _ca_get_properties returns wrong information """ mock_getca.return_value = {'foo': 'bar'} self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'CA could not be found'), self.cahandler.revoke('cert')) @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_050_revoke(self, mock_getca, mock_serial): + def test_053_revoke(self, mock_getca, mock_serial): """ CAhandler.revoke() _ca_get_properties cert_serial_get failed """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = None @@ -490,7 +490,7 @@ def test_050_revoke(self, mock_getca, mock_serial): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_051_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_054_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties failed """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -500,7 +500,7 @@ def test_051_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_052_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_055_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns wrong information """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -510,7 +510,7 @@ def test_052_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_053_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_056_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties empty cert_list """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -520,7 +520,7 @@ def test_053_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_054_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_057_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns cert_list with wrong information """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -531,7 +531,7 @@ def test_054_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_055_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): + def test_058_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns cert_list revocation successful """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -543,7 +543,7 @@ def test_055_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_056_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): + def test_059_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns href. revocation returns status without message """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -555,7 +555,7 @@ def test_056_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_057_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): + def test_060_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns href. revocation returns status with message """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -563,7 +563,7 @@ def test_057_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): mock_post.return_value = {'foo': 'bar', 'status': 'status', 'message': 'message'} self.assertEqual((400, 'urn:ietf:params:acme:error:alreadyRevoked', 'message'), self.cahandler.revoke('cert')) - def test_058_trigger(self): + def test_061_trigger(self): """ CAhandler.trigger() - no payload given """ payload = None self.assertEqual(('No payload given', None, None), self.cahandler.trigger(payload)) @@ -572,7 +572,7 @@ def test_058_trigger(self): @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_059_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop): + def test_062_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop): """ CAhandler.trigger() - payload but ca_lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -585,7 +585,7 @@ def test_059_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop): @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_060_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial): + def test_063_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -600,7 +600,7 @@ def test_060_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_061_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop): + def test_064_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -617,7 +617,7 @@ def test_061_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_062_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): + def test_065_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -635,7 +635,7 @@ def test_062_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_063_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): + def test_066_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -646,23 +646,23 @@ def test_063_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock mock_chain.return_value = 'chain' self.assertEqual((None, 'chain', 'foodecode'), self.cahandler.trigger(payload)) - def test_064__pem_cert_chain_generate(self): + def test_067__pem_cert_chain_generate(self): """ _pem_cert_chain_generate - empty cert_dic """ cert_dic = {} self.assertFalse(self.cahandler._pem_cert_chain_generate(cert_dic)) - def test_065__pem_cert_chain_generate(self): + def test_068__pem_cert_chain_generate(self): """ _pem_cert_chain_generate - wrong dic """ cert_dic = {'foo': 'bar'} self.assertFalse(self.cahandler._pem_cert_chain_generate(cert_dic)) - def test_066__pem_cert_chain_generate(self): + def test_069__pem_cert_chain_generate(self): """ _pem_cert_chain_generate - certificateBase64 in dict """ cert_dic = {'certificateBase64': 'certificateBase64'} self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase64\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_067__pem_cert_chain_generate(self, mock_get): + def test_070__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - issuer in dict without certificateBase64 """ cert_dic = {'issuer': 'issuer'} mockresponse = Mock() @@ -671,7 +671,7 @@ def test_067__pem_cert_chain_generate(self, mock_get): self.assertFalse(self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_068__pem_cert_chain_generate(self, mock_get): + def test_071__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns "certificates" but no active """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -682,7 +682,7 @@ def test_068__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_069__pem_cert_chain_generate(self, mock_get): + def test_072__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns certificate and active, 2nd request is bogus """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -693,7 +693,7 @@ def test_069__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_070__pem_cert_chain_generate(self, mock_get): + def test_073__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns certificate two certs """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -706,7 +706,7 @@ def test_070__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\ncertificateBase642\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_071__pem_cert_chain_generate(self, mock_get): + def test_074__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns certificate three certs """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -723,7 +723,7 @@ def test_071__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\ncertificateBase642\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\ncertificateBase643\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_072__pem_cert_chain_generate(self, mock_get): + def test_075__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - issuerCa in """ cert_dic = {'issuerCa': 'issuerCa', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -733,12 +733,12 @@ def test_072__pem_cert_chain_generate(self, mock_get): mock_get.side_effect = [mockresponse1, mockresponse2] self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) - def test_066__enter__(self): + def test_076__enter__(self): """ test __enter__ """ self.cahandler.__enter__() @patch('requests.get') - def test_074_request_poll(self, mock_get): + def test_077_request_poll(self, mock_get): """ test request poll request returned exception """ mock_get.side_effect = Exception('exc_api_get') result = ('"status" field not found in response.', None, None, 'url', False) @@ -747,7 +747,7 @@ def test_074_request_poll(self, mock_get): self.assertIn('ERROR:test_a2c:CAhandler._request.poll() returned: exc_api_get', lcm.output) @patch('requests.get') - def test_075_request_poll(self, mock_get): + def test_078_request_poll(self, mock_get): """ test request poll request returned unknown status """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'unknown'} @@ -756,7 +756,7 @@ def test_075_request_poll(self, mock_get): self.assertEqual(result, self.cahandler._request_poll('url')) @patch('requests.get') - def test_076_request_poll(self, mock_get): + def test_079_request_poll(self, mock_get): """ test request poll request returned status rejected """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'rejected'} @@ -765,7 +765,7 @@ def test_076_request_poll(self, mock_get): self.assertEqual(result, self.cahandler._request_poll('url')) @patch('requests.get') - def test_077_request_poll(self, mock_get): + def test_080_request_poll(self, mock_get): """ test request poll request returned status accepted but no certinformation in """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'accepted', 'foo': 'bar'} @@ -774,7 +774,7 @@ def test_077_request_poll(self, mock_get): self.assertEqual(result, self.cahandler._request_poll('url')) @patch('requests.get') - def test_077_request_poll(self, mock_get): + def test_081_request_poll(self, mock_get): """ test request poll request returned status accepted but no certinformation in """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'accepted', 'certificate': 'certificate'} @@ -784,7 +784,7 @@ def test_077_request_poll(self, mock_get): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._pem_cert_chain_generate') @patch('requests.get') - def test_078_request_poll(self, mock_get, mock_pemgen): + def test_082_request_poll(self, mock_get, mock_pemgen): """ test request poll request returned status accepted but no certinformation in """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'accepted', 'certificate': 'certificate', 'certificateBase64': 'certificateBase64'} diff --git a/test/test_message.py b/test/test_message.py index 191e69cd..88635e0e 100644 --- a/test/test_message.py +++ b/test/test_message.py @@ -4,6 +4,7 @@ # pylint: disable=C0302, C0415, R0904, R0913, R0914, R0915, W0212 import unittest import sys +import configparser from unittest.mock import patch, MagicMock sys.path.insert(0, '.') @@ -91,7 +92,27 @@ def test_006_message_check(self, mock_decode, mock_nonce_check, mock_aname, mock mock_aname.return_value = 'account_name' mock_sig.return_value = (True, None, None) message = '{"foo" : "bar"}' - self.assertEqual((200, None, None, 'protected', 'payload', 'account_name'), self.message.check(message, skip_nonce_check=True)) + self.message.disable_dic = {'nonce_check_disable': True, 'signature_check_disable': False} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((200, None, None, 'protected', 'payload', 'account_name'), self.message.check(message, skip_nonce_check=True)) + self.assertIn('ERROR:test_a2c:**** NONCE CHECK DISABLED!!! Severe security issue ****', lcm.output) + + @patch('acme.signature.Signature.check') + @patch('acme.message.Message._name_get') + @patch('acme.nonce.Nonce.check') + @patch('acme.message.decode_message') + def test_026_message_check(self, mock_decode, mock_nonce_check, mock_aname, mock_sig): + """ message check successful as nonce check is disabled """ + mock_decode.return_value = (True, None, 'protected', 'payload', 'signature') + mock_nonce_check.return_value = (400, 'badnonce', None) + mock_aname.return_value = 'account_name' + mock_sig.return_value = (True, None, None) + message = '{"foo" : "bar"}' + self.message.disable_dic = {'nonce_check_disable': True, 'signature_check_disable': True} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((200, None, None, 'protected', 'payload', None), self.message.check(message, skip_nonce_check=True)) + self.assertIn('ERROR:test_a2c:**** SIGNATURE_CHECK_DISABLE!!! Severe security issue ****', lcm.output) + self.assertIn('ERROR:test_a2c:**** NONCE CHECK DISABLED!!! Severe security issue ****', lcm.output) @patch('acme.nonce.Nonce.generate_and_add') def test_007_message_prepare_response(self, mock_nnonce): @@ -208,5 +229,50 @@ def test_023_message__name_get(self): self.message._name_get(protected) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Message._name_get(): exc_mess__name_get', lcm.output) + def test_024__enter__(self): + """ test enter """ + self.message.__enter__() + + @patch('acme.message.load_config') + def test_025_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + # parser['Account'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + self.message._config_load() + self.assertFalse(self.message.disable_dic['nonce_check_disable']) + self.assertFalse(self.message.disable_dic['signature_check_disable']) + + @patch('acme.message.load_config') + def test_026_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Nonce'] = {'nonce_check_disable': False, 'signature_check_disable': False} + mock_load_cfg.return_value = parser + self.message._config_load() + self.assertFalse(self.message.disable_dic['nonce_check_disable']) + self.assertFalse(self.message.disable_dic['signature_check_disable']) + + @patch('acme.message.load_config') + def test_027_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Nonce'] = {'nonce_check_disable': True, 'signature_check_disable': False} + mock_load_cfg.return_value = parser + self.message._config_load() + self.assertTrue(self.message.disable_dic['nonce_check_disable']) + self.assertFalse(self.message.disable_dic['signature_check_disable']) + + @patch('acme.message.load_config') + def test_028_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Nonce'] = {'nonce_check_disable': False, 'signature_check_disable': True} + mock_load_cfg.return_value = parser + self.message._config_load() + self.assertFalse(self.message.disable_dic['nonce_check_disable']) + self.assertTrue(self.message.disable_dic['signature_check_disable']) + + if __name__ == '__main__': unittest.main() From edff5be018c8d9ef0b33ce1a81151ec89eef6217 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 15 May 2021 15:42:01 +0200 Subject: [PATCH 07/51] [wf] django_mariadb tests --- .github/django_settings_mariadb.py | 130 ++++++++++++++++++++++++++++ .github/workflows/django_tests..yml | 102 ++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 .github/django_settings_mariadb.py create mode 100644 .github/workflows/django_tests..yml diff --git a/.github/django_settings_mariadb.py b/.github/django_settings_mariadb.py new file mode 100644 index 00000000..1ee48294 --- /dev/null +++ b/.github/django_settings_mariadb.py @@ -0,0 +1,130 @@ +""" +Django settings for acme2certifier project. + +Generated by 'django-admin startproject' using Django 1.11.15. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False + +ALLOWED_HOSTS = ['127.0.0.1','*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'acme' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + # 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'acme2certifier.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'acme2certifier.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + #'default': { + # 'ENGINE': 'django.db.backends.sqlite3', + # 'NAME': os.path.join(BASE_DIR, '/var/www/acme2certifier/volume/db.sqlite3'), + #} + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': '1mmSvDFl', + 'HOST': "mariadbsrv.acme", + 'OPTIONS': {"init_command": "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1","charset": "utf8mb4", "use_unicode": True}, + }, + +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'zv_u=c*o!=91amnit_mo6epg%#(p8s#3-02-wr@tm$dch51kw&' diff --git a/.github/workflows/django_tests..yml b/.github/workflows/django_tests..yml new file mode 100644 index 00000000..6c91f4d7 --- /dev/null +++ b/.github/workflows/django_tests..yml @@ -0,0 +1,102 @@ +name: Django Tests + +on: + push: + pull_request: + branches: [ devel ] + schedule: + # * is a special character in YAML so you have to quote this string + - cron: '0 2 * * 6' + +jobs: + apache_django: + name: "apache_django" + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: "checkout GIT" + uses: actions/checkout@v2 + + - name: "[ PREPARE ] Build environment" + working-directory: examples/Docker/ + run: | + sed -i "s/wsgi/django/g" .env + sudo mkdir -p data/mysql + docker network create acme + docker-compose up -d + docker-compose logs + + - name: "[ PREPARE ] install mariadb" + working-directory: examples/Docker/ + run: | + # docker run --name mariadbsrv --network acme -v $PWD/data/mysql:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=foobar -d mariadb + docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb + + - name: "[ PREPARE ] Sleep for 10s" + uses: juliangruber/sleep-action@v1 + with: + time: 10s + + - name: "[ PREPARE ] configure mariadb" + working-directory: examples/Docker/ + run: | + docker exec mariadbsrv mysql -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" + docker exec mariadbsrv mysql -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" + docker exec mariadbsrv mysql -u root --password=foobar -e"FLUSH PRIVILEGES;" + + - name: "[ PREPARE ] configure acme2certifier" + run: | + sudo cp examples/ca_handler/openssl_ca_handler.py examples/Docker/data/ca_handler.py + sudo mkdir -p examples/Docker/data/acme_ca/certs + sudo cp test/ca/sub-ca-key.pem test/ca/sub-ca-crl.pem test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem examples/Docker/data/acme_ca/ + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg + sudo cp .github/django_settings_mariadb.py examples/Docker/data/settings.py + sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem + cd examples/Docker/ + docker-compose restart + docker-compose logs + + - name: "Test if http://acme-srv/directory is accessable" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + + - name: "Test if https://acme-srv/directory is accessable" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "[ PREPARE ] prepare acme.sh container" + run: | + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + + - name: "[ ENROLL ] register via http" + run: | + docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 + + - name: "[ ENROLL ] register via https" + run: | + docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 + + - name: "[ REGISTER] certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + + - name: "[ ENROLL ] HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile examples/Docker/data/acme_ca/root-ca-cert.pem -untrusted examples/Docker/data/acme_ca/sub-ca-cert.pem certbot/live/certbot/cert.pem + + - name: "[ * ] collecting test logs" + if: ${{ failure() }} + run: | + docker exec mariadbsrv mysqldump -u root --password=foobar acme2certifier > /tmp/acme2certifer.sql + mkdir -p ${{ github.workspace }}/artifact/upload + sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + sudo cp /tmp/acme2certifer.sql ${{ github.workspace }}/artifact/data/ + cd examples/Docker + docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data + - name: "[ * ] uploading artificates" + uses: actions/upload-artifact@v2 + if: ${{ failure() }} + with: + name: django-${{ matrix.keylength }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ From 952a8fdca5c513874df088579e7f43bb5a882d9b Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 15 May 2021 18:59:27 +0200 Subject: [PATCH 08/51] [wf] django_psql tests --- .github/a2c.psql | 6 ++ .github/django_settings_psql.py | 125 ++++++++++++++++++++++++++++ .github/pgpass | 1 + .github/workflows/django_tests..yml | 103 ++++++++++++++++++++++- 4 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 .github/a2c.psql create mode 100644 .github/django_settings_psql.py create mode 100644 .github/pgpass diff --git a/.github/a2c.psql b/.github/a2c.psql new file mode 100644 index 00000000..1789c075 --- /dev/null +++ b/.github/a2c.psql @@ -0,0 +1,6 @@ +CREATE DATABASE acme2certifier; +CREATE USER acme2certifier WITH PASSWORD '1mmSvDF'; +ALTER ROLE acme2certifier SET client_encoding TO 'utf8'; +ALTER ROLE acme2certifier SET default_transaction_isolation TO 'read committed'; +ALTER ROLE acme2certifier SET timezone TO 'UTC'; +GRANT ALL PRIVILEGES ON DATABASE acme2certifier TO acme2certifier; diff --git a/.github/django_settings_psql.py b/.github/django_settings_psql.py new file mode 100644 index 00000000..d48d1a03 --- /dev/null +++ b/.github/django_settings_psql.py @@ -0,0 +1,125 @@ +""" +Django settings for acme2certifier project. + +Generated by 'django-admin startproject' using Django 1.11.15. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False + +ALLOWED_HOSTS = ['127.0.0.1','*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'acme' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + # 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'acme2certifier.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'acme2certifier.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': '1mmSvDF', + 'HOST': 'postgresdbsrv', + 'PORT': '', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'zv_u=c*o!=91amnit_mo6epg%#(p8s#3-02-wr@tm$dch51kw&' diff --git a/.github/pgpass b/.github/pgpass new file mode 100644 index 00000000..2934f6e1 --- /dev/null +++ b/.github/pgpass @@ -0,0 +1 @@ +postgresdbsrv:*:*:postgres:foobar diff --git a/.github/workflows/django_tests..yml b/.github/workflows/django_tests..yml index 6c91f4d7..dd660dbc 100644 --- a/.github/workflows/django_tests..yml +++ b/.github/workflows/django_tests..yml @@ -9,8 +9,8 @@ on: - cron: '0 2 * * 6' jobs: - apache_django: - name: "apache_django" + apache_django_mariadb: + name: "apache_django_mariadb" runs-on: ubuntu-latest strategy: fail-fast: false @@ -98,5 +98,102 @@ jobs: uses: actions/upload-artifact@v2 if: ${{ failure() }} with: - name: django-${{ matrix.keylength }}.tar.gz + name: django-mariadb.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + + apache_django_psql: + name: "apache_django_psql" + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: "checkout GIT" + uses: actions/checkout@v2 + + - name: "[ PREPARE ] Build environment" + working-directory: examples/Docker/ + run: | + sed -i "s/wsgi/django/g" .env + sudo mkdir -p data/mysql + sudo mkdir -p data/pgsql + docker network create acme + docker-compose up -d + docker-compose logs + + - name: "[ PREPARE ] postgres environment" + run: | + sudo cp .github/a2c.psql examples/Docker/data/pgsql/a2c.psql + sudo cp .github/pgpass examples/Docker/data/pgsql/pgpass + sudo chmod 600 examples/Docker/data/pgsql/pgpass + + - name: "[ PREPARE ] install postgres" + working-directory: examples/Docker/ + run: | + docker run --name postgresdbsrv --network acme -e POSTGRES_PASSWORD=foobar -d postgres + + - name: "[ PREPARE ] Sleep for 10s" + uses: juliangruber/sleep-action@v1 + with: + time: 10s + + - name: "[ PREPARE ] configure postgres" + working-directory: examples/Docker/ + run: | + docker run -v "$(pwd)/data/pgsql/a2c.psql":/tmp/a2c.psql -v "$(pwd)/data/pgsql/pgpass:/root/.pgpass" --rm --network acme postgres psql -U postgres -h postgresdbsrv -f /tmp/a2c.psql + + - name: "[ PREPARE ] configure acme2certifier" + run: | + sudo cp examples/ca_handler/openssl_ca_handler.py examples/Docker/data/ca_handler.py + sudo mkdir -p examples/Docker/data/acme_ca/certs + sudo cp test/ca/sub-ca-key.pem test/ca/sub-ca-crl.pem test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem examples/Docker/data/acme_ca/ + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg + sudo cp .github/django_settings_psql.py examples/Docker/data/settings.py + sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem + cd examples/Docker/ + docker-compose restart + docker-compose logs + + - name: "Test if http://acme-srv/directory is accessable" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + + - name: "Test if https://acme-srv/directory is accessable" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "[ PREPARE ] prepare acme.sh container" + run: | + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + + - name: "[ ENROLL ] register via http" + run: | + docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 + + - name: "[ ENROLL ] register via https" + run: | + docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 + + - name: "[ REGISTER] certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + + - name: "[ ENROLL ] HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile examples/Docker/data/acme_ca/root-ca-cert.pem -untrusted examples/Docker/data/acme_ca/sub-ca-cert.pem certbot/live/certbot/cert.pem + + - name: "[ * ] collecting test logs" + if: ${{ failure() }} + run: | + docker run -v "$(pwd)/examples/Docker/data/pgsql/pgpass":/root/.pgpass --rm --network acme postgres pg_dump -U postgres -h postgresdbsrv acme2certifier > /tmp/acme2certifier.psql + mkdir -p ${{ github.workspace }}/artifact/upload + sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + sudo cp /tmp/acme2certifier.psql ${{ github.workspace }}/artifact/data/ + cd examples/Docker + docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data + + - name: "[ * ] uploading artificates" + uses: actions/upload-artifact@v2 + if: ${{ failure() }} + with: + name: django-psql.tar.gz path: ${{ github.workspace }}/artifact/upload/ From d4481f0b3a6c0384e54caba61dd7421010b70449 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 15 May 2021 19:08:49 +0200 Subject: [PATCH 09/51] [fix] psycopg2 in dockerfile --- examples/Docker/apache2/django/Dockerfile | 1 + examples/Docker/nginx/django/Dockerfile | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/Docker/apache2/django/Dockerfile b/examples/Docker/apache2/django/Dockerfile index bbb0726e..a7c2b6ff 100644 --- a/examples/Docker/apache2/django/Dockerfile +++ b/examples/Docker/apache2/django/Dockerfile @@ -13,6 +13,7 @@ RUN apt-get install --no-install-recommends -y \ python3-django \ python3-mysqldb \ python3-pymysql \ + python3-psycopg2 \ python3-cryptography \ python3-yaml \ && rm -rf /var/lib/apt/lists/* diff --git a/examples/Docker/nginx/django/Dockerfile b/examples/Docker/nginx/django/Dockerfile index f4febd51..b7a26b58 100644 --- a/examples/Docker/nginx/django/Dockerfile +++ b/examples/Docker/nginx/django/Dockerfile @@ -13,6 +13,7 @@ RUN apt-get install --no-install-recommends -y \ python3-django \ python3-mysqldb \ python3-pymysql \ + python3-psycopg2 \ python3-yaml \ python3-cryptography \ && rm -rf /var/lib/apt/lists/* From 4dfd99bb4466bef5ff50be7dc3eba604089f8dc9 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 16 May 2021 06:22:16 +0200 Subject: [PATCH 10/51] [fix] change from neilpang/acme.sh:dev to neilpang/acme.sh:latest --- .github/workflows/acme_sh-application-test.yml | 8 ++++---- .github/workflows/alpn-test.yml | 2 +- .github/workflows/ca_handler_tests.yml | 2 +- .github/workflows/container-tests.yml | 8 ++++---- .github/workflows/django_tests..yml | 4 ++-- .github/workflows/eab-test.yml | 2 +- .github/workflows/ipv6-test.yml | 8 ++++---- .github/workflows/push_images_to_dockerhub.yml | 8 ++++---- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/acme_sh-application-test.yml b/.github/workflows/acme_sh-application-test.yml index 8886fccc..9a7b6de8 100644 --- a/.github/workflows/acme_sh-application-test.yml +++ b/.github/workflows/acme_sh-application-test.yml @@ -44,7 +44,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh" run: | @@ -156,7 +156,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh" run: | @@ -267,7 +267,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh" run: | @@ -380,7 +380,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh" run: | diff --git a/.github/workflows/alpn-test.yml b/.github/workflows/alpn-test.yml index 7a5369c8..709ae76a 100644 --- a/.github/workflows/alpn-test.yml +++ b/.github/workflows/alpn-test.yml @@ -47,7 +47,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] acme.sh" run: | diff --git a/.github/workflows/ca_handler_tests.yml b/.github/workflows/ca_handler_tests.yml index 69a23318..c33e0b79 100644 --- a/.github/workflows/ca_handler_tests.yml +++ b/.github/workflows/ca_handler_tests.yml @@ -28,7 +28,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ PREPARE ] setup openssl ca_handler" run: | diff --git a/.github/workflows/container-tests.yml b/.github/workflows/container-tests.yml index a9f807a0..17cd8f1f 100644 --- a/.github/workflows/container-tests.yml +++ b/.github/workflows/container-tests.yml @@ -37,7 +37,7 @@ jobs: run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] register via http" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 @@ -89,7 +89,7 @@ jobs: run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] register via http" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 @@ -141,7 +141,7 @@ jobs: run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] register via http" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 @@ -194,7 +194,7 @@ jobs: run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] register via http" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 diff --git a/.github/workflows/django_tests..yml b/.github/workflows/django_tests..yml index dd660dbc..75e40662 100644 --- a/.github/workflows/django_tests..yml +++ b/.github/workflows/django_tests..yml @@ -65,7 +65,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] register via http" run: | @@ -161,7 +161,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] register via http" run: | diff --git a/.github/workflows/eab-test.yml b/.github/workflows/eab-test.yml index 06408e49..5faacb9e 100644 --- a/.github/workflows/eab-test.yml +++ b/.github/workflows/eab-test.yml @@ -64,7 +64,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ REGISTER] acme.sh" run: | diff --git a/.github/workflows/ipv6-test.yml b/.github/workflows/ipv6-test.yml index 5876c66d..55a1a702 100644 --- a/.github/workflows/ipv6-test.yml +++ b/.github/workflows/ipv6-test.yml @@ -32,7 +32,7 @@ jobs: docker-compose logs - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure @@ -81,7 +81,7 @@ jobs: docker-compose logs - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure @@ -131,7 +131,7 @@ jobs: docker-compose logs - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure @@ -182,7 +182,7 @@ jobs: docker-compose logs - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure diff --git a/.github/workflows/push_images_to_dockerhub.yml b/.github/workflows/push_images_to_dockerhub.yml index 09e71ee4..c0cef71b 100644 --- a/.github/workflows/push_images_to_dockerhub.yml +++ b/.github/workflows/push_images_to_dockerhub.yml @@ -95,7 +95,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] via openssl ca_handler" run: | @@ -150,7 +150,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] via openssl ca_handler" run: | @@ -202,7 +202,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] via openssl ca_handler" run: | @@ -257,7 +257,7 @@ jobs: - name: "[ PREPARE ] prepare acme.sh container" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:dev daemon + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - name: "[ ENROLL ] via openssl ca_handler" run: | From 2d143a05f1daf0d81a081ae8fa3c7597b3a68f4c Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 16 May 2021 14:13:25 +0200 Subject: [PATCH 11/51] [feat] password variable xca_ca_handler.py --- docs/xca.md | 4 +- examples/ca_handler/xca_ca_handler.py | 11 +- test/test_xca_ca_handler.py | 346 ++++++++++++++------------ 3 files changed, 199 insertions(+), 162 deletions(-) diff --git a/docs/xca.md b/docs/xca.md index 5ffa0507..9d351755 100644 --- a/docs/xca.md +++ b/docs/xca.md @@ -29,15 +29,15 @@ root@rlh:~# cp example/ca_handlers/xca_ca_handler.py acme/ca_handler.py xdb_file: acme/xca/acme2certifier.xdb issuing_ca_name: sub-ca issuing_ca_key: sub-ca-key -passphrase: test1234 +passphrase_variable: XCA_PASSPHRASE ca_cert_chain_list: ["root-ca"] template_name: XCA template to be applied to CSRs ``` - `xdb_file` - path to XCA database -- `issuing_ca_key_passphrase` - password to access the private key - `issuing_ca_name` - XCA name of the certificate authority used to issue certificates. - `issuing_ca_key` - XCA name of the ley used to sign certificates. If not set same value as configured in `issuing_ca_name` will be assumed. +- `passphrase_variable` - *optional* - name of the environment variable containing the passphrase to decrypt the CA key (a configured `passphrase` parameter takes precedence) - `passphrase` - *optional* - passphrase to access the database and decrypt the private CA Key - `ca_cert_chain_list` - *optional* - List of root and intermediate CA certificates to be added to the bundle return to an ACME-client (the issuing CA cert must not be included) - `template_name` - *optional* - name of the XCA template to be applied during certificate issuance diff --git a/examples/ca_handler/xca_ca_handler.py b/examples/ca_handler/xca_ca_handler.py index 58d6933f..2f31bdce 100644 --- a/examples/ca_handler/xca_ca_handler.py +++ b/examples/ca_handler/xca_ca_handler.py @@ -22,7 +22,7 @@ def __init__(self, debug=None, logger=None): self.debug = debug self.logger = logger self.xdb_file = None - self.passphrase = 'i_dont_know' + self.passphrase = None self.issuing_ca_name = None self.issuing_ca_key = None self.cert_validity_days = 365 @@ -176,7 +176,16 @@ def _config_load(self): if 'xdb_file' in config_dic['CAhandler']: self.xdb_file = config_dic['CAhandler']['xdb_file'] + if 'passphrase_variable' in config_dic['CAhandler']: + try: + self.passphrase = os.environ[config_dic['CAhandler']['passphrase_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load passphrase_variable:{0}'.format(err)) + if 'passphrase' in config_dic['CAhandler']: + # overwrite passphrase specified in variable + if self.passphrase: + self.logger.info('CAhandler._config_load() overwrite passphrase_variable') self.passphrase = config_dic['CAhandler']['passphrase'] if 'issuing_ca_name' in config_dic['CAhandler']: diff --git a/test/test_xca_ca_handler.py b/test/test_xca_ca_handler.py index b6d6a357..4729fa55 100644 --- a/test/test_xca_ca_handler.py +++ b/test/test_xca_ca_handler.py @@ -151,7 +151,7 @@ def test_016_ca_key_load(self): self.assertFalse(self.cahandler._ca_key_load()) @patch('OpenSSL.crypto.load_privatekey') - def test_018_ca_key_load(self, mock_key): + def test_017_ca_key_load(self, mock_key): """ CAhandler._ca_key_load """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_key = 'sub-ca' @@ -162,7 +162,7 @@ def test_018_ca_key_load(self, mock_key): self.assertIn('ERROR:test_a2c:CAhandler._ca_key_load() failed with error: exc_key_load', lcm.output) @patch('OpenSSL.crypto.load_certificate') - def test_019_ca_cert_load(self, mock_certload): + def test_018_ca_cert_load(self, mock_certload): """ CAhandler._ca_cert_load """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' @@ -171,112 +171,112 @@ def test_019_ca_cert_load(self, mock_certload): self.assertEqual((None, None, None), self.cahandler._ca_load()) self.assertIn('ERROR:test_a2c:CAhandler._ca_cert_load() failed with error: exc_cert_load', lcm.output) - def test_017_csr_insert(self): + def test_019_csr_insert(self): """ CAhandler._csr_insert empty item dic """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' csr_dic = {} self.assertFalse(self.cahandler._csr_insert(csr_dic)) - def test_018_csr_insert(self): + def test_020_csr_insert(self): """ CAhandler._csr_insert full item dic """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' csr_dic = {'item': 2, 'signed': 0, 'request': 'request'} self.assertEqual(2, self.cahandler._csr_insert(csr_dic)) - def test_019_csr_insert(self): + def test_021_csr_insert(self): """ CAhandler._csr_insert full item dic item has wrong datatype """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' csr_dic = {'item': '2', 'signed': 0, 'request': 'request'} self.assertFalse(self.cahandler._csr_insert(csr_dic)) - def test_020_csr_insert(self): + def test_022_csr_insert(self): """ CAhandler._csr_insert full item dic item has wrong datatype """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' csr_dic = {'item': 2, 'signed': '0', 'request': 'request'} self.assertFalse(self.cahandler._csr_insert(csr_dic)) - def test_021_csr_insert(self): + def test_023_csr_insert(self): """ CAhandler._csr_insert item dic without item """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' csr_dic = {'signed': 0, 'request': 'request'} self.assertFalse(self.cahandler._csr_insert(csr_dic)) - def test_022_csr_insert(self): + def test_024_csr_insert(self): """ CAhandler._csr_insert item dic without signed """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' csr_dic = {'item': 2, 'request': 'request'} self.assertFalse(self.cahandler._csr_insert(csr_dic)) - def test_023_csr_insert(self): + def test_025_csr_insert(self): """ CAhandler._csr_insert item dic without request """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' csr_dic = {'item': 2, 'signed': 0} self.assertFalse(self.cahandler._csr_insert(csr_dic)) - def test_024_item_insert(self): + def test_026_item_insert(self): """ CAhandler._item_insert empty item dic """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {} self.assertFalse(self.cahandler._item_insert(item_dic)) - def test_025_item_insert(self): + def test_027_item_insert(self): """ CAhandler._item_insert full item dic """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {'name': 'name', 'type': 2, 'source': 0, 'date': 'date', 'comment': 'comment'} self.assertEqual(15, self.cahandler._item_insert(item_dic)) - def test_026_item_insert(self): + def test_028_item_insert(self): """ CAhandler._item_insert no name """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {'type': 2, 'source': 0, 'date': 'date', 'comment': 'comment'} self.assertFalse(self.cahandler._item_insert(item_dic)) - def test_027_item_insert(self): + def test_029_item_insert(self): """ CAhandler._item_insert no type """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {'name': 'name', 'source': 0, 'date': 'date', 'comment': 'comment'} self.assertFalse(self.cahandler._item_insert(item_dic)) - def test_028_item_insert(self): + def test_030_item_insert(self): """ CAhandler._item_insert no siurce """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {'name': 'name', 'item': 2, 'date': 'date', 'comment': 'comment'} self.assertFalse(self.cahandler._item_insert(item_dic)) - def test_029_item_insert(self): + def test_031_item_insert(self): """ CAhandler._item_insert no date """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {'name': 'name', 'type': 2, 'source': 0, 'comment': 'comment'} self.assertFalse(self.cahandler._item_insert(item_dic)) - def test_030_item_insert(self): + def test_032_item_insert(self): """ CAhandler._item_insert no date """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {'name': 'name', 'type': 2, 'source': 0, 'date': 'date'} self.assertFalse(self.cahandler._item_insert(item_dic)) - def test_031_item_insert(self): + def test_033_item_insert(self): """ CAhandler._item_insert full item dic type has wrong datatype """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' item_dic = {'name': 'name', 'type': '2', 'source': 0, 'date': 'date', 'comment': 'comment'} self.assertFalse(self.cahandler._item_insert(item_dic)) - def test_032_item_insert(self): + def test_034_item_insert(self): """ CAhandler._item_insert full item dic source has wrong datatype """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.issuing_ca_name = 'sub-ca' @@ -284,7 +284,7 @@ def test_032_item_insert(self): self.assertFalse(self.cahandler._item_insert(item_dic)) @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_search') - def test_033_csr_import(self, mock_search): + def test_035_csr_import(self, mock_search): """ CAhandler._csr_import with existing cert_dic """ mock_search.return_value = {'foo', 'bar'} self.assertEqual({'foo', 'bar'}, self.cahandler._csr_import('csr', 'request_name')) @@ -292,74 +292,74 @@ def test_033_csr_import(self, mock_search): @patch('examples.ca_handler.xca_ca_handler.CAhandler._item_insert') @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_insert') @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_search') - def test_034_csr_import(self, mock_search, mock_csr_insert, mock_item_insert): + def test_036_csr_import(self, mock_search, mock_csr_insert, mock_item_insert): """ CAhandler._csr_import with existing cert_dic """ mock_search.return_value = {} mock_csr_insert.return_value = 5 mock_item_insert.return_value = 10 self.assertEqual({'item': 10, 'signed': 1, 'request': 'csr'}, self.cahandler._csr_import('csr', 'request_name')) - def test_035_cert_insert(self): + def test_037_cert_insert(self): """ CAhandler._csr_import with empty cert_dic """ cert_dic = {} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_036_cert_insert(self): + def test_038_cert_insert(self): """ CAhandler._csr_import item missing """ cert_dic = {'serial': 'serial', 'issuer': 'issuer', 'ca': 'ca', 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_037_cert_insert(self): + def test_039_cert_insert(self): """ CAhandler._csr_import serial missing """ cert_dic = {'item': 'item', 'issuer': 'issuer', 'ca': 'ca', 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_038_cert_insert(self): + def test_040_cert_insert(self): """ CAhandler._csr_import issuer missing """ cert_dic = {'item': 'item', 'serial': 'serial', 'ca': 'ca', 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_039_cert_insert(self): + def test_041_cert_insert(self): """ CAhandler._csr_import ca missing """ cert_dic = {'item': 'item', 'serial': 'serial', 'issuer': 'issuer', 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_040_cert_insert(self): + def test_042_cert_insert(self): """ CAhandler._csr_import cert missing """ cert_dic = {'item': 'item', 'serial': 'serial', 'issuer': 'issuer', 'ca': 'ca', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_041_cert_insert(self): + def test_043_cert_insert(self): """ CAhandler._csr_import iss_hash missing """ cert_dic = {'item': 'item', 'serial': 'serial', 'issuer': 'issuer', 'ca': 'ca', 'cert': 'cert', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_042_cert_insert(self): + def test_044_cert_insert(self): """ CAhandler._csr_import hash missing """ cert_dic = {'item': 'item', 'serial': 'serial', 'issuer': 'issuer', 'ca': 'ca', 'cert': 'cert', 'iss_hash': 'iss_hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_043_cert_insert(self): + def test_045_cert_insert(self): """ CAhandler._csr_import with item not int """ cert_dic = {'item': 'item', 'serial': 'serial', 'issuer': 'issuer', 'ca': 'ca', 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_044_cert_insert(self): + def test_046_cert_insert(self): """ CAhandler._csr_import with issuer not int """ cert_dic = {'item': 1, 'serial': 'serial', 'issuer': 'issuer', 'ca': 'ca', 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_045_cert_insert(self): + def test_047_cert_insert(self): """ CAhandler._csr_import with ca not int """ cert_dic = {'item': 1, 'serial': 'serial', 'issuer': 1, 'ca': 'ca', 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_046_cert_insert(self): + def test_048_cert_insert(self): """ CAhandler._csr_import with iss_hash not int """ cert_dic = {'item': 1, 'serial': 'serial', 'issuer': 2, 'ca': 3, 'cert': 'cert', 'iss_hash': 'iss_hash', 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) - def test_047_cert_insert(self): + def test_049_cert_insert(self): """ CAhandler._csr_import with hash not int """ cert_dic = {'item': 1, 'serial': 'serial', 'issuer': 2, 'ca': 3, 'cert': 'cert', 'iss_hash': 4, 'hash': 'hash'} self.assertFalse(self.cahandler._cert_insert(cert_dic)) @@ -377,21 +377,21 @@ def test_050_cert_insert(self, mock_open, mock_close): self.assertTrue(mock_open.called) self.assertTrue(mock_close.called) - def test_048_pemcertchain_generate(self): + def test_051_pemcertchain_generate(self): """ CAhandler._pemcertchain_generate no certificates """ ee_cert = None issuer_cert = None self.cahandler.ca_cert_chain_list = [] self.assertFalse(self.cahandler._pemcertchain_generate(ee_cert, issuer_cert)) - def test_049_pemcertchain_generate(self): + def test_052_pemcertchain_generate(self): """ CAhandler._pemcertchain_generate no issuer """ ee_cert = 'ee_cert' issuer_cert = None self.cahandler.ca_cert_chain_list = [] self.assertEqual('ee_cert', self.cahandler._pemcertchain_generate(ee_cert, issuer_cert)) - def test_050_pemcertchain_generate(self): + def test_053_pemcertchain_generate(self): """ CAhandler._pemcertchain_generate no ca chain """ ee_cert = 'ee_cert' issuer_cert = 'issuer_cert' @@ -400,7 +400,7 @@ def test_050_pemcertchain_generate(self): @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_search') @patch('OpenSSL.crypto.load_certificate') - def test_051_pemcertchain_generate(self, mock_cert, mock_search): + def test_054_pemcertchain_generate(self, mock_cert, mock_search): """ CAhandler._pemcertchain_generate empty cert dic in ca_chain """ ee_cert = 'ee_cert' issuer_cert = 'issuer_cert' @@ -411,7 +411,7 @@ def test_051_pemcertchain_generate(self, mock_cert, mock_search): @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_search') @patch('OpenSSL.crypto.load_certificate') - def test_052_pemcertchain_generate(self, mock_cert, mock_search): + def test_055_pemcertchain_generate(self, mock_cert, mock_search): """ CAhandler._pemcertchain_generate empty no cert in chain """ ee_cert = 'ee_cert' issuer_cert = 'issuer_cert' @@ -424,7 +424,7 @@ def test_052_pemcertchain_generate(self, mock_cert, mock_search): @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_search') @patch('OpenSSL.crypto.load_certificate') @patch('OpenSSL.crypto.dump_certificate') - def test_053_pemcertchain_generate(self, mock_dump, mock_load, mock_search, mock_b64dec): + def test_056_pemcertchain_generate(self, mock_dump, mock_load, mock_search, mock_b64dec): """ CAhandler._pemcertchain_generate one cert in chain """ ee_cert = 'ee_cert' issuer_cert = 'issuer_cert' @@ -439,7 +439,7 @@ def test_053_pemcertchain_generate(self, mock_dump, mock_load, mock_search, mock @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_search') @patch('OpenSSL.crypto.load_certificate') @patch('OpenSSL.crypto.dump_certificate') - def test_054_pemcertchain_generate(self, mock_dump, mock_load, mock_search, mock_b64dec): + def test_057_pemcertchain_generate(self, mock_dump, mock_load, mock_search, mock_b64dec): """ CAhandler._pemcertchain_generate two certs in chain """ ee_cert = 'ee_cert' issuer_cert = 'issuer_cert' @@ -451,14 +451,14 @@ def test_054_pemcertchain_generate(self, mock_dump, mock_load, mock_search, mock self.assertEqual('ee_certissuer_certfoo1foo2', self.cahandler._pemcertchain_generate(ee_cert, issuer_cert)) @patch('examples.ca_handler.xca_ca_handler.csr_cn_get') - def test_055_requestname_get(self, mock_cn): + def test_058_requestname_get(self, mock_cn): """ CAhandler._requestname_get from cn """ mock_cn.return_value = 'foo' self.assertEqual('foo', self.cahandler._requestname_get('csr')) @patch('examples.ca_handler.xca_ca_handler.csr_san_get') @patch('examples.ca_handler.xca_ca_handler.csr_cn_get') - def test_056_requestname_get(self, mock_cn, mock_san): + def test_059_requestname_get(self, mock_cn, mock_san): """ CAhandler._requestname_get empty cn empty san""" mock_cn.return_value = None mock_san.return_value = [] @@ -466,7 +466,7 @@ def test_056_requestname_get(self, mock_cn, mock_san): @patch('examples.ca_handler.xca_ca_handler.csr_san_get') @patch('examples.ca_handler.xca_ca_handler.csr_cn_get') - def test_057_requestname_get(self, mock_cn, mock_san): + def test_060_requestname_get(self, mock_cn, mock_san): """ CAhandler._requestname_get empty cn empty dsmaged san""" mock_cn.return_value = None mock_san.return_value = ['foo'] @@ -474,7 +474,7 @@ def test_057_requestname_get(self, mock_cn, mock_san): @patch('examples.ca_handler.xca_ca_handler.csr_san_get') @patch('examples.ca_handler.xca_ca_handler.csr_cn_get') - def test_058_requestname_get(self, mock_cn, mock_san): + def test_061_requestname_get(self, mock_cn, mock_san): """ CAhandler._requestname_get empty cn empty dsmaged san""" mock_cn.return_value = None mock_san.return_value = ['dns:foo'] @@ -482,48 +482,48 @@ def test_058_requestname_get(self, mock_cn, mock_san): @patch('examples.ca_handler.xca_ca_handler.csr_san_get') @patch('examples.ca_handler.xca_ca_handler.csr_cn_get') - def test_059_requestname_get(self, mock_cn, mock_san): + def test_062_requestname_get(self, mock_cn, mock_san): """ CAhandler._requestname_get empty cn empty dsmaged san""" mock_cn.return_value = None mock_san.return_value = ['dns:foo', 'bar'] self.assertEqual('foo', self.cahandler._requestname_get('csr')) - def test_060_cert_insert(self): + def test_063_cert_insert(self): """ CAhandler._revocation_insert with empty rev_dic """ rev_dic = {} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) - def test_061_cert_insert(self): + def test_064_cert_insert(self): """ CAhandler._revocation_insert no caID """ rev_dic = {'serial': 'serial', 'date': 'date', 'invaldate': 'invaldate', 'reasonBit': 0} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) - def test_062_cert_insert(self): + def test_065_cert_insert(self): """ CAhandler._revocation_insert no serial """ rev_dic = {'caID': 4, 'date': 'date', 'invaldate': 'invaldate', 'reasonBit': 0} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) - def test_063_cert_insert(self): + def test_066_cert_insert(self): """ CAhandler._revocation_insert no date """ rev_dic = {'caID': 4, 'serial': 'serial', 'invaldate': 'invaldate', 'reasonBit': 0} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) - def test_064_cert_insert(self): + def test_067_cert_insert(self): """ CAhandler._revocation_insert no invaldate """ rev_dic = {'caID': 4, 'serial': 'serial', 'date': 'date', 'reasonBit': 0} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) - def test_065_cert_insert(self): + def test_068_cert_insert(self): """ CAhandler._revocation_insert no resonBit """ rev_dic = {'caID': 4, 'serial': 'serial', 'date': 'date', 'invaldate': 'invaldate'} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) - def test_066_cert_insert(self): + def test_069_cert_insert(self): """ CAhandler._revocation_insert with caID is not int """ rev_dic = {'caID': 'caID', 'serial': 'serial', 'date': 'date', 'invaldate': 'invaldate', 'reasonBit': 0} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) - def test_067_cert_insert(self): + def test_070_cert_insert(self): """ CAhandler._revocation_insert with caID is not int """ rev_dic = {'caID': 0, 'serial': 'serial', 'date': 'date', 'invaldate': 'invaldate', 'reasonBit': '0'} self.assertFalse(self.cahandler._revocation_insert(rev_dic)) @@ -541,7 +541,7 @@ def test_071_rev_insert(self, mock_open, mock_close): self.assertTrue(mock_close.called) @patch('examples.ca_handler.xca_ca_handler.uts_to_date_utc') - def test_068_revoke(self, mock_date): + def test_072_revoke(self, mock_date): """ CAhandler.revocation without xdb file """ mock_date.return_value = 'foo' self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'configuration error'), self.cahandler.revoke('cert', 'reason', None)) @@ -549,7 +549,7 @@ def test_068_revoke(self, mock_date): @patch('examples.ca_handler.xca_ca_handler.cert_serial_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') @patch('examples.ca_handler.xca_ca_handler.uts_to_date_utc') - def test_069_revoke(self, mock_date, mock_ca, mock_serial): + def test_073_revoke(self, mock_date, mock_ca, mock_serial): """ CAhandler.revocation no CA ID """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' mock_date.return_value = 'foo' @@ -560,7 +560,7 @@ def test_069_revoke(self, mock_date, mock_ca, mock_serial): @patch('examples.ca_handler.xca_ca_handler.cert_serial_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') @patch('examples.ca_handler.xca_ca_handler.uts_to_date_utc') - def test_070_revoke(self, mock_date, mock_ca, mock_serial): + def test_074_revoke(self, mock_date, mock_ca, mock_serial): """ CAhandler.revocation no serial """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' mock_date.return_value = 'foo' @@ -573,7 +573,7 @@ def test_070_revoke(self, mock_date, mock_ca, mock_serial): @patch('examples.ca_handler.xca_ca_handler.cert_serial_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') @patch('examples.ca_handler.xca_ca_handler.uts_to_date_utc') - def test_071_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock_search): + def test_075_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock_search): """ CAhandler.revocation no serial """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' mock_date.return_value = 'foo' @@ -588,7 +588,7 @@ def test_071_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock @patch('examples.ca_handler.xca_ca_handler.cert_serial_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') @patch('examples.ca_handler.xca_ca_handler.uts_to_date_utc') - def test_072_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock_search): + def test_076_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock_search): """ CAhandler.revocation no serial """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' mock_date.return_value = 'foo' @@ -603,7 +603,7 @@ def test_072_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock @patch('examples.ca_handler.xca_ca_handler.cert_serial_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._ca_load') @patch('examples.ca_handler.xca_ca_handler.uts_to_date_utc') - def test_073_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock_search): + def test_077_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock_search): """ CAhandler.revocation no serial """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' mock_date.return_value = 'foo' @@ -613,24 +613,24 @@ def test_073_revoke(self, mock_date, mock_ca, mock_serial, mock_rev_insert, mock mock_serial.return_value = 1000 self.assertEqual((200, None, None), self.cahandler.revoke('cert', 'reason', None)) - def test_074_cert_search(self): + def test_078_cert_search(self): """ CAhandler._cert_sarch cert can be found """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' search_result = {'item': 6, 'hash': 1675584264, 'iss_hash': 1339028853, 'serial': '0BCC30C544EF26A4', 'issuer': 4, 'ca': 0, 'cert': 'MIIEQTCCAimgAwIBAgIIC8wwxUTvJqQwDQYJKoZIhvcNAQELBQAwETEPMA0GA1UEAxMGc3ViLWNhMB4XDTIwMDYwOTE3MTkwMFoXDTIxMDYwOTE3MTkwMFowGzEZMBcGA1UEAxMQY2xpZW50LmJhci5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJps2tk/d5pqv1gSeLnDBFQSzznY/iSBtzRNLlRWm6J7yOAERgGsbMBW7s5AhYRbuHuberlBtsyFyKenWvijo6r7DTOGiv2oBf7iCoCXYbNAqlvnP5inzp6ZmmgmxigLFbdlTfPQBkaytDzLAav1KLCmCof4DpQunsxdDjW0kBm8jRC7HY5bauxeFKQb2NcGmjlB3kQjZNHF52xG/GgkMIH7E0NJUhmsVfItSezkmFUQFhP2VqYYsiPRtvXlZqpzPISxn2InGcUaaBzJFO7RWif0IIsgzcyzqXvt8KEqeoI15gmd1G4lXPeyadXG8kzE8L+8f4J+gGgQSA1eR4VMkOMCAwEAAaOBkjCBjzAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRjovc4aaN6LCIE5E/ZgsLBH+3/WDAOBgNVHQ8BAf8EBAMCA+gwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBsGA1UdEQQUMBKCEGNsaWVudC5iYXIubG9jYWwwEQYJYIZIAYb4QgEBBAQDAgZAMA0GCSqGSIb3DQEBCwUAA4ICAQCZm5d3jc9oopD193bGwJFo8NNo1wzYvvqbK/lONy/JsisX1pERxN+EZyTB2CLxQ4yKZU9Xnx0fmcJExqoPLEva6hAMdOiSEsEs52yyL6gjMLHxJJfdXBiqMZetp+BCPf23rc96ONzyjURDCfsN4VMg7090e9yKpuyHKIOHStqMT+ZLvPcd+YiU4jMazoagauEW2mdpqyA8mN92qiphwo8QMCv3XZJWJ1PEwaCTGhBxlzMoaknWKzCD2YQ/yyGE4Ha8vBaymk1eh7txo5B53C0OpO0UT4WGUOZDP1GPySymqQfDO6R9BhBjyggsG5G9FA84tUqZJAKlGhPesQyIQBM4SZlQTJt/hP/cCoZ6BiibBdaZnLzOyH+NTJ9ou0hpmMp2LZiB8G2Igam7wdXySvQe9sxXXDDTKhxwqk7V+by2gS6asfcQjstQQeMN/iMrg3AtZt/Kl5WcHcwSjZAypHugPiwjr48WHvDS2lUKnbbDuiCxvc1TsPGG6Z+b/0aTwrps6yMeTRuDk3A8DYceHftrWZSOgg+5A2ISd58vPOHiamATVLXGJ1vnCP0Sm/Z4QCnIGfOvxltdAnrcA75MnefaOmQv9CrhwyBembugd9fPC/uFi/ESKGPuo6zLYwjFwLqwNe99UgU98iYz9rfdKNqJ6fWRolzz4AXqUHQ4Dc8eZA=='} self.assertEqual(search_result, self.cahandler._cert_search('name', 'client')) - def test_075_cert_search(self): + def test_079_cert_search(self): """ CAhandler._cert_sarch cert failed """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.assertFalse(self.cahandler._cert_search('name', 'client_failed')) - def test_076_cert_search(self): + def test_080_cert_search(self): """ CAhandler._cert_sarch item search succ / cert_search failed """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.assertFalse(self.cahandler._cert_search('name', 'item_no_cert')) @patch('examples.ca_handler.xca_ca_handler.load_config') - def test_077_config_load(self, mock_load_cfg): + def test_081_config_load(self, mock_load_cfg): """ test _config_load - ca_chain is not json format """ mock_load_cfg.return_value = {'CAhandler': {'ca_cert_chain_list': '[foo]'}} with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -639,7 +639,7 @@ def test_077_config_load(self, mock_load_cfg): self.assertIn('ERROR:test_a2c:CAhandler._config_load(): parameter "ca_cert_chain_list" cannot be loaded', lcm.output) @patch('examples.ca_handler.xca_ca_handler.load_config') - def test_078_config_load(self, mock_load_cfg): + def test_082_config_load(self, mock_load_cfg): """ test _config_load - load template """ mock_load_cfg.return_value = {'CAhandler': {'template_name': 'foo'}} self.cahandler._config_load() @@ -673,107 +673,135 @@ def test_086_config_load(self, mock_load_cfg): self.cahandler._config_load() self.assertEqual('foo', self.cahandler.issuing_ca_key) - def test_079_stream_split(self): + @patch.dict('os.environ', {'foo': 'foo_var'}) + @patch('examples.ca_handler.xca_ca_handler.load_config') + def test_087_config_load(self, mock_load_cfg): + """ test _config_load - load template with passphrase variable """ + mock_load_cfg.return_value = {'CAhandler': {'passphrase_variable': 'foo'}} + self.cahandler._config_load() + self.assertEqual('foo_var', self.cahandler.passphrase) + + @patch.dict('os.environ', {'foo': 'foo_var'}) + @patch('examples.ca_handler.xca_ca_handler.load_config') + def test_088_config_load(self, mock_load_cfg): + """ test _config_load - load template passpharese variable configured but does not exist """ + mock_load_cfg.return_value = {'CAhandler': {'passphrase_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.passphrase) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load passphrase_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'foo': 'foo_var'}) + @patch('examples.ca_handler.xca_ca_handler.load_config') + def test_089_config_load(self, mock_load_cfg): + """ test _config_load - load template with passphrase variable - overwritten bei cfg file""" + mock_load_cfg.return_value = {'CAhandler': {'passphrase_variable': 'foo', 'passphrase': 'foo_file'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('foo_file', self.cahandler.passphrase) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite passphrase_variable', lcm.output) + + def test_090_stream_split(self): """ test stream_split - all ok """ byte_stream = b'before\x00\x00\x00\x0cafter' self.assertEqual((b'before\x00\x00\x00\x0c', b'after'), self.cahandler._stream_split(byte_stream)) - def test_080_stream_split(self): + def test_091_stream_split(self): """ test stream_split - no bytestream """ byte_stream = None self.assertEqual((None, None), self.cahandler._stream_split(byte_stream)) - def test_081_stream_split(self): + def test_092_stream_split(self): """ test stream_split - no match """ byte_stream = b'foofoobar' self.assertEqual((None, None), self.cahandler._stream_split(byte_stream)) - def test_082_stream_split(self): + def test_093_stream_split(self): """ test stream_split - start with match match """ byte_stream = b'\x00\x00\x00\x0cafter' self.assertEqual((b'\x00\x00\x00\x0c', b'after'), self.cahandler._stream_split(byte_stream)) - def test_083__utf_stream_parse(self): + def test_094__utf_stream_parse(self): """ test _utf_stream_parse() - all ok """ utf_stream = b'foo\x00\x00\x00bar' self.assertEqual(({'foo': 'ar'}), self.cahandler._utf_stream_parse(utf_stream)) - def test_084__utf_stream_parse(self): + def test_095__utf_stream_parse(self): """ test _utf_stream_parse() - two parameter """ utf_stream = b'foo1\x00\x00\x00_bar1\x00\x00\x00_foo2\x00\x00\x00_bar2' self.assertEqual(({'foo1': 'bar1', 'foo2': 'bar2'}), self.cahandler._utf_stream_parse(utf_stream)) - def test_085__utf_stream_parse(self): + def test_096__utf_stream_parse(self): """ test _utf_stream_parse() - non even parameter """ utf_stream = b'foo1\x00\x00\x00_bar1\x00\x00\x00_foo2' self.assertEqual(({'foo1': 'bar1'}), self.cahandler._utf_stream_parse(utf_stream)) - def test_086__utf_stream_parse(self): + def test_097__utf_stream_parse(self): """ test _utf_stream_parse() - replace single \x00 in list key """ utf_stream = b'f\x00oo1\x00\x00\x00_bar1\x00\x00\x00_foo2' self.assertEqual(({'foo1': 'bar1'}), self.cahandler._utf_stream_parse(utf_stream)) - def test_087__utf_stream_parse(self): + def test_098__utf_stream_parse(self): """ test _utf_stream_parse() - replace multiple \x00 in list key """ utf_stream = b'f\x00o\x00o\x001\x00\x00\x00_bar1\x00\x00\x00_foo2' self.assertEqual(({'foo1': 'bar1'}), self.cahandler._utf_stream_parse(utf_stream)) - def test_088__utf_stream_parse(self): + def test_099__utf_stream_parse(self): """ test _utf_stream_parse() - replace single \x00 in list value """ utf_stream = b'foo1\x00\x00\x00_b\x00ar1\x00\x00\x00_foo2' self.assertEqual(({'foo1': 'bar1'}), self.cahandler._utf_stream_parse(utf_stream)) - def test_089__utf_stream_parse(self): + def test_100__utf_stream_parse(self): """ test _utf_stream_parse() - replace multiple \x00 in list value """ utf_stream = b'foo\x001\x00\x00\x00_b\x00a\x00r1\x00\x00\x00_foo2' self.assertEqual(({'foo1': 'bar1'}), self.cahandler._utf_stream_parse(utf_stream)) - def test_090__utf_stream_parse(self): + def test_101__utf_stream_parse(self): """ test _utf_stream_parse() - no utf_stream """ utf_stream = None self.assertFalse(self.cahandler._utf_stream_parse(utf_stream)) - def test_091__ans1_stream_parse(self): + def test_102__ans1_stream_parse(self): """ test _ans1_stream_parse - with country """ asn1_stream = b'12345678foo\x06\x03\x55\x04\x06\02fco' self.assertEqual(({'countryName': 'co'}), self.cahandler._asn1_stream_parse(asn1_stream)) - def test_092__ans1_stream_parse(self): + def test_103__ans1_stream_parse(self): """ test _ans1_stream_parse - country, loc """ asn1_stream = b'12345678foo\x06\x03\x55\x04\x06\02fco\x06\x03\x55\x04\x07\03floc' self.assertEqual(({'countryName': 'co', 'localityName': 'loc'}), self.cahandler._asn1_stream_parse(asn1_stream)) - def test_093__ans1_stream_parse(self): + def test_104__ans1_stream_parse(self): """ test _ans1_stream_parse - country, lo, state """ asn1_stream = b'12345678foo\x06\x03\x55\x04\x06\02fco\x06\x03\x55\x04\x07\03floc\x06\x03\x55\x04\x08\05fstate' self.assertEqual(({'countryName': 'co', 'localityName': 'loc', 'stateOrProvinceName': 'state'}), self.cahandler._asn1_stream_parse(asn1_stream)) - def test_094__ans1_stream_parse(self): + def test_105__ans1_stream_parse(self): """ test _ans1_stream_parse - country, loc, state, org """ asn1_stream = b'12345678foo\x06\x03\x55\x04\x06\02fco\x06\x03\x55\x04\x07\03floc\x06\x03\x55\x04\x08\05fstate\x06\x03\x55\x04\x0a\03forg' self.assertEqual(({'countryName': 'co', 'localityName': 'loc', 'stateOrProvinceName': 'state', 'organizationName': 'org'}), self.cahandler._asn1_stream_parse(asn1_stream)) - def test_095__ans1_stream_parse(self): + def test_106__ans1_stream_parse(self): """ test _ans1_stream_parse - country, loc, state, org, ou """ asn1_stream = b'12345678foo\x06\x03\x55\x04\x06\02fco\x06\x03\x55\x04\x07\03floc\x06\x03\x55\x04\x08\05fstate\x06\x03\x55\x04\x0a\03forg\x06\x03\x55\x04\x0b\02fou' self.assertEqual(({'countryName': 'co', 'localityName': 'loc', 'stateOrProvinceName': 'state', 'organizationName': 'org', 'organizationalUnitName': 'ou'}), self.cahandler._asn1_stream_parse(asn1_stream)) - def test_096__ans1_stream_parse(self): + def test_107__ans1_stream_parse(self): """ test _ans1_stream_parse - extralong value """ asn1_stream = b'12345678foo\x06\x03\x55\x04\x07\x11flllllllllllllllll' self.assertEqual(({'localityName': 'lllllllllllllllll'}), self.cahandler._asn1_stream_parse(asn1_stream)) - def test_097__ans1_stream_parse(self): + def test_108__ans1_stream_parse(self): """ test _ans1_stream_parse - empty stream """ asn1_stream = None self.assertFalse(self.cahandler._asn1_stream_parse(asn1_stream)) - def test_098__ans1_stream_parse(self): + def test_109__ans1_stream_parse(self): """ test _ans1_stream_parse - too short """ asn1_stream = b'123456' self.assertFalse(self.cahandler._asn1_stream_parse(asn1_stream)) - def test_099__ans1_stream_parse(self): + def test_110__ans1_stream_parse(self): """ test _ans1_stream_parse - country, non existing value in beteeen """ asn1_stream = b'12345678foo\x06\x03\x55\x04\x06\02fco\x06\x03\x55\x05\x07\03floc' self.assertEqual(({'countryName': 'co'}), self.cahandler._asn1_stream_parse(asn1_stream)) @@ -782,7 +810,7 @@ def test_099__ans1_stream_parse(self): @patch('examples.ca_handler.xca_ca_handler.CAhandler._utf_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._asn1_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._stream_split') - def test_100__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): + def test_111__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): """ __template_parse() - all good """ byte_string = 'foo' mock_split.return_value = (b'foo', b'bar') @@ -795,7 +823,7 @@ def test_100__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): @patch('examples.ca_handler.xca_ca_handler.CAhandler._utf_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._asn1_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._stream_split') - def test_101__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): + def test_112__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): """ __template_parse() - multiple values """ byte_string = 'foo' mock_split.return_value = (b'foo', b'bar') @@ -807,7 +835,7 @@ def test_101__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): @patch('examples.ca_handler.xca_ca_handler.CAhandler._validity_calculate') @patch('examples.ca_handler.xca_ca_handler.CAhandler._utf_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._stream_split') - def test_102__template_parse(self, mock_split, mock_utf, mock_valid): + def test_113__template_parse(self, mock_split, mock_utf, mock_valid): """ __template_parse() - no asn1_stream returned """ byte_string = 'foo' mock_split.return_value = (None, b'bar') @@ -817,7 +845,7 @@ def test_102__template_parse(self, mock_split, mock_utf, mock_valid): @patch('examples.ca_handler.xca_ca_handler.CAhandler._asn1_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._stream_split') - def test_103__template_parse(self, mock_split, mock_asn): + def test_114__template_parse(self, mock_split, mock_asn): """ __template_parse() - no asn1_stream returned """ byte_string = 'foo' mock_split.return_value = (b'foo', None) @@ -825,7 +853,7 @@ def test_103__template_parse(self, mock_split, mock_asn): self.assertEqual(({'foo1': 'bar1'}, {}), self.cahandler._template_parse(byte_string)) @patch('examples.ca_handler.xca_ca_handler.CAhandler._stream_split') - def test_104__template_parse(self, mock_split): + def test_115__template_parse(self, mock_split): """ __template_parse() - no asn1_stream returned """ byte_string = 'foo' mock_split.return_value = (None, None) @@ -835,7 +863,7 @@ def test_104__template_parse(self, mock_split): @patch('examples.ca_handler.xca_ca_handler.CAhandler._utf_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._asn1_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._stream_split') - def test_105__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): + def test_116__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): """ __template_parse() - multiple values replace blank with None""" byte_string = 'foo' mock_split.return_value = (b'foo', b'bar') @@ -848,7 +876,7 @@ def test_105__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): @patch('examples.ca_handler.xca_ca_handler.CAhandler._utf_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._asn1_stream_parse') @patch('examples.ca_handler.xca_ca_handler.CAhandler._stream_split') - def test_106__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): + def test_117__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): """ __template_parse() - multiple values replace blanks with None""" byte_string = 'foo' mock_split.return_value = (b'foo', b'bar') @@ -857,7 +885,7 @@ def test_106__template_parse(self, mock_split, mock_asn, mock_utf, mock_valid): mock_valid.return_value = 'valid' self.assertEqual(({'foo1': 'bar1', 'foo11': 'bar11'}, {'foo2': 'bar2', 'foo21': None, 'foo22': None, 'validity': 'valid'}), self.cahandler._template_parse(byte_string)) - def test_107__template_load(self): + def test_118__template_load(self): """ CAhandler._templatelod - existing template """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.template_name = 'template' @@ -865,114 +893,114 @@ def test_107__template_load(self): template_dic = {'validity': 30, 'validN': '30', 'validMidn': '0', 'validM': '0', 'subKey': '0', 'subAltName': None, 'nsSslServerName': None, 'nsRevocationUrl': None, 'nsRenewalUrl': None, 'nsComment': 'xca certificate', 'nsCertType': '0', 'nsCaPolicyUrl': None, 'nsCARevocationUrl': None, 'nsBaseUrl': None, 'noWellDefinedExpDate': '0', 'kuCritical': '1', 'keyUse': '3', 'issAltName': None, 'ekuCritical': '1', 'eKeyUse': 'serverAuth, clientAuth', 'crlDist': None, 'ca': '0', 'bcCritical': '0', 'basicPath': None, 'authKey': '0', 'authInfAcc': None, 'adv_ext': None} self.assertEqual((dn_dic, template_dic), self.cahandler._template_load()) - def test_108__template_load(self): + def test_119__template_load(self): """ CAhandler._templatelod - not existing template """ self.cahandler.xdb_file = self.dir_path + '/ca/acme2certifier.xdb' self.cahandler.template_name = 'notexist' self.assertEqual(({}, {}), self.cahandler._template_load()) - def test_109__validity_calculate(self): + def test_120__validity_calculate(self): """ CAhandler._validity_calculate() - day value """ template_dic = {'validM': '0', 'validN': '10'} self.assertEqual(10, self.cahandler._validity_calculate(template_dic)) - def test_110__validity_calculate(self): + def test_121__validity_calculate(self): """ CAhandler._validity_calculate() - month value """ template_dic = {'validM': '1', 'validN': '10'} self.assertEqual(300, self.cahandler._validity_calculate(template_dic)) - def test_111__validity_calculate(self): + def test_122__validity_calculate(self): """ CAhandler._validity_calculate() - year value """ template_dic = {'validM': '2', 'validN': '2'} self.assertEqual(730, self.cahandler._validity_calculate(template_dic)) - def test_112__validity_calculate(self): + def test_123__validity_calculate(self): """ CAhandler._validity_calculate() - novalidn """ template_dic = {'validM': '2', 'novalidN': '2'} self.assertEqual(365, self.cahandler._validity_calculate(template_dic)) - def test_113__validity_calculate(self): + def test_124__validity_calculate(self): """ CAhandler._validity_calculate() - novalidn """ template_dic = {'novalidM': '2', 'validN': '2'} self.assertEqual(365, self.cahandler._validity_calculate(template_dic)) - def test_114__kue_generate(self): + def test_125__kue_generate(self): """ CAhandler._kue_generate() - digitalSignature """ kup = 1 self.assertEqual('digitalSignature', self.cahandler._kue_generate(kup)) - def test_115__kue_generate(self): + def test_126__kue_generate(self): """ CAhandler._kue_generate() - nonRepudiation """ kup = 2 self.assertEqual('nonRepudiation', self.cahandler._kue_generate(kup)) - def test_116__kue_generate(self): + def test_127__kue_generate(self): """ CAhandler._kue_generate() - keyEncipherment """ kup = 4 self.assertEqual('keyEncipherment', self.cahandler._kue_generate(kup)) - def test_117__kue_generate(self): + def test_128__kue_generate(self): """ CAhandler._kue_generate() - dataEncipherment """ kup = 8 self.assertEqual('dataEncipherment', self.cahandler._kue_generate(kup)) - def test_118__kue_generate(self): + def test_129__kue_generate(self): """ CAhandler._kue_generate() - keyAgreement """ kup = 16 self.assertEqual('keyAgreement', self.cahandler._kue_generate(kup)) - def test_119__kue_generate(self): + def test_130__kue_generate(self): """ CAhandler._kue_generate() - keyCertSign """ kup = 32 self.assertEqual('keyCertSign', self.cahandler._kue_generate(kup)) - def test_120__kue_generate(self): + def test_131__kue_generate(self): """ CAhandler._kue_generate() - cRLSign """ kup = 64 self.assertEqual('cRLSign', self.cahandler._kue_generate(kup)) - def test_121__kue_generate(self): + def test_132__kue_generate(self): """ CAhandler._kue_generate() - encipherOnly """ kup = 128 self.assertEqual('encipherOnly', self.cahandler._kue_generate(kup)) - def test_122__kue_generate(self): + def test_133__kue_generate(self): """ CAhandler._kue_generate() - encipherOnly """ kup = 256 self.assertEqual('decipherOnly', self.cahandler._kue_generate(kup)) - def test_123__kue_generate(self): + def test_134__kue_generate(self): """ CAhandler._kue_generate() - digitalSignature and nonRepudiation """ kup = 3 self.assertEqual('digitalSignature,nonRepudiation', self.cahandler._kue_generate(kup)) - def test_124__kue_generate(self): + def test_135__kue_generate(self): """ CAhandler._kue_generate() - all """ kup = 511 self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign,encipherOnly,decipherOnly', self.cahandler._kue_generate(kup)) - def test_125__kue_generate(self): + def test_136__kue_generate(self): """ CAhandler._kue_generate() - all """ kup = 0 with self.assertLogs('test_a2c', level='INFO') as lcm: self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,keyAgreement', self.cahandler._kue_generate(kup)) self.assertIn('ERROR:test_a2c:CAhandler._extension_list_generate(): defaulting ku_val to 23', lcm.output) - def test_126__kue_generate(self): + def test_137__kue_generate(self): """ CAhandler._kue_generate() - all """ kup = '0' with self.assertLogs('test_a2c', level='INFO') as lcm: self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,keyAgreement', self.cahandler._kue_generate(kup)) self.assertIn('ERROR:test_a2c:CAhandler._extension_list_generate(): defaulting ku_val to 23', lcm.output) - def test_127__kue_generate(self): + def test_138__kue_generate(self): """ CAhandler._kue_generate() - all """ kup = 'a' with self.assertLogs('test_a2c', level='INFO') as lcm: self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,keyAgreement', self.cahandler._kue_generate(kup)) self.assertIn('ERROR:test_a2c:CAhandler._extension_list_generate(): convert to int failed defaulting ku_val to 23', lcm.output) - def test_125__subject_modify(self): + def test_139__subject_modify(self): """ CAhandler._subject_modify() empty dn_dic """ dn_dic = {} subject = Mock() @@ -990,7 +1018,7 @@ def test_125__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_126__subject_modify(self): + def test_140__subject_modify(self): """ CAhandler._subject_modify() wrong dn_dic """ dn_dic = {'foo': 'bar'} subject = Mock() @@ -1008,7 +1036,7 @@ def test_126__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_127__subject_modify(self): + def test_141__subject_modify(self): """ CAhandler._subject_modify() c included """ dn_dic = {'foo': 'bar', 'countryName': 'co'} subject = Mock() @@ -1026,7 +1054,7 @@ def test_127__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_128__subject_modify(self): + def test_142__subject_modify(self): """ CAhandler._subject_modify() c, st included """ dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st'} subject = Mock() @@ -1044,7 +1072,7 @@ def test_128__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_129__subject_modify(self): + def test_143__subject_modify(self): """ CAhandler._subject_modify() c, st, l included """ dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st', 'localityName': 'lo'} subject = Mock() @@ -1062,7 +1090,7 @@ def test_129__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_130__subject_modify(self): + def test_144__subject_modify(self): """ CAhandler._subject_modify() c, st, l, o included """ dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st', 'localityName': 'lo', 'organizationName': 'or'} subject = Mock() @@ -1080,7 +1108,7 @@ def test_130__subject_modify(self): self.assertEqual('or', rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_131__subject_modify(self): + def test_145__subject_modify(self): """ CAhandler._subject_modify() c, st, l, o included """ dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st', 'localityName': 'lo', 'organizationName': 'or', 'organizationalUnitName': 'ou'} subject = Mock() @@ -1099,7 +1127,7 @@ def test_131__subject_modify(self): self.assertEqual('ou', rc_obj.organizationalUnitName) @patch('OpenSSL.crypto.X509Extension') - def test_132__extension_list_generate(self, mock_crypto): + def test_146__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - empty template """ template_dic = {} cert = 'cert' @@ -1109,7 +1137,7 @@ def test_132__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_133__extension_list_generate(self, mock_crypto): + def test_147__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - wrong template """ template_dic = {'foo': 'bar'} cert = 'cert' @@ -1119,7 +1147,7 @@ def test_133__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_134__extension_list_generate(self, mock_crypto): + def test_148__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - eKeyUse without ekuCritical """ template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse'} cert = 'cert' @@ -1129,7 +1157,7 @@ def test_134__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_135__extension_list_generate(self, mock_crypto): + def test_149__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - eKeyUse with ekuCritical 0 """ template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse', 'ekuCritical': '0'} cert = 'cert' @@ -1139,7 +1167,7 @@ def test_135__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_136__extension_list_generate(self, mock_crypto): + def test_150__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - eKeyUse with ekuCritical 1 """ template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse', 'ekuCritical': '1'} cert = 'cert' @@ -1149,7 +1177,7 @@ def test_136__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_137__extension_list_generate(self, mock_crypto): + def test_151__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - eKeyUse with ekuCritical string """ template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse', 'ekuCritical': 'string'} cert = 'cert' @@ -1160,7 +1188,7 @@ def test_137__extension_list_generate(self, mock_crypto): @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') @patch('OpenSSL.crypto.X509Extension') - def test_138__extension_list_generate(self, mock_crypto, mock_kue): + def test_152__extension_list_generate(self, mock_crypto, mock_kue): """ CAhandler._extension_list_generate() - KeyUse without kuCritical """ template_dic = {'foo': 'bar', 'keyUse': 'keyUse'} cert = 'cert' @@ -1172,7 +1200,7 @@ def test_138__extension_list_generate(self, mock_crypto, mock_kue): @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') @patch('OpenSSL.crypto.X509Extension') - def test_139__extension_list_generate(self, mock_crypto, mock_kue): + def test_153__extension_list_generate(self, mock_crypto, mock_kue): """ CAhandler._extension_list_generate() - KeyUse with kuCritical 0 """ template_dic = {'foo': 'bar', 'keyUse': 'keyUse', 'kuCritical': '0'} cert = 'cert' @@ -1184,7 +1212,7 @@ def test_139__extension_list_generate(self, mock_crypto, mock_kue): @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') @patch('OpenSSL.crypto.X509Extension') - def test_140__extension_list_generate(self, mock_crypto, mock_kue): + def test_154__extension_list_generate(self, mock_crypto, mock_kue): """ CAhandler._extension_list_generate() - KeyUse with kuCritical 1 """ template_dic = {'foo': 'bar', 'keyUse': 'keyUse', 'kuCritical': '1'} cert = 'cert' @@ -1196,7 +1224,7 @@ def test_140__extension_list_generate(self, mock_crypto, mock_kue): @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') @patch('OpenSSL.crypto.X509Extension') - def test_141__extension_list_generate(self, mock_crypto, mock_kue): + def test_155__extension_list_generate(self, mock_crypto, mock_kue): """ CAhandler._extension_list_generate() - KeyUse with kuCritical string """ template_dic = {'foo': 'bar', 'keyUse': 'keyUse', 'kuCritical': 'string'} cert = 'cert' @@ -1207,7 +1235,7 @@ def test_141__extension_list_generate(self, mock_crypto, mock_kue): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_142__extension_list_generate(self, mock_crypto): + def test_156__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - eKeyUse with crlDist """ template_dic = {'foo': 'bar', 'crlDist': 'crlDist'} cert = 'cert' @@ -1217,7 +1245,7 @@ def test_142__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_143__extension_list_generate(self, mock_crypto): + def test_157__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - eKeyUse with crlDist but no value """ template_dic = {'foo': 'bar', 'crlDist': None} cert = 'cert' @@ -1227,7 +1255,7 @@ def test_143__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_144__extension_list_generate(self, mock_crypto): + def test_158__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - basicConstrains without bcCritical """ template_dic = {'foo': 'bar', 'ca': '2'} cert = 'cert' @@ -1237,7 +1265,7 @@ def test_144__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_145__extension_list_generate(self, mock_crypto): + def test_159__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - basicConstrains with bcCritical 0 """ template_dic = {'foo': 'bar', 'ca': '2', 'bcCritical': '0'} cert = 'cert' @@ -1247,7 +1275,7 @@ def test_145__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_146__extension_list_generate(self, mock_crypto): + def test_160__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - basicConstrains with bcCritical 1 """ template_dic = {'foo': 'bar', 'ca': '2', 'bcCritical': '1'} cert = 'cert' @@ -1257,7 +1285,7 @@ def test_146__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_147__extension_list_generate(self, mock_crypto): + def test_161__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - basicConstrains with bcCritical string """ template_dic = {'foo': 'bar', 'ca': '2', 'bcCritical': 'string'} cert = 'cert' @@ -1267,7 +1295,7 @@ def test_147__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_148__extension_list_generate(self, mock_crypto): + def test_162__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - basicConstrains with ca 1 """ template_dic = {'foo': 'bar', 'ca': '1', 'bcCritical': '1'} cert = 'cert' @@ -1277,7 +1305,7 @@ def test_148__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('OpenSSL.crypto.X509Extension') - def test_149__extension_list_generate(self, mock_crypto): + def test_163__extension_list_generate(self, mock_crypto): """ CAhandler._extension_list_generate() - basicConstrains with ca 0 """ template_dic = {'foo': 'bar', 'ca': '0', 'bcCritical': '1'} cert = 'cert' @@ -1287,35 +1315,35 @@ def test_149__extension_list_generate(self, mock_crypto): self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_load') - def test_150__enter__(self, mock_cfg): + def test_164__enter__(self, mock_cfg): """ test enter """ mock_cfg.return_value = True self.cahandler.__enter__() self.assertTrue(mock_cfg.called) @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_load') - def test_151__enter__(self, mock_cfg): + def test_165__enter__(self, mock_cfg): """ test enter """ self.cahandler.xdb_file = self.dir_path + '/ca/est_proxy.xdb' mock_cfg.return_value = True self.cahandler.__enter__() self.assertFalse(mock_cfg.called) - def test_152_trigger(self): + def test_166_trigger(self): """ test trigger """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) - def test_153_poll(self): + def test_167_poll(self): """ test poll """ self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier','csr')) - def test_154_stub_func(self): + def test_168_stub_func(self): """ test stubfunc """ self.assertEqual('parameter', self.cahandler._stub_func('parameter')) @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_insert') @patch('examples.ca_handler.xca_ca_handler.CAhandler._item_insert') - def test_155__store_cert(self, mock_i_insert, mock_c_insert): + def test_169__store_cert(self, mock_i_insert, mock_c_insert): """ test insert """ mock_i_insert.return_value = 1 mock_c_insert.return_value = 2 @@ -1326,7 +1354,7 @@ def test_155__store_cert(self, mock_i_insert, mock_c_insert): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_156_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_170_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search """ mock_dicfrow.return_value = {'foo': 'bar'} mock_open.return_value = True @@ -1340,7 +1368,7 @@ def test_156_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_157_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_171_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search dicfromrow throws exception """ mock_dicfrow.side_effect = Exception('exc_dicfromrow') mock_open.return_value = True @@ -1354,7 +1382,7 @@ def test_157_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_166_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_172_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search """ mock_dicfrow.return_value = {'foo': 'bar'} mock_open.return_value = True @@ -1368,7 +1396,7 @@ def test_166_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_167_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_173_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search dicfromrow throws exception """ mock_dicfrow.side_effect = Exception('exc_dicfromrow') mock_open.return_value = True @@ -1381,7 +1409,7 @@ def test_167_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_insert') @patch('examples.ca_handler.xca_ca_handler.CAhandler._item_insert') - def test_165__store_cert(self, mock_i_insert, mock_c_insert): + def test_174__store_cert(self, mock_i_insert, mock_c_insert): """ test insert """ mock_i_insert.return_value = 1 mock_c_insert.return_value = 2 @@ -1390,14 +1418,14 @@ def test_165__store_cert(self, mock_i_insert, mock_c_insert): self.assertTrue(mock_c_insert.called) @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_168_enroll(self, mock_chk): + def test_175_enroll(self, mock_chk): """ enroll test error returned from config_check""" mock_chk.return_value = 'error' self.assertEqual(('error', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_169_enroll(self, mock_chk, mock_nameget): + def test_176_enroll(self, mock_chk, mock_nameget): """ enroll test error returned no request name returned """ mock_chk.return_value = None mock_nameget.return_value = None @@ -1407,7 +1435,7 @@ def test_169_enroll(self, mock_chk, mock_nameget): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_170_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + def test_177_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): """ enroll test error returned from ca_load failed """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1419,7 +1447,7 @@ def test_170_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_171_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + def test_178_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): """ enroll test error returned from ca_load failed """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1431,7 +1459,7 @@ def test_171_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_172_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + def test_179_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): """ enroll test error returned from ca_load failed """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1450,7 +1478,7 @@ def test_172_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_173_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + def test_180_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): """ enroll test """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1483,7 +1511,7 @@ def test_173_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_175_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + def test_181_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): """ enroll test - default cert validity """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1517,7 +1545,7 @@ def test_175_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_174_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + def test_182_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): """ enroll test - rewrite CN """ mock_chk.return_value = None mock_nameget.return_value = 'reqname' @@ -1553,7 +1581,7 @@ def test_174_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_176_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): + def test_183_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): """ enroll test - template load validity """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1593,7 +1621,7 @@ def test_176_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_177_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): + def test_184_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): """ enroll test - template load validity """ mock_chk.return_value = None mock_nameget.return_value = 'name' From c38d5402cee152f43914cceae85f1f6ce93d40c1 Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 18 May 2021 12:57:42 +0200 Subject: [PATCH 12/51] [tst] unittests --- acme/order.py | 10 +- acme/trigger.py | 9 +- test/test_order.py | 365 ++++++++++++++++++++++++++++++++++++------- test/test_trigger.py | 96 +++++++++++- 4 files changed, 413 insertions(+), 67 deletions(-) diff --git a/acme/order.py b/acme/order.py index 427facd0..1f835f93 100644 --- a/acme/order.py +++ b/acme/order.py @@ -100,7 +100,10 @@ def _config_load(self): self.tnauthlist_support = config_dic.getboolean('Order', 'tnauthlist_support', fallback=False) self.expiry_check_disable = config_dic.getboolean('Order', 'expiry_check_disable', fallback=False) if 'retry_after_timeout' in config_dic['Order']: - self.retry_after = config_dic['Order']['retry_after_timeout'] + try: + self.retry_after = int(config_dic['Order']['retry_after_timeout']) + except BaseException: + self.logger.warning('Order._config_load(): failed to parse retry_after: {0}'.format(config_dic['Order']['retry_after_timeout'])) if 'validity' in config_dic['Order']: try: self.validity = int(config_dic['Order']['validity']) @@ -279,7 +282,10 @@ def _lookup(self, order_name): if tmp_dic['notafter'] != 0: order_dic['notAfter'] = uts_to_date_utc(tmp_dic['notafter']) if 'identifiers' in tmp_dic: - order_dic['identifiers'] = json.loads(tmp_dic['identifiers']) + try: + order_dic['identifiers'] = json.loads(tmp_dic['identifiers']) + except BaseException: + self.logger.error('Order.lookup(): error while parsing the identifier {0}'.format(tmp_dic['identifiers'])) try: authz_list = self.dbstore.authorization_lookup('order__name', order_name, ['name', 'status__name']) except BaseException as err_: diff --git a/acme/trigger.py b/acme/trigger.py index 70c6922a..a743b0c1 100644 --- a/acme/trigger.py +++ b/acme/trigger.py @@ -58,8 +58,13 @@ def _config_load(self): if 'CAhandler' in config_dic and 'handler_file' in config_dic['CAhandler']: try: ca_handler_module = importlib.import_module(ca_handler_get(self.logger, config_dic['CAhandler']['handler_file'])) - except BaseException: - ca_handler_module = importlib.import_module('acme.ca_handler') + except BaseException as err_: + self.logger.critical('Certificate._config_load(): loading CAhandler configured in cfg failed with err: {0}'.format(err_)) + try: + ca_handler_module = importlib.import_module('acme.ca_handler') + except BaseException as err_: + ca_handler_module = None + self.logger.critical('Certificate._config_load(): loading default CAhandler failed with err: {0}'.format(err_)) else: if 'CAhandler' in config_dic: ca_handler_module = importlib.import_module('acme.ca_handler') diff --git a/test/test_order.py b/test/test_order.py index 218105cd..e1fa27bb 100644 --- a/test/test_order.py +++ b/test/test_order.py @@ -5,6 +5,7 @@ import unittest import sys import importlib +import configparser from unittest.mock import patch, MagicMock sys.path.insert(0, '.') @@ -217,7 +218,55 @@ def test_020_order__lookup(self, mock_oinfo): self.assertEqual(e_result, self.order._lookup('foo')) @patch('acme.order.Order._info') - def test_021_order__csr_process(self, mock_oinfo): + def test_021_order__lookup(self, mock_oinfo): + """ test order lookup correct identifier for oder info""" + self.order.dbstore.authorization_lookup.return_value = 'foo' + mock_oinfo.return_value = {'status' : 'status_value', 'expires' : 1543640400, 'notbefore' : 1543640400, 'notafter' : 1543640400, 'identifiers': '{"foo": "bar"}'} + e_result = {'status': 'status_value', 'authorizations': [], 'expires': '2018-12-01T05:00:00Z', 'notAfter': '2018-12-01T05:00:00Z', 'notBefore': '2018-12-01T05:00:00Z', 'identifiers': {'foo': 'bar'}} + self.assertEqual(e_result, self.order._lookup('foo')) + + @patch('acme.order.Order._info') + def test_022_order__lookup(self, mock_oinfo): + """ test order lookup incorrect identifier for oder info""" + self.order.dbstore.authorization_lookup.return_value = 'foo' + mock_oinfo.return_value = {'status' : 'status_value', 'expires' : 1543640400, 'notbefore' : 1543640400, 'notafter' : 1543640400, 'identifiers': 'wrongvalue'} + e_result = {'status': 'status_value', 'authorizations': [], 'expires': '2018-12-01T05:00:00Z', 'notAfter': '2018-12-01T05:00:00Z', 'notBefore': '2018-12-01T05:00:00Z'} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(e_result, self.order._lookup('foo')) + self.assertIn('ERROR:test_a2c:Order.lookup(): error while parsing the identifier wrongvalue', lcm.output) + + @patch('acme.order.Order._update') + @patch('acme.order.Order._info') + def test_023_order__lookup(self, mock_oinfo, mock_update): + """ test order lookup correct identifier for oder info status - pending order-update """ + self.order.dbstore.authorization_lookup.return_value = [{'name': 'name', 'status__name': 'valid'}] + mock_oinfo.return_value = {'status' : 'pending', 'expires' : 1543640400, 'notbefore' : 1543640400, 'notafter' : 1543640400, 'identifiers': '{"foo": "bar"}'} + e_result = {'status': 'pending', 'authorizations': ['http://tester.local/acme/authz/name'], 'expires': '2018-12-01T05:00:00Z', 'notAfter': '2018-12-01T05:00:00Z', 'notBefore': '2018-12-01T05:00:00Z', 'identifiers': {'foo': 'bar'}} + self.assertEqual(e_result, self.order._lookup('foo')) + self.assertTrue(mock_update.called) + + @patch('acme.order.Order._update') + @patch('acme.order.Order._info') + def test_024_order__lookup(self, mock_oinfo, mock_update): + """ test order lookup correct identifier for oder info status - pending order-update """ + self.order.dbstore.authorization_lookup.return_value = [{'name': 'name', 'status__name': 'valid'}] + mock_oinfo.return_value = {'status' : 'notpending', 'expires' : 1543640400, 'notbefore' : 1543640400, 'notafter' : 1543640400, 'identifiers': '{"foo": "bar"}'} + e_result = {'status': 'notpending', 'authorizations': ['http://tester.local/acme/authz/name'], 'expires': '2018-12-01T05:00:00Z', 'notAfter': '2018-12-01T05:00:00Z', 'notBefore': '2018-12-01T05:00:00Z', 'identifiers': {'foo': 'bar'}} + self.assertEqual(e_result, self.order._lookup('foo')) + self.assertFalse(mock_update.called) + + @patch('acme.order.Order._update') + @patch('acme.order.Order._info') + def test_025_order__lookup(self, mock_oinfo, mock_update): + """ test order lookup correct identifier for oder info status - invalid statusname """ + self.order.dbstore.authorization_lookup.return_value = [{'name': 'name', 'status__name': 'invalid'}] + mock_oinfo.return_value = {'status' : 'pending', 'expires' : 1543640400, 'notbefore' : 1543640400, 'notafter' : 1543640400, 'identifiers': '{"foo": "bar"}'} + e_result = {'status': 'pending', 'authorizations': ['http://tester.local/acme/authz/name'], 'expires': '2018-12-01T05:00:00Z', 'notAfter': '2018-12-01T05:00:00Z', 'notBefore': '2018-12-01T05:00:00Z', 'identifiers': {'foo': 'bar'}} + self.assertEqual(e_result, self.order._lookup('foo')) + self.assertFalse(mock_update.called) + + @patch('acme.order.Order._info') + def test_026_order__csr_process(self, mock_oinfo): """ test order prcoess_csr with empty order_dic """ mock_oinfo.return_value = {} self.assertEqual((400, 'urn:ietf:params:acme:error:unauthorized', 'order: order_name not found'), self.order._csr_process('order_name', 'csr')) @@ -225,7 +274,7 @@ def test_021_order__csr_process(self, mock_oinfo): @patch('importlib.import_module') @patch('acme.certificate.Certificate.store_csr') @patch('acme.order.Order._info') - def test_022_order__csr_process(self, mock_oinfo, mock_certname, mock_import): + def test_027_order__csr_process(self, mock_oinfo, mock_certname, mock_import): """ test order prcoess_csr with failed csr dbsave""" mock_oinfo.return_value = {'foo', 'bar'} mock_certname.return_value = None @@ -236,7 +285,7 @@ def test_022_order__csr_process(self, mock_oinfo, mock_certname, mock_import): @patch('acme.certificate.Certificate.enroll_and_store') @patch('acme.certificate.Certificate.store_csr') @patch('acme.order.Order._info') - def test_023_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mock_import): + def test_028_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mock_import): """ test order prcoess_csr with failed cert enrollment""" mock_oinfo.return_value = {'foo', 'bar'} mock_certname.return_value = 'foo' @@ -248,7 +297,7 @@ def test_023_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mo @patch('acme.certificate.Certificate.enroll_and_store') @patch('acme.certificate.Certificate.store_csr') @patch('acme.order.Order._info') - def test_024_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mock_import): + def test_029_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mock_import): """ test order prcoess_csr with successful cert enrollment""" mock_oinfo.return_value = {'foo', 'bar'} mock_certname.return_value = 'foo' @@ -256,35 +305,35 @@ def test_024_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mo mock_import.return_value = importlib.import_module('examples.ca_handler.skeleton_ca_handler') self.assertEqual((200, 'foo', None), self.order._csr_process('order_name', 'csr')) - def test_025_order__name_get(self): + def test_030_order__name_get(self): """ Order.name_get() http""" self.assertEqual('foo', self.order._name_get('http://tester.local/acme/order/foo')) - def test_026_order__name_get(self): + def test_031_order__name_get(self): """ Order.name_get() http with further path (finalize)""" self.assertEqual('foo', self.order._name_get('http://tester.local/acme/order/foo/bar')) - def test_027_order__name_get(self): + def test_032_order__name_get(self): """ Order.name_get() http with parameters""" self.assertEqual('foo', self.order._name_get('http://tester.local/acme/order/foo?bar')) - def test_028_order__name_get(self): + def test_033_order__name_get(self): """ Order.name_get() http with key/value parameters""" self.assertEqual('foo', self.order._name_get('http://tester.local/acme/order/foo?key=value')) - def test_029_order__name_get(self): + def test_034_order__name_get(self): """ Order.name_get() https with key/value parameters""" self.assertEqual('foo', self.order._name_get('https://tester.local/acme/order/foo?key=value')) @patch('acme.message.Message.check') - def test_030_order_parse(self, mock_mcheck): + def test_035_order_parse(self, mock_mcheck): """ Order.parse() failed bcs. of failed message check """ mock_mcheck.return_value = (400, 'message', 'detail', None, None, 'account_name') message = '{"foo" : "bar"}' self.assertEqual({'header': {}, 'code': 400, 'data': {'detail': 'detail', 'message': 'message', 'status': 400}}, self.order.parse(message)) @patch('acme.message.Message.check') - def test_031_order_parse(self, mock_mcheck): + def test_036_order_parse(self, mock_mcheck): """ Order.parse() failed bcs. no url key in protected """ mock_mcheck.return_value = (200, None, None, {'foo_protected' : 'bar_protected'}, {"foo_payload" : "bar_payload"}, 'account_name') message = '{"foo" : "bar"}' @@ -292,7 +341,7 @@ def test_031_order_parse(self, mock_mcheck): @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_032_order_parse(self, mock_mcheck, mock_oname): + def test_037_order_parse(self, mock_mcheck, mock_oname): """ Order.parse() name_get failed """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = None @@ -302,7 +351,7 @@ def test_032_order_parse(self, mock_mcheck, mock_oname): @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_033_order_parse(self, mock_mcheck, mock_oname, mock_lookup): + def test_038_order_parse(self, mock_mcheck, mock_oname, mock_lookup): """ Order.parse() failed as order lookup failed """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = 'foo' @@ -314,7 +363,7 @@ def test_033_order_parse(self, mock_mcheck, mock_oname, mock_lookup): @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_034_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process): + def test_039_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process): """ Order.parse() succ, oder process returned non 200 """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = 'foo' @@ -328,7 +377,7 @@ def test_034_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_proces @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_035_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): + def test_040_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): """ Order.parse() succ, oder process returned 200 and no certname """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = 'foo' @@ -343,7 +392,7 @@ def test_035_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_proces @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_036_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): + def test_041_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): """ Order.parse() succ, oder process returned 200 and certname and valid status """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = 'foo' @@ -358,7 +407,7 @@ def test_036_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_proces @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_037_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): + def test_042_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): """ Order.parse() succ, oder process returned 200 and certname without status """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = 'foo' @@ -373,7 +422,7 @@ def test_037_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_proces @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_038_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): + def test_043_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): """ Order.parse() succ, oder process returned 200 and certname and non-valid status """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = 'foo' @@ -383,80 +432,80 @@ def test_038_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_proces message = '{"foo" : "bar"}' self.assertEqual({'code': 200, 'data': {'finalize': 'http://tester.local/acme/order/foo/finalize', 'foo': 'bar', 'status': 'foobar'}, 'header': {'Location': 'http://tester.local/acme/order/foo', 'Replay-Nonce': 'nonce'}}, self.order.parse(message)) - def test_039_order__identifiers_check(self): + def test_044_order__identifiers_check(self): """ order identifers check with empty identifer list""" self.assertEqual('urn:ietf:params:acme:error:malformed', self.order._identifiers_check([])) - def test_040_order__identifiers_check(self): + def test_045_order__identifiers_check(self): """ order identifers check with string identifier """ self.assertEqual('urn:ietf:params:acme:error:malformed', self.order._identifiers_check('foo')) - def test_041_order__identifiers_check(self): + def test_046_order__identifiers_check(self): """ order identifers check with dictionary identifier """ self.assertEqual('urn:ietf:params:acme:error:malformed', self.order._identifiers_check({'type': 'dns', 'value': 'foo.bar'})) - def test_042_order__identifiers_check(self): + def test_047_order__identifiers_check(self): """ order identifers check with correct identifer but case-insensitive """ self.assertEqual('urn:ietf:params:acme:error:malformed', self.order._identifiers_check([{'Type': 'dns', 'value': 'value'}])) - def test_043_order__identifiers_check(self): + def test_048_order__identifiers_check(self): """ order identifers check with wrong identifer in list""" self.assertEqual('urn:ietf:params:acme:error:unsupportedIdentifier', self.order._identifiers_check([{'type': 'foo', 'value': 'value'}])) - def test_044_order__identifiers_check(self): + def test_049_order__identifiers_check(self): """ order identifers check with correct identifer in list""" self.assertEqual(None, self.order._identifiers_check([{'type': 'dns', 'value': 'value'}])) - def test_045_order__identifiers_check(self): + def test_050_order__identifiers_check(self): """ order identifers check with two identifers in list (one wrong) """ self.assertEqual('urn:ietf:params:acme:error:unsupportedIdentifier', self.order._identifiers_check([{'type': 'dns', 'value': 'value'}, {'type': 'foo', 'value': 'value'}])) - def test_046_order__identifiers_check(self): + def test_051_order__identifiers_check(self): """ order identifers check with two identifers in list (one wrong) """ self.assertEqual('urn:ietf:params:acme:error:unsupportedIdentifier', self.order._identifiers_check([{'type': 'foo', 'value': 'value'}, {'type': 'dns', 'value': 'value'}])) - def test_047_order__identifiers_check(self): + def test_052_order__identifiers_check(self): """ order identifers check with two identifers in list (one wrong) """ self.assertEqual(None, self.order._identifiers_check([{'type': 'dns', 'value': 'value'}, {'type': 'dns', 'value': 'value'}])) - def test_048_order__identifiers_check(self): + def test_053_order__identifiers_check(self): """ order identifers check with tnauthlist identifier and support false """ self.order.tnauthlist_support = False self.assertEqual('urn:ietf:params:acme:error:unsupportedIdentifier', self.order._identifiers_check([{'type': 'TNAuthList', 'value': 'value'}, {'type': 'dns', 'value': 'value'}])) - def test_049_order__identifiers_check(self): + def test_054_order__identifiers_check(self): """ order identifers check with tnauthlist identifier and support True """ self.order.tnauthlist_support = True self.assertEqual(None, self.order._identifiers_check([{'type': 'TNAuthList', 'value': 'value'}, {'type': 'dns', 'value': 'value'}])) - def test_050_order__identifiers_check(self): + def test_055_order__identifiers_check(self): """ order identifers check with tnauthlist identifier and support True """ self.order.tnauthlist_support = True self.assertEqual(None, self.order._identifiers_check([{'type': 'TNAuthList', 'value': 'value'}])) - def test_051_order__identifiers_check(self): + def test_056_order__identifiers_check(self): """ order identifers check with tnauthlist identifier a wrong identifer and support True """ self.order.tnauthlist_support = True self.assertEqual('urn:ietf:params:acme:error:unsupportedIdentifier', self.order._identifiers_check([{'type': 'TNAuthList', 'value': 'value'}, {'type': 'type', 'value': 'value'}])) - def test_052_order__identifiers_check(self): + def test_057_order__identifiers_check(self): """ order identifers check with wrong identifer in list and tnauthsupport true""" self.order.tnauthlist_support = True self.assertEqual('urn:ietf:params:acme:error:unsupportedIdentifier', self.order._identifiers_check([{'type': 'foo', 'value': 'value'}])) - def test_053_order__identifiers_check(self): + def test_058_order__identifiers_check(self): """ order identifers check with correct identifer in list and tnauthsupport true""" self.order.tnauthlist_support = True self.assertEqual(None, self.order._identifiers_check([{'type': 'dns', 'value': 'value'}])) - def test_054_order__process(self): + def test_059_order__process(self): """ Order.prcoess() without url in protected header """ order_name = 'order_name' protected = 'protected' payload = 'payload' self.assertEqual((400, 'urn:ietf:params:acme:error:malformed', 'url is missing in protected', None), self.order._process(order_name, protected, payload)) - def test_055_order__process(self): + def test_060_order__process(self): """ Order.prcoess() polling request with failed certificate lookup """ order_name = 'order_name' protected = {'url': 'foo'} @@ -464,7 +513,7 @@ def test_055_order__process(self): self.order.dbstore.certificate_lookup.return_value = {} self.assertEqual((200, None, None, None), self.order._process(order_name, protected, payload)) - def test_056_order__process(self): + def test_061_order__process(self): """ Order.prcoess() polling request with successful certificate lookup """ order_name = 'order_name' protected = {'url': 'foo'} @@ -473,7 +522,7 @@ def test_056_order__process(self): self.assertEqual((200, None, None, 'cert_name'), self.order._process(order_name, protected, payload)) @patch('acme.order.Order._info') - def test_057_order__process(self, mock_info): + def test_062_order__process(self, mock_info): """ Order.prcoess() finalize request with empty orderinfo """ mock_info.return_value = {} order_name = 'order_name' @@ -482,7 +531,7 @@ def test_057_order__process(self, mock_info): self.assertEqual((403, 'urn:ietf:params:acme:error:orderNotReady', 'Order is not ready', None), self.order._process(order_name, protected, payload)) @patch('acme.order.Order._info') - def test_058_order__process(self, mock_info): + def test_063_order__process(self, mock_info): """ Order.prcoess() finalize request with orderinfo without status""" mock_info.return_value = {'foo': 'bar'} order_name = 'order_name' @@ -491,7 +540,7 @@ def test_058_order__process(self, mock_info): self.assertEqual((403, 'urn:ietf:params:acme:error:orderNotReady', 'Order is not ready', None), self.order._process(order_name, protected, payload)) @patch('acme.order.Order._info') - def test_059_order__process(self, mock_info): + def test_064_order__process(self, mock_info): """ Order.prcoess() finalize request with orderinfo with wrong status""" mock_info.return_value = {'status': 'bar'} order_name = 'order_name' @@ -500,7 +549,7 @@ def test_059_order__process(self, mock_info): self.assertEqual((403, 'urn:ietf:params:acme:error:orderNotReady', 'Order is not ready', None), self.order._process(order_name, protected, payload)) @patch('acme.order.Order._info') - def test_060_order__process(self, mock_info): + def test_065_order__process(self, mock_info): """ Order.prcoess() finalize request without CSR """ mock_info.return_value = {'status': 'ready'} order_name = 'order_name' @@ -510,7 +559,7 @@ def test_060_order__process(self, mock_info): @patch('acme.order.Order._csr_process') @patch('acme.order.Order._info') - def test_061_order__process(self, mock_info, mock_process_csr): + def test_066_order__process(self, mock_info, mock_process_csr): """ Order.prcoess() finalize request with CSR but csr_process failed """ mock_info.return_value = {'status': 'ready'} order_name = 'order_name' @@ -522,7 +571,7 @@ def test_061_order__process(self, mock_info, mock_process_csr): @patch('acme.order.Order._update') @patch('acme.order.Order._csr_process') @patch('acme.order.Order._info') - def test_062_order__process(self, mock_info, mock_process_csr, mock_update): + def test_067_order__process(self, mock_info, mock_process_csr, mock_update): """ Order.prcoess() finalize request with CSR but csr_process failed """ mock_info.return_value = {'status': 'ready'} order_name = 'order_name' @@ -531,12 +580,13 @@ def test_062_order__process(self, mock_info, mock_process_csr, mock_update): mock_process_csr.return_value = (200, 'cert_name', 'detail') mock_update.return_value = None self.assertEqual((200, None, 'detail', 'cert_name'), self.order._process(order_name, protected, payload)) + self.assertTrue(mock_update.called) @patch('importlib.import_module') @patch('acme.certificate.Certificate.enroll_and_store') @patch('acme.certificate.Certificate.store_csr') @patch('acme.order.Order._info') - def test_063_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mock_import): + def test_068_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mock_import): """ test order prcoess_csr with failed cert enrollment with internal error (response code must be corrected by 500)""" mock_oinfo.return_value = {'foo', 'bar'} mock_certname.return_value = 'foo' @@ -549,7 +599,7 @@ def test_063_order__csr_process(self, mock_oinfo, mock_certname, mock_enroll, mo @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_064_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): + def test_069_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): """ Order.parse() succ, oder process returned 200 and certname processing status default retry after-header """ mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') mock_oname.return_value = 'foo' @@ -564,7 +614,7 @@ def test_064_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_proces @patch('acme.order.Order._lookup') @patch('acme.order.Order._name_get') @patch('acme.message.Message.check') - def test_065_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): + def test_070_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_process, mock_nnonce): """ Order.parse() succ, oder process returned 200 and certname processing status configurable retry after-header """ self.order.retry_after = 60 mock_mcheck.return_value = (200, None, None, {'url' : 'bar_url/finalize'}, {"foo_payload" : "bar_payload"}, 'account_name') @@ -575,38 +625,38 @@ def test_065_order_parse(self, mock_mcheck, mock_oname, mock_lookup, mock_proces message = '{"foo" : "bar"}' self.assertEqual({'code': 200, 'data': {'finalize': 'http://tester.local/acme/order/foo/finalize', 'foo': 'bar', 'status': 'processing'}, 'header': {'Location': 'http://tester.local/acme/order/foo', 'Replay-Nonce': 'nonce', 'Retry-After': '60'}}, self.order.parse(message)) - def test_066_order_invalidate(self): + def test_071_order_invalidate(self): """ test Order.invalidate() empty order list """ self.order.dbstore.orders_invalid_search.return_value = [] self.assertEqual((['id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'], []), self.order.invalidate()) - def test_067_order_invalidate(self): + def test_072_order_invalidate(self): """ test Certificate._fieldlist_normalize() - wrong return list (no status__name included) """ self.order.dbstore.orders_invalid_search.return_value = [{'foo': 'bar'}] self.assertEqual((['id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'], []), self.order.invalidate()) - def test_068_order_invalidate(self): + def test_073_order_invalidate(self): """ test Certificate._fieldlist_normalize() - no name but status__name """ self.order.dbstore.orders_invalid_search.return_value = [{'foo': 'bar', 'status__name': 'foo'}] self.assertEqual((['id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'], []), self.order.invalidate()) - def test_069_order_invalidate(self): + def test_074_order_invalidate(self): """ test Certificate._fieldlist_normalize() - name but no status__name """ self.order.dbstore.orders_invalid_search.return_value = [{'foo': 'bar', 'name': 'foo'}] self.assertEqual((['id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'], []), self.order.invalidate()) - def test_070_order_invalidate(self): + def test_075_order_invalidate(self): """ test Certificate._fieldlist_normalize() - name and status__name but invalid """ self.order.dbstore.orders_invalid_search.return_value = [{'foo': 'bar', 'name': 'foo', 'status__name': 'invalid'}] self.assertEqual((['id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'], []), self.order.invalidate()) - def test_071_order_invalidate(self): + def test_076_order_invalidate(self): """ test Certificate._fieldlist_normalize() - name and status__name but invalid """ self.order.dbstore.orders_invalid_search.return_value = [{'foo': 'bar', 'name': 'foo', 'status__name': 'foobar'}] self.assertEqual((['id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'], [{'foo': 'bar', 'name': 'foo', 'status__name': 'foobar'}]), self.order.invalidate()) @patch('acme.order.Order._identifiers_check') - def test_072_order__add(self, mock_idchk): + def test_077_order__add(self, mock_idchk): """ test Order._add - dbstore.authorization_add() raises an exception """ self.order.dbstore.authorization_add.side_effect = Exception('exc_order_add') self.order.dbstore.order_add.return_value = 'oid' @@ -616,7 +666,7 @@ def test_072_order__add(self, mock_idchk): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._add() authz: exc_order_add', lcm.output) @patch('acme.order.Order._identifiers_check') - def test_073_order__add(self, mock_idchk): + def test_078_order__add(self, mock_idchk): """ test Order._add - dbstore.order_add() raises an exception """ self.order.dbstore.order_add.side_effect = Exception('exc_order_add') mock_idchk.return_value = False @@ -624,21 +674,21 @@ def test_073_order__add(self, mock_idchk): self.order._add({'foo': 'bar', 'identifiers': 'identifiers'}, 'aname') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._add() order: exc_order_add', lcm.output) - def test_074_order__info(self): + def test_079_order__info(self): """ test Order._info - dbstore.order_lookup() raises an exception """ self.order.dbstore.order_lookup.side_effect = Exception('exc_order_info') with self.assertLogs('test_a2c', level='INFO') as lcm: self.order._info('oname') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._info(): exc_order_info', lcm.output) - def test_075_order__process(self): + def test_080_order__process(self): """ test Order._process - dbstore.order_lookup() raises an exception """ self.order.dbstore.certificate_lookup.side_effect = Exception('exc_order_process') with self.assertLogs('test_a2c', level='INFO') as lcm: self.order._process('oname', {'url': 'url'}, 'payload') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._process(): exc_order_process', lcm.output) - def test_076_order__update(self): + def test_081_order__update(self): """ test Order._update - dbstore.order_update() raises an exception """ self.order.dbstore.order_update.side_effect = Exception('exc_order_upd') with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -646,7 +696,7 @@ def test_076_order__update(self): self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._update(): exc_order_upd', lcm.output) @patch('acme.order.Order._info') - def test_077_order__lookup(self, mock_info): + def test_082_order__lookup(self, mock_info): """ test Order._lookup - dbstore.authorization_lookup() raises an exception """ self.order.dbstore.authorization_lookup.side_effect = Exception('exc_authz_lookup') mock_info.return_value = {'status': 'valid'} @@ -654,7 +704,7 @@ def test_077_order__lookup(self, mock_info): self.order._lookup('oname') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._lookup(): exc_authz_lookup', lcm.output) - def test_078_order_invalidate(self): + def test_083_order_invalidate(self): """ test Order.invalidate - dbstore.order_update() raises an exception """ self.order.dbstore.order_update.side_effect = Exception('exc_order_upd') self.order.dbstore.order_invalid_search.return_value = ['foo'] @@ -663,7 +713,7 @@ def test_078_order_invalidate(self): self.order.invalidate(timestamp) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._invalidate() upd: exc_order_upd', lcm.output) - def test_079_order_invalidate(self): + def test_084_order_invalidate(self): """ test Order.invalidate - dbstore.order_update() raises an exception """ self.order.dbstore.orders_invalid_search.side_effect = Exception('exc_order_search') timestamp = 1543640400 @@ -671,5 +721,202 @@ def test_079_order_invalidate(self): self.order.invalidate(timestamp) self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Order._invalidate() search: exc_order_search', lcm.output) + @patch('acme.order.Order._config_load') + def test_085__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.order.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('acme.order.load_config') + def test_086_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + + @patch('acme.order.load_config') + def test_087_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + + @patch('acme.order.load_config') + def test_088_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': False} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + + @patch('acme.order.load_config') + def test_089_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': True} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertTrue(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_090_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'expiry_check_disable': False} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_091_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'expiry_check_disable': True} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertTrue(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_092_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'retry_after_timeout': 1200} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(1200, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_093_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'retry_after_timeout': '1200'} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(1200, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_094_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'retry_after_timeout': 'foo'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + self.assertIn('WARNING:test_a2c:Order._config_load(): failed to parse retry_after: foo', lcm.output) + + @patch('acme.order.load_config') + def test_095_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'validity': 1200} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(1200, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_096_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'validity': '1200'} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(1200, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_097_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Order'] = {'validity': 'foo'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + self.assertIn('WARNING:test_a2c:Order._config_load(): failed to parse validity: foo', lcm.output) + + @patch('acme.order.load_config') + def test_098_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'validity': 1200} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(1200, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_099_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'validity': '1200'} + mock_load_cfg.return_value = parser + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(1200, self.order.authz_validity) + + @patch('acme.order.load_config') + def test_100_config_load(self, mock_load_cfg): + """ test _config_load """ + parser = configparser.ConfigParser() + parser['Authorization'] = {'validity': 'foo'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.order._config_load() + self.assertFalse(self.order.tnauthlist_support) + self.assertFalse(self.order.expiry_check_disable) + self.assertEqual(600, self.order.retry_after) + self.assertEqual(86400, self.order.validity) + self.assertEqual(86400, self.order.authz_validity) + self.assertIn('WARNING:test_a2c:Order._config_load(): failed to parse authz validity: foo', lcm.output) + + + if __name__ == '__main__': unittest.main() diff --git a/test/test_trigger.py b/test/test_trigger.py index 5c23f804..61c6a39e 100644 --- a/test/test_trigger.py +++ b/test/test_trigger.py @@ -5,6 +5,7 @@ import unittest import sys import importlib +import configparser from unittest.mock import patch, MagicMock, Mock sys.path.insert(0, '.') @@ -189,6 +190,22 @@ def test_016_trigger__payload_process(self, mock_cobystr, mock_der2pem, mock_b64 @patch('acme.trigger.cert_der2pem') @patch('acme.trigger.convert_byte_to_string') def test_017_trigger__payload_process(self, mock_cobystr, mock_der2pem, mock_b64dec, mock_lookup): + """ Trigger._payload_process() _certname.lookup() returned empty list """ + payload = {'payload': 'foo'} + ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') + self.trigger.cahandler = ca_handler_module.CAhandler + self.trigger.cahandler.trigger = Mock(return_value=('error', 'bundle', 'raw')) + mock_der2pem.return_value = 'der2pem' + mock_cobystr.return_value = 'cert_pem' + mock_b64dec.return_value = 'b64dec' + mock_lookup.return_value = [] + self.assertEqual((400, 'certificate_name lookup failed', None), self.trigger._payload_process(payload)) + + @patch('acme.trigger.Trigger._certname_lookup') + @patch('acme.trigger.b64_decode') + @patch('acme.trigger.cert_der2pem') + @patch('acme.trigger.convert_byte_to_string') + def test_018_trigger__payload_process(self, mock_cobystr, mock_der2pem, mock_b64dec, mock_lookup): """ Trigger._payload_process() without certificate_name """ payload = {'payload': 'foo'} ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') @@ -205,7 +222,7 @@ def test_017_trigger__payload_process(self, mock_cobystr, mock_der2pem, mock_b64 @patch('acme.trigger.b64_decode') @patch('acme.trigger.cert_der2pem') @patch('acme.trigger.convert_byte_to_string') - def test_018_trigger__payload_process(self, mock_cobystr, mock_der2pem, mock_b64dec, mock_lookup): + def test_019_trigger__payload_process(self, mock_cobystr, mock_der2pem, mock_b64dec, mock_lookup): """ Trigger._payload_process() without certificate_name """ payload = {'payload': 'foo'} ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') @@ -221,7 +238,7 @@ def test_018_trigger__payload_process(self, mock_cobystr, mock_der2pem, mock_b64 @patch('acme.trigger.cert_der2pem') @patch('acme.trigger.Trigger._certname_lookup') @patch('acme.trigger.convert_byte_to_string') - def test_019_trigger__payload_process(self, mock_cobystr, mock_lookup, mock_der2pem, mock_b64dec): + def test_020_trigger__payload_process(self, mock_cobystr, mock_lookup, mock_der2pem, mock_b64dec): """ test Trigger._payload_process - dbstore.order_update() raises an exception """ ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') self.trigger.cahandler = ca_handler_module.CAhandler @@ -240,7 +257,7 @@ def test_019_trigger__payload_process(self, mock_cobystr, mock_lookup, mock_der2 @patch('acme.trigger.cert_der2pem') @patch('acme.trigger.Trigger._certname_lookup') @patch('acme.trigger.convert_byte_to_string') - def test_020_trigger__payload_process(self, mock_cobystr, mock_lookup, mock_der2pem, mock_b64dec): + def test_021_trigger__payload_process(self, mock_cobystr, mock_lookup, mock_der2pem, mock_b64dec): """ test Trigger._payload_process - dbstore.order_update() raises an exception """ ca_handler_module = importlib.import_module('examples.ca_handler.skeleton_ca_handler') self.trigger.cahandler = ca_handler_module.CAhandler @@ -255,12 +272,83 @@ def test_020_trigger__payload_process(self, mock_cobystr, mock_lookup, mock_der2 self.assertIn('CRITICAL:test_a2c:acme2certifier database error in trigger._payload_process() add: exc_trigger_order_add', lcm.output) @patch('acme.trigger.load_config') - def test_021_config_load(self, mock_load_cfg): + def test_022_config_load(self, mock_load_cfg): """ test _config_load missing ca_handler """ mock_load_cfg.return_value = {} with self.assertLogs('test_a2c', level='INFO') as lcm: self.trigger._config_load() self.assertIn('ERROR:test_a2c:Trigger._config_load(): CAhandler configuration missing in config file', lcm.output) + @patch('acme.trigger.Trigger._config_load') + def test_023__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.trigger.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('acme.trigger.load_config') + def test_024_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + # parser['Account'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.trigger._config_load() + self.assertFalse(self.trigger.tnauthlist_support) + self.assertIn('ERROR:test_a2c:Trigger._config_load(): CAhandler configuration missing in config file', lcm.output) + + @patch('acme.trigger.load_config') + def test_025_config_load(self, mock_load_cfg): + """ test _config_load missing ca_handler """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'handler_file': 'foo'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.trigger._config_load() + self.assertIn("CRITICAL:test_a2c:Certificate._config_load(): loading CAhandler configured in cfg failed with err: No module named 'foo'", lcm.output) + # self.assertIn("CRITICAL:test_a2c:Certificate._config_load(): loading default CAhandler failed with err: No module named 'acme.ca_handler'", lcm.output) + + @patch('importlib.import_module') + @patch('acme.trigger.load_config') + def test_026_config_load(self, mock_load_cfg, mock_imp): + """ test _config_load missing ca_handler """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'handler_file': 'foo'} + mock_load_cfg.return_value = parser + mock_imp.return_value = Mock() + self.trigger._config_load() + self.assertTrue(self.trigger.cahandler) + + @patch('importlib.import_module') + @patch('acme.trigger.load_config') + def test_027_config_load(self, mock_load_cfg, mock_imp): + """ test _config_load missing ca_handler """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + mock_imp.return_value = Mock() + self.trigger._config_load() + self.assertTrue(self.trigger.cahandler) + + @patch('acme.trigger.load_config') + def test_028_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': False} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.trigger._config_load() + self.assertFalse(self.trigger.tnauthlist_support) + + @patch('acme.trigger.load_config') + def test_029_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + parser['Order'] = {'tnauthlist_support': True} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.trigger._config_load() + self.assertTrue(self.trigger.tnauthlist_support) + if __name__ == '__main__': unittest.main() From e5fa3e082de9cc9a1bb9d7e42c1f3837e3f96253 Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 18 May 2021 19:04:43 +0200 Subject: [PATCH 13/51] [fix] removed TimeConverter class file --- acme/timeconverter.py | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 acme/timeconverter.py diff --git a/acme/timeconverter.py b/acme/timeconverter.py deleted file mode 100644 index 86a4857b..00000000 --- a/acme/timeconverter.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -""" Timeconverter class """ -from __future__ import print_function -from datetime import datetime -import time -import calendar -import pytz -from acme.helper import logger_setup - -class Timeconverter(object): - """ Timeconverter """ - def __init__(self): - self.debug = None - self.logger = logger_setup(self.debug) - - def uts_to_date_utc(self, uts, format_='%Y-%m-%dT%H:%M:%S'): - """ convert unix timestamp to date format """ - self.logger.debug('Timeconverter.uts_to_date_utc({0}:{1})'.format(uts, format_)) - date_string = datetime.fromtimestamp(int(uts), tz=pytz.utc).strftime(format_) - return date_string - - def date_to_uts_utc(self, date_human, format_='%Y-%m-%dT%H:%M:%S'): - """ convert date to unix timestamp """ - self.logger.debug('Timeconverter.date_to_uts_utc({0}:{1})'.format(date_human, format_)) - uts = calendar.timegm(time.strptime(date_human, format_)) - return uts From f04f6efe5e0678e4ee43437c17196df2d01fab24 Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 18 May 2021 19:05:00 +0200 Subject: [PATCH 14/51] [tst] unittests --- test/test_housekeeping.py | 134 +++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 1 deletion(-) diff --git a/test/test_housekeeping.py b/test/test_housekeeping.py index a7b61639..0a80d12c 100644 --- a/test/test_housekeeping.py +++ b/test/test_housekeeping.py @@ -4,7 +4,8 @@ # pylint: disable=C0302, C0415, R0904, R0913, R0914, R0915, W0212 import unittest import sys -from unittest.mock import patch, MagicMock +from unittest.mock import patch, MagicMock, mock_open +import configparser sys.path.insert(0, '.') sys.path.insert(1, '..') @@ -372,5 +373,136 @@ def test_054_housekeeping_dbversion_check(self): self.housekeeping.dbversion_check(2) self.assertIn('CRITICAL:test_a2c:acme2certifier database version mismatch in: version is 1 but should be 2. Please run the "foo" script', lcm.output) + @patch('acme.housekeeping.Housekeeping._config_load') + def test_055__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.housekeeping.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('acme.housekeeping.load_config') + def test_056_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + # parser['Account'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + self.housekeeping._config_load() + self.assertTrue(mock_load_cfg.called) + + @patch('acme.housekeeping.load_config') + def test_057_config_load(self, mock_load_cfg): + """ test _config_load empty config """ + parser = configparser.ConfigParser() + parser['Housekeeping'] = {'foo': 'bar'} + mock_load_cfg.return_value = parser + self.housekeeping._config_load() + self.assertTrue(mock_load_cfg.called) + + @patch('csv.writer') + @patch("builtins.open", mock_open(read_data='csv_dump'), create=True) + def test_058__csv_dump(self, mock_write): + """ test csv dump """ + self.housekeeping._csv_dump('filename', 'data') + self.assertTrue(mock_write.called) + + @patch('json.dumps') + @patch("builtins.open", mock_open(read_data='csv_dump'), create=True) + def test_058__csv_dump(self, mock_json): + """ test csv dump """ + mock_json.return_value = {'foo': 'bar'} + self.housekeeping._json_dump('filename', 'data') + self.assertTrue(mock_json.called) + + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._accountlist_get') + def test_059_accountreport_get(self, mock_get, mock_norm, mock_convert): + """ test accountreport_get() no report name""" + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = ('foo', 'bar') + mock_convert.return_value = ['list'] + self.assertEqual(['list'], self.housekeeping.accountreport_get('csv', None, False)) + + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._accountlist_get') + def test_060_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + """ test accountreport_get() report name csv """ + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = ('foo', 'bar') + mock_convert.return_value = ['list'] + self.assertEqual(['list'], self.housekeeping.accountreport_get('csv', 'report_name', False)) + self.assertTrue(mock_list.called) + self.assertTrue(mock_dump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._to_acc_json') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._accountlist_get') + def test_061_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + """ test accountreport_get() report name json not nested """ + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = ('foo', 'bar') + mock_convert.return_value = ['list'] + self.assertEqual(['list'], self.housekeeping.accountreport_get('json', 'report_name', False)) + self.assertFalse(mock_list.called) + self.assertTrue(mock_dump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._to_acc_json') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._accountlist_get') + def test_062_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + """ test accountreport_get() report name json not nested """ + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = ('foo', 'bar') + mock_convert.return_value = ['list'] + mock_list.return_value = ['list1'] + self.assertEqual(['list1'], self.housekeeping.accountreport_get('json', 'report_name', True)) + self.assertTrue(mock_list.called) + self.assertTrue(mock_dump.called) + + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._certificatelist_get') + def test_063_certreport_get(self, mock_get, mock_norm, mock_convert): + """ test accountreport_get() no report name""" + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = (['foo'], 'bar') + mock_convert.return_value = ['list'] + self.assertEqual(['list'], self.housekeeping.certreport_get('csv', None)) + + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._certificatelist_get') + def test_064_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + """ test accountreport_get() no report name""" + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = (['foo'], 'bar') + mock_convert.return_value = ['list'] + self.assertEqual(['list'], self.housekeeping.certreport_get('csv', 'report_name')) + self.assertTrue(mock_list.called) + self.assertTrue(mock_dump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._to_acc_json') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._certificatelist_get') + def test_065_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + """ test accountreport_get() report name json not nested """ + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = (['foo'], 'bar') + mock_convert.return_value = ['list'] + self.assertEqual(['list'], self.housekeeping.certreport_get('json', 'report_name')) + self.assertFalse(mock_list.called) + self.assertTrue(mock_dump.called) + if __name__ == '__main__': unittest.main() From fa9502f8b0f766b39ab55bbc420c22109f2b2299 Mon Sep 17 00:00:00 2001 From: grindsa Date: Wed, 19 May 2021 20:17:35 +0200 Subject: [PATCH 15/51] [tst] unittests --- test/test_housekeeping.py | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/test/test_housekeeping.py b/test/test_housekeeping.py index 0a80d12c..0a31ce15 100644 --- a/test/test_housekeeping.py +++ b/test/test_housekeeping.py @@ -504,5 +504,76 @@ def test_065_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, self.assertFalse(mock_list.called) self.assertTrue(mock_dump.called) + @patch('acme.certificate.Certificate.dates_update') + def test_066_certificate_data_update(self, mock_update): + """ test certificate_dates_update """ + self.housekeeping.certificate_dates_update() + self.assertTrue(mock_update.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.certificate.Certificate.cleanup') + @patch('acme.housekeeping.uts_now') + def test_067_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup no uts empty report_name """ + mock_uts.return_value = 1111111111 + mock_cleanup.return_value = ('fieldlist', []) + self.assertFalse(self.housekeeping.certificates_cleanup(uts=None, purge=False, report_format='csv', report_name=None)) + self.assertTrue(mock_uts.called) + self.assertTrue(mock_cleanup.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.certificate.Certificate.cleanup') + @patch('acme.housekeeping.uts_now') + def test_068_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup uts but empty report_name """ + mock_uts.return_value = 1111111111 + mock_cleanup.return_value = ('fieldlist', []) + self.assertFalse(self.housekeeping.certificates_cleanup(uts='uts', purge=False, report_format='csv', report_name=None)) + self.assertFalse(mock_uts.called) + self.assertTrue(mock_cleanup.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.certificate.Certificate.cleanup') + @patch('acme.housekeeping.uts_now') + def test_069_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup no uts empty certlist """ + mock_uts.return_value = 111111111 + mock_cleanup.return_value = ('fieldlist', []) + self.assertFalse(self.housekeeping.certificates_cleanup(uts='foo', purge=False, report_format='csv', report_name='foo')) + self.assertFalse(mock_uts.called) + self.assertTrue(mock_cleanup.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.certificate.Certificate.cleanup') + @patch('acme.housekeeping.uts_now') + def test_069_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup no uts empty certlist """ + mock_uts.return_value = 111111111 + mock_cleanup.return_value = ('fieldlist', 'certlist') + self.assertEqual('cert_list', self.housekeeping.certificates_cleanup(uts='foo', purge=False, report_format='csv', report_name='foo')) + self.assertFalse(mock_uts.called) + self.assertTrue(mock_cleanup.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + if __name__ == '__main__': unittest.main() From 42c6f3804e5ce40b0d4a498ba9506282dd353d73 Mon Sep 17 00:00:00 2001 From: grindsa Date: Thu, 20 May 2021 19:25:27 +0200 Subject: [PATCH 16/51] [tst] unittests --- test/test_housekeeping.py | 298 +++++++++++++++++++++++++++++++++++--- 1 file changed, 279 insertions(+), 19 deletions(-) diff --git a/test/test_housekeeping.py b/test/test_housekeeping.py index 0a31ce15..614560d6 100644 --- a/test/test_housekeeping.py +++ b/test/test_housekeeping.py @@ -373,15 +373,22 @@ def test_054_housekeeping_dbversion_check(self): self.housekeeping.dbversion_check(2) self.assertIn('CRITICAL:test_a2c:acme2certifier database version mismatch in: version is 1 but should be 2. Please run the "foo" script', lcm.output) + def test_055_housekeeping_dbversion_check(self): + """ test Housekeeping.dbversion_check load - version mismatch """ + self.housekeeping.dbstore.dbversion_get.side_effect = Exception('exc_dbversion_chk') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.housekeeping.dbversion_check(2) + self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Housekeeping.dbversion_check(): exc_dbversion_chk', lcm.output) + @patch('acme.housekeeping.Housekeeping._config_load') - def test_055__enter__(self, mock_cfg): + def test_056__enter__(self, mock_cfg): """ test enter """ mock_cfg.return_value = True self.housekeeping.__enter__() self.assertTrue(mock_cfg.called) @patch('acme.housekeeping.load_config') - def test_056_config_load(self, mock_load_cfg): + def test_057_config_load(self, mock_load_cfg): """ test _config_load empty config """ parser = configparser.ConfigParser() # parser['Account'] = {'foo': 'bar'} @@ -390,7 +397,7 @@ def test_056_config_load(self, mock_load_cfg): self.assertTrue(mock_load_cfg.called) @patch('acme.housekeeping.load_config') - def test_057_config_load(self, mock_load_cfg): + def test_058_config_load(self, mock_load_cfg): """ test _config_load empty config """ parser = configparser.ConfigParser() parser['Housekeeping'] = {'foo': 'bar'} @@ -400,14 +407,14 @@ def test_057_config_load(self, mock_load_cfg): @patch('csv.writer') @patch("builtins.open", mock_open(read_data='csv_dump'), create=True) - def test_058__csv_dump(self, mock_write): + def test_059__csv_dump(self, mock_write): """ test csv dump """ self.housekeeping._csv_dump('filename', 'data') self.assertTrue(mock_write.called) @patch('json.dumps') @patch("builtins.open", mock_open(read_data='csv_dump'), create=True) - def test_058__csv_dump(self, mock_json): + def test_060__csv_dump(self, mock_json): """ test csv dump """ mock_json.return_value = {'foo': 'bar'} self.housekeeping._json_dump('filename', 'data') @@ -416,7 +423,7 @@ def test_058__csv_dump(self, mock_json): @patch('acme.housekeeping.Housekeeping._convert_data') @patch('acme.housekeeping.Housekeeping._lists_normalize') @patch('acme.housekeeping.Housekeeping._accountlist_get') - def test_059_accountreport_get(self, mock_get, mock_norm, mock_convert): + def test_061_accountreport_get(self, mock_get, mock_norm, mock_convert): """ test accountreport_get() no report name""" mock_get.return_value = ('foo', 'bar') mock_norm.return_value = ('foo', 'bar') @@ -428,7 +435,7 @@ def test_059_accountreport_get(self, mock_get, mock_norm, mock_convert): @patch('acme.housekeeping.Housekeeping._convert_data') @patch('acme.housekeeping.Housekeeping._lists_normalize') @patch('acme.housekeeping.Housekeeping._accountlist_get') - def test_060_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + def test_062_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): """ test accountreport_get() report name csv """ mock_get.return_value = ('foo', 'bar') mock_norm.return_value = ('foo', 'bar') @@ -442,7 +449,7 @@ def test_060_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_lis @patch('acme.housekeeping.Housekeeping._convert_data') @patch('acme.housekeeping.Housekeeping._lists_normalize') @patch('acme.housekeeping.Housekeeping._accountlist_get') - def test_061_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + def test_063_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): """ test accountreport_get() report name json not nested """ mock_get.return_value = ('foo', 'bar') mock_norm.return_value = ('foo', 'bar') @@ -456,7 +463,7 @@ def test_061_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_lis @patch('acme.housekeeping.Housekeeping._convert_data') @patch('acme.housekeeping.Housekeeping._lists_normalize') @patch('acme.housekeeping.Housekeeping._accountlist_get') - def test_062_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + def test_064_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): """ test accountreport_get() report name json not nested """ mock_get.return_value = ('foo', 'bar') mock_norm.return_value = ('foo', 'bar') @@ -469,7 +476,7 @@ def test_062_accountreport_get(self, mock_get, mock_norm, mock_convert, mock_lis @patch('acme.housekeeping.Housekeeping._convert_data') @patch('acme.housekeeping.Housekeeping._lists_normalize') @patch('acme.housekeeping.Housekeeping._certificatelist_get') - def test_063_certreport_get(self, mock_get, mock_norm, mock_convert): + def test_065_certreport_get(self, mock_get, mock_norm, mock_convert): """ test accountreport_get() no report name""" mock_get.return_value = ('foo', 'bar') mock_norm.return_value = (['foo'], 'bar') @@ -481,7 +488,7 @@ def test_063_certreport_get(self, mock_get, mock_norm, mock_convert): @patch('acme.housekeeping.Housekeeping._convert_data') @patch('acme.housekeeping.Housekeeping._lists_normalize') @patch('acme.housekeeping.Housekeeping._certificatelist_get') - def test_064_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + def test_066_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): """ test accountreport_get() no report name""" mock_get.return_value = ('foo', 'bar') mock_norm.return_value = (['foo'], 'bar') @@ -495,7 +502,7 @@ def test_064_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, @patch('acme.housekeeping.Housekeeping._convert_data') @patch('acme.housekeeping.Housekeeping._lists_normalize') @patch('acme.housekeeping.Housekeeping._certificatelist_get') - def test_065_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + def test_067_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): """ test accountreport_get() report name json not nested """ mock_get.return_value = ('foo', 'bar') mock_norm.return_value = (['foo'], 'bar') @@ -504,8 +511,24 @@ def test_065_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, self.assertFalse(mock_list.called) self.assertTrue(mock_dump.called) + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._to_acc_json') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.housekeeping.Housekeeping._certificatelist_get') + def test_068_certreport_get(self, mock_get, mock_norm, mock_convert, mock_list, mock_dump): + """ test accountreport_get() report name json not nested """ + mock_get.return_value = ('foo', 'bar') + mock_norm.return_value = (['foo'], 'bar') + mock_convert.return_value = ['list'] + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(['list'], self.housekeeping.certreport_get('unknown', 'report_name')) + self.assertFalse(mock_list.called) + self.assertFalse(mock_dump.called) + self.assertIn('INFO:test_a2c:Housekeeping.certreport_get(): No dump just return report', lcm.output) + @patch('acme.certificate.Certificate.dates_update') - def test_066_certificate_data_update(self, mock_update): + def test_069_certificate_data_update(self, mock_update): """ test certificate_dates_update """ self.housekeeping.certificate_dates_update() self.assertTrue(mock_update.called) @@ -515,7 +538,23 @@ def test_066_certificate_data_update(self, mock_update): @patch('acme.housekeeping.Housekeeping._to_list') @patch('acme.certificate.Certificate.cleanup') @patch('acme.housekeeping.uts_now') - def test_067_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + def test_070_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup no uts empty report_name """ + mock_uts.return_value = 1111111111 + mock_cleanup.return_value = ('fieldlist', []) + self.assertFalse(self.housekeeping.certificates_cleanup(uts=None, purge=False, report_format='csv', report_name=None)) + self.assertTrue(mock_uts.called) + self.assertTrue(mock_cleanup.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.certificate.Certificate.cleanup') + @patch('acme.housekeeping.uts_now') + def test_071_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): """ test certificates_cleanup no uts empty report_name """ mock_uts.return_value = 1111111111 mock_cleanup.return_value = ('fieldlist', []) @@ -531,7 +570,7 @@ def test_067_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_ @patch('acme.housekeeping.Housekeeping._to_list') @patch('acme.certificate.Certificate.cleanup') @patch('acme.housekeeping.uts_now') - def test_068_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + def test_072_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): """ test certificates_cleanup uts but empty report_name """ mock_uts.return_value = 1111111111 mock_cleanup.return_value = ('fieldlist', []) @@ -547,7 +586,7 @@ def test_068_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_ @patch('acme.housekeeping.Housekeeping._to_list') @patch('acme.certificate.Certificate.cleanup') @patch('acme.housekeeping.uts_now') - def test_069_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + def test_073_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): """ test certificates_cleanup no uts empty certlist """ mock_uts.return_value = 111111111 mock_cleanup.return_value = ('fieldlist', []) @@ -563,17 +602,238 @@ def test_069_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_ @patch('acme.housekeeping.Housekeeping._to_list') @patch('acme.certificate.Certificate.cleanup') @patch('acme.housekeeping.uts_now') - def test_069_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): - """ test certificates_cleanup no uts empty certlist """ + def test_074_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup csv """ mock_uts.return_value = 111111111 - mock_cleanup.return_value = ('fieldlist', 'certlist') + mock_cleanup.return_value = ('fieldlist', 'cert_list') self.assertEqual('cert_list', self.housekeeping.certificates_cleanup(uts='foo', purge=False, report_format='csv', report_name='foo')) self.assertFalse(mock_uts.called) self.assertTrue(mock_cleanup.called) + self.assertTrue(mock_list.called) + self.assertTrue(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.certificate.Certificate.cleanup') + @patch('acme.housekeeping.uts_now') + def test_075_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup json """ + mock_uts.return_value = 111111111 + mock_cleanup.return_value = ('fieldlist', 'cert_list') + self.assertEqual('cert_list', self.housekeeping.certificates_cleanup(uts='foo', purge=False, report_format='json', report_name='foo')) + self.assertFalse(mock_uts.called) + self.assertTrue(mock_cleanup.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertTrue(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.certificate.Certificate.cleanup') + @patch('acme.housekeeping.uts_now') + def test_076_certificates_cleanup(self, mock_uts, mock_cleanup, mock_list, mock_cdump, mock_jdump): + """ test certificates_cleanup unknown output """ + mock_uts.return_value = 111111111 + mock_cleanup.return_value = ('fieldlist', 'cert_list') + self.assertEqual('cert_list', self.housekeeping.certificates_cleanup(uts='foo', purge=False, report_format='unkown', report_name='foo')) + self.assertFalse(mock_uts.called) + self.assertTrue(mock_cleanup.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.authorization.Authorization.invalidate') + def test_077_authorizations_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization without report name """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.authorizations_invalidate(uts='foo', report_format='unkown', report_name=None) + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) self.assertFalse(mock_list.called) self.assertFalse(mock_cdump.called) self.assertFalse(mock_jdump.called) + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.authorization.Authorization.invalidate') + def test_078_authorizations_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name but empty auth_list""" + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = [] + self.housekeeping.authorizations_invalidate(uts='foo', report_format='unkown', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.authorization.Authorization.invalidate') + def test_079_authorizations_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name unknown report format """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.authorizations_invalidate(uts='foo', report_format='unkown', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.authorization.Authorization.invalidate') + def test_080_authorizations_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name unknown report format """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.authorizations_invalidate(uts='foo', report_format='csv', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertTrue(mock_list.called) + self.assertTrue(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.authorization.Authorization.invalidate') + def test_081_authorizations_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name unknown report format """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.authorizations_invalidate(uts='foo', report_format='json', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertTrue(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.order.Order.invalidate') + def test_082_orders_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization without report name """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.orders_invalidate(uts='foo', report_format='unkown', report_name=None) + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.order.Order.invalidate') + def test_083_orders_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name but empty auth_list""" + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = [] + self.housekeeping.orders_invalidate(uts='foo', report_format='unkown', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.order.Order.invalidate') + def test_084_orders_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name unknown report format """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.orders_invalidate(uts='foo', report_format='unkown', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.order.Order.invalidate') + def test_085_orders_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name unknown report format """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.orders_invalidate(uts='foo', report_format='csv', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertTrue(mock_list.called) + self.assertTrue(mock_cdump.called) + self.assertFalse(mock_jdump.called) + + @patch('acme.housekeeping.Housekeeping._json_dump') + @patch('acme.housekeeping.Housekeeping._csv_dump') + @patch('acme.housekeeping.Housekeeping._to_list') + @patch('acme.housekeeping.Housekeeping._convert_data') + @patch('acme.housekeeping.Housekeeping._lists_normalize') + @patch('acme.order.Order.invalidate') + def test_086_orders_invalidate(self, mock_invalidate, mock_normalize, mock_convert, mock_list, mock_cdump, mock_jdump): + """ authorization with report name unknown report format """ + mock_invalidate.return_value = ('fieldlist', 'cert_list') + mock_normalize.return_value = ('field_list', 'authorization_list') + mock_convert.return_value = 'authorization_list' + self.housekeeping.orders_invalidate(uts='foo', report_format='json', report_name='foo') + self.assertTrue(mock_invalidate.called) + self.assertTrue(mock_normalize.called) + self.assertTrue(mock_convert.called) + self.assertFalse(mock_list.called) + self.assertFalse(mock_cdump.called) + self.assertTrue(mock_jdump.called) if __name__ == '__main__': unittest.main() From 18527fe3b45d03f8d6f04c190f2751682feb4f53 Mon Sep 17 00:00:00 2001 From: grindsa Date: Fri, 21 May 2021 19:25:36 +0200 Subject: [PATCH 17/51] [feat] certifier_ca_handler.py - user/pw variable --- examples/ca_handler/certifier_ca_handler.py | 27 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/examples/ca_handler/certifier_ca_handler.py b/examples/ca_handler/certifier_ca_handler.py index f37e3efe..b582cdb3 100644 --- a/examples/ca_handler/certifier_ca_handler.py +++ b/examples/ca_handler/certifier_ca_handler.py @@ -142,12 +142,33 @@ def _config_load(self): self.logger.error('CAhandler._config_load() configuration incomplete: "api_host" parameter is missing in config file') if 'api_user' in config_dic['CAhandler']: self.api_user = config_dic['CAhandler']['api_user'] + + if 'api_user' in config_dic['CAhandler'] or 'api_user_variable' in config_dic['CAhandler']: + if 'api_user_variable' in config_dic['CAhandler']: + try: + self.api_user = os.environ[config_dic['CAhandler']['api_user_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load passphrase_variable:{0}'.format(err)) + if 'api_user' in config_dic['CAhandler']: + if self.api_user: + self.logger.info('CAhandler._config_load() overwrite api_user') + self.api_user = config_dic['CAhandler']['api_user'] else: self.logger.error('CAhandler._config_load() configuration incomplete: "api_user" parameter is missing in config file') - if 'api_password' in config_dic['CAhandler']: - self.api_password = config_dic['CAhandler']['api_password'] + + if 'api_password' in config_dic['CAhandler'] or 'api_password_variable' in config_dic['CAhandler']: + if 'api_password_variable' in config_dic['CAhandler']: + try: + self.api_password = os.environ[config_dic['CAhandler']['api_password_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load passphrase_variable:{0}'.format(err)) + if 'api_password' in config_dic['CAhandler']: + if self.api_password: + self.logger.info('CAhandler._config_load() overwrite api_password_variable') + self.api_password = config_dic['CAhandler']['api_password'] else: self.logger.error('CAhandler._config_load() configuration incomplete: "api_password" parameter is missing in config file') + if 'ca_name' in config_dic['CAhandler']: self.ca_name = config_dic['CAhandler']['ca_name'] else: @@ -287,7 +308,7 @@ def _request_poll(self, request_url): error = 'Unknown request status: {0}'.format(request_dic['status']) else: error = '"status" field not found in response.' - + self.logger.debug('CAhandler._request_poll() ended with error: {0}'.format(error)) return(error, cert_bundle, cert_raw, poll_identifier, rejected) From 941302752a05fdaf193a31968d70016bbc322920 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 22 May 2021 06:55:56 +0200 Subject: [PATCH 18/51] [tst] unittests --- examples/ca_handler/certifier_ca_handler.py | 5 +- test/test_certifier_handler.py | 194 +++++++++++++------- 2 files changed, 127 insertions(+), 72 deletions(-) diff --git a/examples/ca_handler/certifier_ca_handler.py b/examples/ca_handler/certifier_ca_handler.py index b582cdb3..520b9adf 100644 --- a/examples/ca_handler/certifier_ca_handler.py +++ b/examples/ca_handler/certifier_ca_handler.py @@ -6,6 +6,7 @@ import math import time import requests +import os from requests.auth import HTTPBasicAuth # pylint: disable=E0401 from acme.helper import load_config, cert_serial_get, uts_now, uts_to_date_utc, b64_decode, b64_encode, cert_pem2der @@ -140,15 +141,13 @@ def _config_load(self): self.api_host = config_dic['CAhandler']['api_host'] else: self.logger.error('CAhandler._config_load() configuration incomplete: "api_host" parameter is missing in config file') - if 'api_user' in config_dic['CAhandler']: - self.api_user = config_dic['CAhandler']['api_user'] if 'api_user' in config_dic['CAhandler'] or 'api_user_variable' in config_dic['CAhandler']: if 'api_user_variable' in config_dic['CAhandler']: try: self.api_user = os.environ[config_dic['CAhandler']['api_user_variable']] except BaseException as err: - self.logger.error('CAhandler._config_load() could not load passphrase_variable:{0}'.format(err)) + self.logger.error('CAhandler._config_load() could not load user_variable:{0}'.format(err)) if 'api_user' in config_dic['CAhandler']: if self.api_user: self.logger.info('CAhandler._config_load() overwrite api_user') diff --git a/test/test_certifier_handler.py b/test/test_certifier_handler.py index db3a7a14..d4e023d4 100644 --- a/test/test_certifier_handler.py +++ b/test/test_certifier_handler.py @@ -173,14 +173,70 @@ def test_013_config_load(self, mock_load_cfg): self.assertEqual('ca_name', self.cahandler.ca_name) self.assertEqual(120, self.cahandler.polling_timeout) - def test_014_auth_set(self): + @patch.dict('os.environ', {'api_user_var': 'user_var'}) + @patch('examples.ca_handler.certifier_ca_handler.load_config') + def test_014_config_load(self, mock_load_cfg): + """ test _config_load - load template with user variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_user_variable': 'api_user_var'}} + self.cahandler._config_load() + self.assertEqual('user_var', self.cahandler.api_user) + + @patch.dict('os.environ', {'api_user_var': 'user_var'}) + @patch('examples.ca_handler.certifier_ca_handler.load_config') + def test_015_config_load(self, mock_load_cfg): + """ test _config_load - load template with user variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_user_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_user) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load user_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'api_user_var': 'user_var'}) + @patch('examples.ca_handler.certifier_ca_handler.load_config') + def test_016_config_load(self, mock_load_cfg): + """ test _config_load - load template with user variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_user_variable': 'api_user_var', 'api_user': 'api_user'}} + self.cahandler._config_load() + # with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual('api_user', self.cahandler.api_user) + # self.assertIn("foo", lcm.output) + + @patch.dict('os.environ', {'api_password_var': 'password_var'}) + @patch('examples.ca_handler.certifier_ca_handler.load_config') + def test_017_config_load(self, mock_load_cfg): + """ test _config_load - load template with password variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_password_variable': 'api_password_var'}} + self.cahandler._config_load() + self.assertEqual('password_var', self.cahandler.api_password) + + @patch.dict('os.environ', {'api_password_var': 'password_var'}) + @patch('examples.ca_handler.certifier_ca_handler.load_config') + def test_018_config_load(self, mock_load_cfg): + """ test _config_load - load template with password variable which does not exist """ + mock_load_cfg.return_value = {'CAhandler': {'api_password_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_password) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load passphrase_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'api_password_var': 'password_var'}) + @patch('examples.ca_handler.certifier_ca_handler.load_config') + def test_019_config_load(self, mock_load_cfg): + """ test _config_load - load template override password variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_password_variable': 'api_password_var', 'api_password': 'api_password'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('api_password', self.cahandler.api_password) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite api_password_variable', lcm.output) + + def test_020_auth_set(self): """ test _auth_set """ self.cahandler.api_user = 'api_user' self.cahandler.api_password = 'api_password' self.cahandler._auth_set() self.assertTrue(self.cahandler.auth) - def test_015_auth_set(self): + def test_021_auth_set(self): """ test _auth_set without api_user """ self.cahandler.api_user = None self.cahandler.api_password = 'api_password' @@ -189,7 +245,7 @@ def test_015_auth_set(self): self.assertFalse(self.cahandler.auth) self.assertIn('ERROR:test_a2c:CAhandler._auth_set(): auth information incomplete. Either "api_user" or "api_password" parameter is missing in config file', lcm.output) - def test_016_auth_set(self): + def test_022_auth_set(self): """ test _auth_set without api_user """ self.cahandler.api_user = 'api_user' self.cahandler.api_password = None @@ -199,7 +255,7 @@ def test_016_auth_set(self): self.assertIn('ERROR:test_a2c:CAhandler._auth_set(): auth information incomplete. Either "api_user" or "api_password" parameter is missing in config file', lcm.output) @patch.object(requests, 'post') - def test_017__api_post(self, mock_req): + def test_023__api_post(self, mock_req): """ test _api_post successful run """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -207,7 +263,7 @@ def test_017__api_post(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._api_post('url', 'data')) @patch('requests.post') - def test_018__api_post(self, mock_post): + def test_024__api_post(self, mock_post): """ CAhandler.get_ca() returns an http error """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -217,7 +273,7 @@ def test_018__api_post(self, mock_post): self.assertIn('ERROR:test_a2c:CAhandler._api_post() returned error: exc_api_post', lcm.output) @patch.object(requests, 'get') - def test_019__ca_get(self, mock_req): + def test_025__ca_get(self, mock_req): """ test _ca_get successful run """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -226,7 +282,7 @@ def test_019__ca_get(self, mock_req): mockresponse.json = lambda: {'foo': 'bar'} self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get()) - def test_020__api_post(self): + def test_026__api_post(self): """ test _ca_get no api_host""" self.cahandler.auth = 'auth' with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -234,7 +290,7 @@ def test_020__api_post(self): self.assertIn('ERROR:test_a2c:CAhandler._ca_get(): api_host is misisng in configuration', lcm.output) @patch.object(requests, 'get') - def test_021__ca_get(self, mock_req): + def test_027__ca_get(self, mock_req): """ test _ca_get auth none """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -243,7 +299,7 @@ def test_021__ca_get(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get()) @patch('requests.get') - def test_022__api_post(self, mock_get): + def test_028__api_post(self, mock_get): """ CAhandler.get_ca() returns an http error """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -253,62 +309,62 @@ def test_022__api_post(self, mock_get): self.assertIn('ERROR:test_a2c:CAhandler._ca_get() returned error: exc_ca_get', lcm.output) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_023__ca_get_properties(self, mock_caget): + def test_029__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns nothing """ mock_caget.return_value = [] self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_024__ca_get_properties(self, mock_caget): + def test_030__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns wrong information """ mock_caget.return_value = 'foo' self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_025__ca_get_properties(self, mock_caget): + def test_031__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns error message """ mock_caget.return_value = {'status': 'status', 'message': 'message'} self.assertEqual({'message': 'message', 'status': 'status'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_026__ca_get_properties(self, mock_caget): + def test_032__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns empty ca_list """ mock_caget.return_value = {'cas': None} self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_027__ca_get_properties(self, mock_caget): + def test_033__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list but filter does not match """ mock_caget.return_value = {'cas': [{'foo': 'bar'}]} self.assertEqual({'status': 404, 'message': 'CA could not be found', 'statusMessage': 'Not Found'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_028__ca_get_properties(self, mock_caget): + def test_034__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list but filter matches """ mock_caget.return_value = {'cas': [{'foo': 'bar'}, {'filterkey': 'filtervalue'}, {'foo1': 'bar1'}]} self.assertEqual({'filterkey': 'filtervalue'}, self.cahandler._ca_get_properties('filterkey', 'filtervalue')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_029__ca_get_properties(self, mock_caget): + def test_035__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list another filterkey """ mock_caget.return_value = {'cas': [{'foo': 'bar'}, {'filterkey': 'filtervalue'}, {'foo1': 'bar1'}]} self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get_properties('foo', 'bar')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get') - def test_030__ca_get_properties(self, mock_caget): + def test_036__ca_get_properties(self, mock_caget): """ CAhandler._ca_get_properties() ca_get returns ca_list filterkey check first match""" mock_caget.return_value = {'cas': [{'foo': 'bar_bogus'}, {'foo': 'bar'}, {'foo': 'bar1'}, {'foo': 'bar2'}]} self.assertEqual({'foo': 'bar'}, self.cahandler._ca_get_properties('foo', 'bar')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_031__cert_get(self, mock_caget): + def test_037__cert_get(self, mock_caget): """ CAhandler._ca_get_properties() _ca_get_properties returns empty dic """ mock_caget.return_value = {} self.assertEqual({}, self.cahandler._cert_get('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._api_post') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_032__cert_get(self, mock_caget, mock_post): + def test_038__cert_get(self, mock_caget, mock_post): """ CAhandler._ca_get_properties() _ca_get_properties does returns "href" key """ self.cahandler.api_host = 'api_host' mock_caget.return_value = {'href': 'href'} @@ -317,7 +373,7 @@ def test_032__cert_get(self, mock_caget, mock_post): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._api_post') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_033__cert_get(self, mock_caget, mock_post): + def test_039__cert_get(self, mock_caget, mock_post): """ CAhandler._ca_get_properties() _ca_get_properties returns "href" key but cert_dic is empty """ self.cahandler.api_host = 'api_host' mock_caget.return_value = {'href': 'href'} @@ -325,7 +381,7 @@ def test_033__cert_get(self, mock_caget, mock_post): self.assertEqual({'href': 'href'}, self.cahandler._cert_get('csr')) @patch('requests.get') - def test_034__cert_get_properties(self, mock_req): + def test_040__cert_get_properties(self, mock_req): """ CAhandler._cert_get_properties() all good """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -335,7 +391,7 @@ def test_034__cert_get_properties(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._cert_get_properties('serial', 'link')) @patch('requests.get') - def test_035__cert_get_properties(self, mock_get): + def test_041__cert_get_properties(self, mock_get): """ CAhandler._cert_get_properties() all good """ self.cahandler.api_host = 'api_host' self.cahandler.auth = 'auth' @@ -344,23 +400,23 @@ def test_035__cert_get_properties(self, mock_get): self.assertEqual({'status': 500, 'message': 'exc_api_get', 'statusMessage': 'Internal Server Error'}, self.cahandler._cert_get_properties('serial', 'link')) self.assertIn('ERROR:test_a2c:CAhandler._cert_get_properties() returned error: exc_api_get', lcm.output) - def test_036_poll(self): + def test_042_poll(self): """ CAhandler.poll() poll_identifier is none """ self.assertEqual((None, None, None, None, False), self.cahandler.poll('cert_name', None, 'csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._request_poll') - def test_037_poll(self, mock_poll): + def test_043_poll(self, mock_poll): """ CAhandler.poll() poll_identifier is none """ mock_poll.return_value = ('error', 'cert_bundle', 'cert_raw', 'poll_identifier', 'rejected') self.assertEqual(('error', 'cert_bundle', 'cert_raw', 'poll_identifier', 'rejected'), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) - def test_038__loop_poll(self): + def test_044__loop_poll(self): """ CAhandler._loop_poll() - no request url""" request_url = None self.assertEqual((None, None, None, None), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_039__loop_poll(self, mock_get): + def test_045__loop_poll(self, mock_get): """ CAhandler._loop_poll() - nothing come back from request get""" self.cahandler.polling_timeout = 5 self.cahandler.timeout = 0 @@ -371,7 +427,7 @@ def test_039__loop_poll(self, mock_get): self.assertEqual((None, None, None, 'request_url'), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_040__loop_poll(self, mock_get): + def test_046__loop_poll(self, mock_get): """ CAhandler._loop_poll() - no status returned from request get""" self.cahandler.polling_timeout = 5 self.cahandler.timeout = 0 @@ -382,7 +438,7 @@ def test_040__loop_poll(self, mock_get): self.assertEqual((None, None, None, 'request_url'), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_041__loop_poll(self, mock_get): + def test_047__loop_poll(self, mock_get): """ CAhandler._loop_poll() - status "rejected" returned from request get""" self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -393,7 +449,7 @@ def test_041__loop_poll(self, mock_get): self.assertEqual(('Request rejected by operator', None, None, None), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_042__loop_poll(self, mock_get): + def test_048__loop_poll(self, mock_get): """ CAhandler._loop_poll() - status "accepted" returned from request get but no certificate in""" self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -404,7 +460,7 @@ def test_042__loop_poll(self, mock_get): self.assertEqual(('Request accepted but no certificate returned', None, None, 'request_url'), self.cahandler._loop_poll(request_url)) @patch('requests.get') - def test_043__loop_poll(self, mock_get): + def test_049__loop_poll(self, mock_get): """ CAhandler._loop_poll() - status "accepted" returned from request "certifiate" in but no "certificateBase64" in 2dn request """ self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -416,7 +472,7 @@ def test_043__loop_poll(self, mock_get): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._pem_cert_chain_generate') @patch('requests.get') - def test_044__loop_poll(self, mock_get, mock_chain): + def test_050__loop_poll(self, mock_get, mock_chain): """ CAhandler._loop_poll() - status "accepted" returned from request "certifiate" in but no "certificateBase64" in 2dn request """ self.cahandler.polling_timeout = 6 self.cahandler.timeout = 0 @@ -428,32 +484,32 @@ def test_044__loop_poll(self, mock_get, mock_chain): self.assertEqual((None, 'foo', 'certificateBase64', None), self.cahandler._loop_poll(request_url)) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_045_enroll(self, mock_certget): + def test_051_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns None """ mock_certget.return_value = {} self.assertEqual(('internal error', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_046_enroll(self, mock_certget): + def test_052_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns wrong information """ mock_certget.return_value = {'foo': 'bar'} self.assertEqual(('no certificate information found', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_047_enroll(self, mock_certget): + def test_053_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns status without error message """ mock_certget.return_value = {'foo': 'bar', 'status': 'foo'} self.assertEqual(('unknown errror', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_048_enroll(self, mock_certget): + def test_054_enroll(self, mock_certget): """ CAhandler.enroll() _cert_get returns status with error message """ mock_certget.return_value = {'foo': 'bar', 'status': 'foo', 'message': 'message'} self.assertEqual(('message', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._pem_cert_chain_generate') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_049_enroll(self, mock_certget, mock_chain): + def test_055_enroll(self, mock_certget, mock_chain): """ CAhandler.enroll() _cert_get returns certb64 """ mock_certget.return_value = {'foo': 'bar', 'certificateBase64': 'certificateBase64'} mock_chain.return_value = 'mock_chain' @@ -461,27 +517,27 @@ def test_049_enroll(self, mock_certget, mock_chain): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._loop_poll') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get') - def test_050_enroll(self, mock_certget, mock_loop): + def test_056_enroll(self, mock_certget, mock_loop): """ CAhandler.enroll() _cert_get returns certb64 """ mock_certget.return_value = {'foo': 'bar', 'href': 'href'} mock_loop.return_value = ('error', 'cert_bundle', 'cert_raw', 'poll_identifier') self.assertEqual(('error', 'cert_bundle', 'cert_raw', 'poll_identifier'), self.cahandler.enroll('csr')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_051_revoke(self, mock_getca): + def test_057_revoke(self, mock_getca): """ CAhandler.revoke() _ca_get_properties returns nothing """ mock_getca.return_value = {} self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'CA could not be found'), self.cahandler.revoke('cert')) @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_052_revoke(self, mock_getca): + def test_058_revoke(self, mock_getca): """ CAhandler.revoke() _ca_get_properties returns wrong information """ mock_getca.return_value = {'foo': 'bar'} self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'CA could not be found'), self.cahandler.revoke('cert')) @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_053_revoke(self, mock_getca, mock_serial): + def test_059_revoke(self, mock_getca, mock_serial): """ CAhandler.revoke() _ca_get_properties cert_serial_get failed """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = None @@ -490,7 +546,7 @@ def test_053_revoke(self, mock_getca, mock_serial): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_054_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_060_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties failed """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -500,7 +556,7 @@ def test_054_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_055_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_061_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns wrong information """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -510,7 +566,7 @@ def test_055_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_056_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_062_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties empty cert_list """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -520,7 +576,7 @@ def test_056_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_057_revoke(self, mock_getca, mock_serial, mock_getcert): + def test_063_revoke(self, mock_getca, mock_serial, mock_getcert): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns cert_list with wrong information """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -531,7 +587,7 @@ def test_057_revoke(self, mock_getca, mock_serial, mock_getcert): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_058_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): + def test_064_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns cert_list revocation successful """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -543,7 +599,7 @@ def test_058_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_059_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): + def test_065_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns href. revocation returns status without message """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -555,7 +611,7 @@ def test_059_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._cert_get_properties') @patch('examples.ca_handler.certifier_ca_handler.cert_serial_get') @patch('examples.ca_handler.certifier_ca_handler.CAhandler._ca_get_properties') - def test_060_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): + def test_066_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): """ CAhandler.revoke() _ca_get_properties get_cert_properties returns href. revocation returns status with message """ mock_getca.return_value = {'foo': 'bar', 'href': 'href'} mock_serial.return_value = 123 @@ -563,7 +619,7 @@ def test_060_revoke(self, mock_getca, mock_serial, mock_getcert, mock_post): mock_post.return_value = {'foo': 'bar', 'status': 'status', 'message': 'message'} self.assertEqual((400, 'urn:ietf:params:acme:error:alreadyRevoked', 'message'), self.cahandler.revoke('cert')) - def test_061_trigger(self): + def test_067_trigger(self): """ CAhandler.trigger() - no payload given """ payload = None self.assertEqual(('No payload given', None, None), self.cahandler.trigger(payload)) @@ -572,7 +628,7 @@ def test_061_trigger(self): @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_062_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop): + def test_068_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop): """ CAhandler.trigger() - payload but ca_lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -585,7 +641,7 @@ def test_062_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop): @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_063_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial): + def test_069_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -600,7 +656,7 @@ def test_063_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_064_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop): + def test_070_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -617,7 +673,7 @@ def test_064_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_065_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): + def test_071_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -635,7 +691,7 @@ def test_065_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock @patch('examples.ca_handler.certifier_ca_handler.cert_pem2der') @patch('examples.ca_handler.certifier_ca_handler.b64_decode') @patch('examples.ca_handler.certifier_ca_handler.b64_encode') - def test_066_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): + def test_072_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock_serial, mock_certprop, mock_chain): """ CAhandler.trigger() - payload serial number lookup failed""" payload = 'foo' mock_b64dec.return_value = 'foodecode' @@ -646,23 +702,23 @@ def test_066_trigger(self, mock_b64dec, mock_b64enc, mock_p2d, mock_caprop, mock mock_chain.return_value = 'chain' self.assertEqual((None, 'chain', 'foodecode'), self.cahandler.trigger(payload)) - def test_067__pem_cert_chain_generate(self): + def test_073__pem_cert_chain_generate(self): """ _pem_cert_chain_generate - empty cert_dic """ cert_dic = {} self.assertFalse(self.cahandler._pem_cert_chain_generate(cert_dic)) - def test_068__pem_cert_chain_generate(self): + def test_074__pem_cert_chain_generate(self): """ _pem_cert_chain_generate - wrong dic """ cert_dic = {'foo': 'bar'} self.assertFalse(self.cahandler._pem_cert_chain_generate(cert_dic)) - def test_069__pem_cert_chain_generate(self): + def test_075__pem_cert_chain_generate(self): """ _pem_cert_chain_generate - certificateBase64 in dict """ cert_dic = {'certificateBase64': 'certificateBase64'} self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase64\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_070__pem_cert_chain_generate(self, mock_get): + def test_076__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - issuer in dict without certificateBase64 """ cert_dic = {'issuer': 'issuer'} mockresponse = Mock() @@ -671,7 +727,7 @@ def test_070__pem_cert_chain_generate(self, mock_get): self.assertFalse(self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_071__pem_cert_chain_generate(self, mock_get): + def test_077__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns "certificates" but no active """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -682,7 +738,7 @@ def test_071__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_072__pem_cert_chain_generate(self, mock_get): + def test_078__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns certificate and active, 2nd request is bogus """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -693,7 +749,7 @@ def test_072__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_073__pem_cert_chain_generate(self, mock_get): + def test_079__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns certificate two certs """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -706,7 +762,7 @@ def test_073__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\ncertificateBase642\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_074__pem_cert_chain_generate(self, mock_get): + def test_080__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - request returns certificate three certs """ cert_dic = {'issuer': 'issuer', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -723,7 +779,7 @@ def test_074__pem_cert_chain_generate(self, mock_get): self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\ncertificateBase642\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\ncertificateBase643\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) @patch('requests.get') - def test_075__pem_cert_chain_generate(self, mock_get): + def test_081__pem_cert_chain_generate(self, mock_get): """ _pem_cert_chain_generate - issuerCa in """ cert_dic = {'issuerCa': 'issuerCa', 'certificateBase64': 'certificateBase641'} mockresponse1 = Mock() @@ -733,12 +789,12 @@ def test_075__pem_cert_chain_generate(self, mock_get): mock_get.side_effect = [mockresponse1, mockresponse2] self.assertEqual('-----BEGIN CERTIFICATE-----\ncertificateBase641\n-----END CERTIFICATE-----\n', self.cahandler._pem_cert_chain_generate(cert_dic)) - def test_076__enter__(self): + def test_082__enter__(self): """ test __enter__ """ self.cahandler.__enter__() @patch('requests.get') - def test_077_request_poll(self, mock_get): + def test_083_request_poll(self, mock_get): """ test request poll request returned exception """ mock_get.side_effect = Exception('exc_api_get') result = ('"status" field not found in response.', None, None, 'url', False) @@ -747,7 +803,7 @@ def test_077_request_poll(self, mock_get): self.assertIn('ERROR:test_a2c:CAhandler._request.poll() returned: exc_api_get', lcm.output) @patch('requests.get') - def test_078_request_poll(self, mock_get): + def test_084_request_poll(self, mock_get): """ test request poll request returned unknown status """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'unknown'} @@ -756,7 +812,7 @@ def test_078_request_poll(self, mock_get): self.assertEqual(result, self.cahandler._request_poll('url')) @patch('requests.get') - def test_079_request_poll(self, mock_get): + def test_085_request_poll(self, mock_get): """ test request poll request returned status rejected """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'rejected'} @@ -765,7 +821,7 @@ def test_079_request_poll(self, mock_get): self.assertEqual(result, self.cahandler._request_poll('url')) @patch('requests.get') - def test_080_request_poll(self, mock_get): + def test_086_request_poll(self, mock_get): """ test request poll request returned status accepted but no certinformation in """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'accepted', 'foo': 'bar'} @@ -774,7 +830,7 @@ def test_080_request_poll(self, mock_get): self.assertEqual(result, self.cahandler._request_poll('url')) @patch('requests.get') - def test_081_request_poll(self, mock_get): + def test_087_request_poll(self, mock_get): """ test request poll request returned status accepted but no certinformation in """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'accepted', 'certificate': 'certificate'} @@ -784,7 +840,7 @@ def test_081_request_poll(self, mock_get): @patch('examples.ca_handler.certifier_ca_handler.CAhandler._pem_cert_chain_generate') @patch('requests.get') - def test_082_request_poll(self, mock_get, mock_pemgen): + def test_088_request_poll(self, mock_get, mock_pemgen): """ test request poll request returned status accepted but no certinformation in """ mockresponse = Mock() mockresponse.json = lambda: {'status': 'accepted', 'certificate': 'certificate', 'certificateBase64': 'certificateBase64'} From 9089f1521306b7dad4976b80c9f10ad29b7bea7c Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 23 May 2021 18:35:05 +0200 Subject: [PATCH 19/51] [tst] unittests --- examples/ca_handler/nclm_ca_handler.py | 2 +- test/test_nclm_ca_handler.py | 131 +++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/examples/ca_handler/nclm_ca_handler.py b/examples/ca_handler/nclm_ca_handler.py index 2ba825db..4b8d8cf9 100644 --- a/examples/ca_handler/nclm_ca_handler.py +++ b/examples/ca_handler/nclm_ca_handler.py @@ -281,7 +281,7 @@ def _login(self): else: # If response code is not ok (200), print the resulting http error code with description self.logger.error(api_response.raise_for_status()) - sys.exit(0) + # sys.exit(0) def _request_import(self, csr): """ import certificate request to NCLM """ diff --git a/test/test_nclm_ca_handler.py b/test/test_nclm_ca_handler.py index c8c07e20..a66d4e53 100644 --- a/test/test_nclm_ca_handler.py +++ b/test/test_nclm_ca_handler.py @@ -300,6 +300,17 @@ def test_023_cert_id_lookup(self, mock_req, mock_comp): mock_comp.side_effect = [True, False] self.assertEqual('certificateId1', self.cahandler._cert_id_lookup('csr_cn', 'san_list')) + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') + @patch('requests.get') + def test_020_cert_id_lookup(self, mock_req, mock_comp): + """ CAhandler._cert_id_lookup() - two certs - 1st match """ + self.cahandler.api_host = 'api_host' + mockresponse = Mock() + mockresponse.json = lambda: {'certificates': [{'subjectAltName': 'subjectAltName1', 'certificateId': 'certificateId1'}, {'subjectAltName': 'subjectAltName2', 'certificateId': 'certificateId2'}]} + mock_req.return_value = mockresponse + mock_comp.side_effect = [True, False] + self.assertEqual('certificateId1', self.cahandler._cert_id_lookup(None, 'san_list')) + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') def test_024_cert_id_lookup(self, mock_req, mock_comp): @@ -798,6 +809,20 @@ def test_065__unusedrequests_get(self, mock_req): self.assertFalse(self.cahandler._unusedrequests_get()) self.assertIn('ERROR:test_a2c:CAhandler._unusedrequests_get() returned error: exc_req_unused', lcm.output) + @patch('requests.get') + def test_065__login(self, mock_get): + """ CAhandler._unusedrequests_get """ + self.cahandler.api_host = 'api_host' + mockresponse1 = Mock() + mockresponse1.status_code = lambda: 'foo' + mockresponse1.ok = None + mockresponse1.raise_for_status = Mock(return_value='status') + mock_get.return_value = mockresponse1 + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._login() + self.assertFalse(self.cahandler.headers) + self.assertIn('ERROR:test_a2c:status', lcm.output) + @patch('requests.post') @patch('requests.get') def test_066__login(self, mock_get, mock_post): @@ -826,6 +851,23 @@ def test_067__login(self, mock_get, mock_post): self.cahandler._login() self.assertEqual({'Authorization': 'Bearer access_token'}, self.cahandler.headers) + @patch('requests.post') + @patch('requests.get') + def test_167__login(self, mock_get, mock_post): + """ CAhandler._unusedrequests_get mock_post without username""" + self.cahandler.api_host = 'api_host' + mockresponse1 = Mock() + mockresponse1.status_code = lambda: 'foo' + mock_get.return_value = mockresponse1 + mockresponse2 = Mock() + mockresponse2.ok = None + mockresponse2.raise_for_status = Mock(return_value='post_status') + mock_post.return_value = mockresponse2 + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._login() + self.assertFalse(self.cahandler.headers) + self.assertIn('ERROR:test_a2c:post_status', lcm.output) + @patch('requests.post') @patch('requests.get') def test_068__login(self, mock_get, mock_post): @@ -1124,6 +1166,95 @@ def test_097__template_id_lookup(self, mock_req): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) self.assertIn('ERROR:test_a2c:CAhandler._template_id_lookup() returned error: req_exc', lcm.output) + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_load') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') + def test_098__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + """ test enter """ + self.cahandler.__enter__() + self.assertTrue(mock_load.called) + self.assertTrue(mock_check.called) + self.assertTrue(mock_login.called) + self.assertTrue(mock_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_load') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') + def test_099__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + """ test enter with host already defined """ + self.cahandler.api_host = 'api_host' + self.cahandler.__enter__() + self.assertFalse(mock_load.called) + self.assertFalse(mock_check.called) + self.assertTrue(mock_login.called) + self.assertTrue(mock_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_load') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') + def test_100__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + """ test enter with header defined """ + self.cahandler.headers = 'header' + self.cahandler.__enter__() + self.assertTrue(mock_load.called) + self.assertTrue(mock_check.called) + self.assertFalse(mock_login.called) + self.assertTrue(mock_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_load') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') + def test_101__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + """ test enter with error defined """ + self.cahandler.error = 'error' + self.cahandler.__enter__() + self.assertTrue(mock_load.called) + self.assertTrue(mock_check.called) + self.assertFalse(mock_login.called) + self.assertFalse(mock_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_load') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') + def test_102__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + """ test enter with tst_info_dic defined """ + self.cahandler.tsg_info_dic = {'id': 'foo'} + self.cahandler.__enter__() + self.assertTrue(mock_load.called) + self.assertTrue(mock_check.called) + self.assertTrue(mock_login.called) + self.assertFalse(mock_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_load') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') + def test_103__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + """ test enter with error defined """ + self.cahandler.tsg_info_dic = {'id': 'foo'} + self.cahandler.error = 'error' + self.cahandler.__enter__() + self.assertTrue(mock_load.called) + self.assertTrue(mock_check.called) + self.assertFalse(mock_login.called) + self.assertFalse(mock_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') + @patch('requests.get') + def test_104_revoke(self, mock_get, mock_serial): + """ test revoke """ + self.cahandler.api_host = 'api_host' + mock_serial.return_value = 11 + mockresponse = Mock() + mockresponse.json = lambda: {'foo': 'bar'} + mock_get.return_value = mockresponse + self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'Cert could not be found'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + if __name__ == '__main__': if os.path.exists('acme_test.db'): From e83a31cdb628b501be52c5966617dcd1b3b7d9e1 Mon Sep 17 00:00:00 2001 From: grindsa Date: Mon, 24 May 2021 21:33:55 +0200 Subject: [PATCH 20/51] [feat] passphrase environment variable in openssl-handler --- examples/ca_handler/nclm_ca_handler.py | 22 +- examples/ca_handler/openssl_ca_handler.py | 123 +++-- test/test_nclm_ca_handler.py | 359 ++++++++++--- test/test_openssl_ca_handler.py | 607 +++++++++++++++++++--- 4 files changed, 907 insertions(+), 204 deletions(-) diff --git a/examples/ca_handler/nclm_ca_handler.py b/examples/ca_handler/nclm_ca_handler.py index 4b8d8cf9..12ee2043 100644 --- a/examples/ca_handler/nclm_ca_handler.py +++ b/examples/ca_handler/nclm_ca_handler.py @@ -23,6 +23,7 @@ def __init__(self, _debug=None, logger=None): self.headers = None self.ca_name = None self.error = None + self.wait_interval = 5 def __enter__(self): """ Makes CAhandler a Context Manager """ @@ -401,7 +402,7 @@ def enroll(self, csr): data_dic['templateID'] = self.template_info_dic['id'] self._api_post(self.api_host + '/targetsystemgroups/' + str(self.tsg_info_dic['id']) + '/enroll/ca/' + str(ca_id), data_dic) # wait for certificate enrollment to get finished - time.sleep(5) + time.sleep(self.wait_interval) cert_id = self._cert_id_lookup(csr_cn, csr_san_list) if cert_id: (error, cert_bundle, cert_raw) = self._cert_bundle_build(cert_id) @@ -439,16 +440,25 @@ def revoke(self, cert, rev_reason, rev_date): hex_serial = ':'.join(serial[i:i+2] for i in range(0, len(serial), 2)) # search for certificate - cert_list = requests.get(self.api_host + '/certificates?freeText==' + str(hex_serial) + '&stateCurrent=false&stateHistory=false&stateWaiting=false&stateManual=false&stateUnattached=false&expiresAfter=%22%22&expiresBefore=%22%22&sortAttribute=createdAt&sortOrder=desc&containerId='+str(self.tsg_info_dic['id']), headers=self.headers, verify=self.ca_bundle).json() + try: + cert_list = requests.get(self.api_host + '/certificates?freeText==' + str(hex_serial) + '&stateCurrent=false&stateHistory=false&stateWaiting=false&stateManual=false&stateUnattached=false&expiresAfter=%22%22&expiresBefore=%22%22&sortAttribute=createdAt&sortOrder=desc&containerId='+str(self.tsg_info_dic['id']), headers=self.headers, verify=self.ca_bundle).json() + except BaseException as err_: + self.logger.error('CAhandler.revoke(): request get aborted with err:'.format(err_)) + cert_list = [] if 'certificates' in cert_list: try: cert_id = cert_list['certificates'][0]['certificateId'] data_dic = {'reason': rev_reason, 'time': rev_date} - detail = self._api_post(self.api_host + '/certificates/' + str(cert_id) + '/revocationrequest', data_dic) - code = 200 - message = None - except IndexError: + try: + detail = self._api_post(self.api_host + '/certificates/' + str(cert_id) + '/revocationrequest', data_dic) + code = 200 + message = None + except BaseException as err: + code = 500 + message = 'urn:ietf:params:acme:error:serverInternal' + detail = 'Revocation operation failed' + except BaseException: code = 404 message = 'urn:ietf:params:acme:error:serverInternal' detail = 'CertificateID could not be found' diff --git a/examples/ca_handler/openssl_ca_handler.py b/examples/ca_handler/openssl_ca_handler.py index d3aaf2e2..bc4805cc 100644 --- a/examples/ca_handler/openssl_ca_handler.py +++ b/examples/ca_handler/openssl_ca_handler.py @@ -117,10 +117,13 @@ def _certificate_extensions_add(self, cert_extension_dic, cert, ca_cert): for extension in cert_extension_dic: self.logger.debug('adding extension: {0}: {1}: {2}'.format(extension, cert_extension_dic[extension]['critical'], cert_extension_dic[extension]['value'])) if extension == 'subjectKeyIdentifier': + self.logger.info('_certificate_extensions_add(): subjectKeyIdentifier') _tmp_list.append(crypto.X509Extension(convert_string_to_byte(extension), critical=cert_extension_dic[extension]['critical'], value=convert_string_to_byte(cert_extension_dic[extension]['value']), subject=cert)) elif 'subject' in cert_extension_dic[extension]: + self.logger.info('_certificate_extensions_add(): subject') _tmp_list.append(crypto.X509Extension(convert_string_to_byte(extension), critical=cert_extension_dic[extension]['critical'], value=convert_string_to_byte(cert_extension_dic[extension]['value']), subject=cert)) elif 'issuer' in cert_extension_dic[extension]: + self.logger.info('_certificate_extensions_add(): issuer') _tmp_list.append(crypto.X509Extension(convert_string_to_byte(extension), critical=cert_extension_dic[extension]['critical'], value=convert_string_to_byte(cert_extension_dic[extension]['value']), issuer=ca_cert)) else: _tmp_list.append(crypto.X509Extension(type_name=convert_string_to_byte(extension), critical=cert_extension_dic[extension]['critical'], value=convert_string_to_byte(cert_extension_dic[extension]['value']))) @@ -135,30 +138,31 @@ def _certificate_extensions_load(self): file_dic = dict(load_config(self.logger, None, self.openssl_conf)) cert_extention_dic = {} - for extension in file_dic['extensions']: + if 'extensions' in file_dic: + for extension in file_dic['extensions']: - cert_extention_dic[extension] = {} - parameters = file_dic['extensions'][extension].split(',') + cert_extention_dic[extension] = {} + parameters = file_dic['extensions'][extension].split(',') - # set crititcal task if applicable - if parameters[0] == 'critical': - cert_extention_dic[extension]['critical'] = bool(parameters.pop(0)) - else: - cert_extention_dic[extension]['critical'] = False + # set crititcal task if applicable + if parameters[0] == 'critical': + cert_extention_dic[extension]['critical'] = bool(parameters.pop(0)) + else: + cert_extention_dic[extension]['critical'] = False - # remove leading blank from first element - parameters[0] = parameters[0].lstrip() + # remove leading blank from first element + parameters[0] = parameters[0].lstrip() - # check if we have an issuer option (if so remove it and mark it as to be set) - if 'issuer:' in parameters[-1]: - cert_extention_dic[extension]['issuer'] = bool(parameters.pop(-1)) + # check if we have an issuer option (if so remove it and mark it as to be set) + if 'issuer:' in parameters[-1]: + cert_extention_dic[extension]['issuer'] = bool(parameters.pop(-1)) - # check if we have an issuer option (if so remove it and mark it as to be set) - if 'subject:' in parameters[-1]: - cert_extention_dic[extension]['subject'] = bool(parameters.pop(-1)) + # check if we have an issuer option (if so remove it and mark it as to be set) + if 'subject:' in parameters[-1]: + cert_extention_dic[extension]['subject'] = bool(parameters.pop(-1)) - # combine the remaining items and put them in as values - cert_extention_dic[extension]['value'] = ','.join(parameters) + # combine the remaining items and put them in as values + cert_extention_dic[extension]['value'] = ','.join(parameters) self.logger.debug('CAhandler._certificate_extensions_load() ended') return cert_extention_dic @@ -176,11 +180,15 @@ def _certificate_store(self, cert): # determine filename if self.save_cert_as_hex: + self.logger.info('convert serial to hex: {0}: {1}'.format(serial, '{:X}'.format(serial))) cert_file = '{:X}'.format(serial) else: cert_file = str(serial) with open('{0}/{1}.pem'.format(self.cert_save_path, cert_file), 'wb') as fso: fso.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) + else: + self.logger.error('CAhandler._certificate_store() handler configuration incomplete: cert_save_path is missing') + self.logger.debug('CAhandler._certificate_store() ended') def _config_check(self): @@ -237,7 +245,14 @@ def _config_load(self): self.issuer_dict['issuing_ca_key'] = config_dic['CAhandler']['issuing_ca_key'] if 'issuing_ca_cert' in config_dic['CAhandler']: self.issuer_dict['issuing_ca_cert'] = config_dic['CAhandler']['issuing_ca_cert'] + if 'issuing_ca_key_passphrase_variable' in config_dic['CAhandler']: + try: + self.issuer_dict['passphrase'] = os.environ[config_dic['CAhandler']['issuing_ca_key_passphrase_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load issuing_ca_key_passphrase_variable:{0}'.format(err)) if 'issuing_ca_key_passphrase' in config_dic['CAhandler']: + if 'passphrase' in self.issuer_dict and self.issuer_dict['passphrase']: + self.logger.info('CAhandler._config_load() overwrite issuing_ca_key_passphrase_variable') self.issuer_dict['passphrase'] = config_dic['CAhandler']['issuing_ca_key_passphrase'] if 'ca_cert_chain_list' in config_dic['CAhandler']: self.ca_cert_chain_list = json.loads(config_dic['CAhandler']['ca_cert_chain_list']) @@ -465,7 +480,6 @@ def enroll(self, csr): # store certifiate self._certificate_store(cert) - # create bundle and raw cert cert_bundle = self._pemcertchain_generate(convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)), open(self.issuer_dict['issuing_ca_cert']).read()) cert_raw = convert_byte_to_string(base64.b64encode(crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))) @@ -474,6 +488,7 @@ def enroll(self, csr): except BaseException as err: self.logger.error('CAhandler.enroll() error: {0}'.format(err)) + error = 'Unknown exception' self.logger.debug('CAhandler.enroll() ended') return(error, cert_bundle, cert_raw, None) @@ -508,46 +523,46 @@ def revoke(self, cert, rev_reason='unspecified', rev_date=None): # result = self._certificate_chain_verify(cert, ca_cert) result = None # proceed if the cert and ca-cert belong together - if not result: - serial = cert_serial_get(self.logger, cert) - # serial = serial.replace('0x', '') - if ca_key and ca_cert and serial: - serial = hex(serial).replace('0x', '') - if os.path.exists(self.issuer_dict['issuing_ca_crl']): - # existing CRL - with open(self.issuer_dict['issuing_ca_crl'], 'r') as fso: - crl = crypto.load_crl(crypto.FILETYPE_PEM, fso.read()) - # check CRL already contains serial - sn_match = self._crl_check(crl, serial) - else: - # new CRL - crl = crypto.CRL() - sn_match = None - - # this is the revocation operation - if not sn_match: - revoked = crypto.Revoked() - revoked.set_reason(convert_string_to_byte(rev_reason)) - revoked.set_serial(convert_string_to_byte(serial)) - revoked.set_rev_date(convert_string_to_byte(rev_date)) - crl.add_revoked(revoked) - # save CRL - crl_text = crl.export(ca_cert, ca_key, crypto.FILETYPE_PEM, 7, convert_string_to_byte('sha256')) - with open(self.issuer_dict['issuing_ca_crl'], 'wb') as fso: - fso.write(crl_text) - code = 200 - else: - code = 400 - message = 'urn:ietf:params:acme:error:alreadyRevoked' - detail = 'Certificate has already been revoked' + # if not result: + serial = cert_serial_get(self.logger, cert) + # serial = serial.replace('0x', '') + if ca_key and ca_cert and serial: + serial = hex(serial).replace('0x', '') + if os.path.exists(self.issuer_dict['issuing_ca_crl']): + # existing CRL + with open(self.issuer_dict['issuing_ca_crl'], 'r') as fso: + crl = crypto.load_crl(crypto.FILETYPE_PEM, fso.read()) + # check CRL already contains serial + sn_match = self._crl_check(crl, serial) + else: + # new CRL + crl = crypto.CRL() + sn_match = None + + # this is the revocation operation + if not sn_match: + revoked = crypto.Revoked() + revoked.set_reason(convert_string_to_byte(rev_reason)) + revoked.set_serial(convert_string_to_byte(serial)) + revoked.set_rev_date(convert_string_to_byte(rev_date)) + crl.add_revoked(revoked) + # save CRL + crl_text = crl.export(ca_cert, ca_key, crypto.FILETYPE_PEM, 7, convert_string_to_byte('sha256')) + with open(self.issuer_dict['issuing_ca_crl'], 'wb') as fso: + fso.write(crl_text) + code = 200 else: code = 400 - message = 'urn:ietf:params:acme:error:serverInternal' - detail = 'configuration error' + message = 'urn:ietf:params:acme:error:alreadyRevoked' + detail = 'Certificate has already been revoked' else: code = 400 message = 'urn:ietf:params:acme:error:serverInternal' - detail = result + detail = 'configuration error' + #else: + # code = 400 + # message = 'urn:ietf:params:acme:error:serverInternal' + # detail = result else: code = 400 message = 'urn:ietf:params:acme:error:serverInternal' diff --git a/test/test_nclm_ca_handler.py b/test/test_nclm_ca_handler.py index a66d4e53..e3bd4f62 100644 --- a/test/test_nclm_ca_handler.py +++ b/test/test_nclm_ca_handler.py @@ -302,7 +302,7 @@ def test_023_cert_id_lookup(self, mock_req, mock_comp): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') - def test_020_cert_id_lookup(self, mock_req, mock_comp): + def test_024_cert_id_lookup(self, mock_req, mock_comp): """ CAhandler._cert_id_lookup() - two certs - 1st match """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -313,7 +313,7 @@ def test_020_cert_id_lookup(self, mock_req, mock_comp): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') - def test_024_cert_id_lookup(self, mock_req, mock_comp): + def test_025_cert_id_lookup(self, mock_req, mock_comp): """ CAhandler._cert_id_lookup() - two certs - 2nd match """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -324,7 +324,7 @@ def test_024_cert_id_lookup(self, mock_req, mock_comp): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') - def test_025_cert_id_lookup(self, mock_req, mock_comp): + def test_026_cert_id_lookup(self, mock_req, mock_comp): """ CAhandler._cert_id_lookup() - no certificateid in """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -335,7 +335,7 @@ def test_025_cert_id_lookup(self, mock_req, mock_comp): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') - def test_026_cert_id_lookup(self, mock_req, mock_comp): + def test_027_cert_id_lookup(self, mock_req, mock_comp): """ CAhandler._cert_id_lookup() - two certs """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -346,7 +346,7 @@ def test_026_cert_id_lookup(self, mock_req, mock_comp): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') - def test_027_cert_id_lookup(self, mock_req, mock_comp): + def test_028_cert_id_lookup(self, mock_req, mock_comp): """ CAhandler._cert_id_lookup() - one cert - no san in """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -357,7 +357,7 @@ def test_027_cert_id_lookup(self, mock_req, mock_comp): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') - def test_028_cert_id_lookup(self, mock_req, mock_comp): + def test_029_cert_id_lookup(self, mock_req, mock_comp): """ CAhandler._cert_id_lookup() - no san_list in function """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -368,7 +368,7 @@ def test_028_cert_id_lookup(self, mock_req, mock_comp): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._san_compare') @patch('requests.get') - def test_029_cert_id_lookup(self, mock_req, mock_comp): + def test_030_cert_id_lookup(self, mock_req, mock_comp): """ CAhandler._cert_id_lookup() - one cert - ok """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -380,7 +380,7 @@ def test_029_cert_id_lookup(self, mock_req, mock_comp): self.assertIn('ERROR:test_a2c:_cert_id_lookup(): no certificates found for csr_cn', lcm.output) @patch('requests.get') - def test_030_cert_id_lookup(self, mock_req): + def test_031_cert_id_lookup(self, mock_req): """ CAhandler._cert_id_lookup() - request raises exception """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('req_exc') @@ -388,14 +388,14 @@ def test_030_cert_id_lookup(self, mock_req): self.assertFalse(self.cahandler._cert_id_lookup('csr_cn', 'san_list')) self.assertIn('ERROR:test_a2c:CAhandler._cert_id_lookup() returned error: req_exc', lcm.output) - def test_031__config_check(self): + def test_032__config_check(self): """ CAhandler._config.check() no api_host """ with self.assertLogs('test_a2c', level='INFO') as lcm: self.cahandler._config_check() self.assertEqual('api_host to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"api_host" to be set in config file', lcm.output) - def test_032__config_check(self): + def test_033__config_check(self): """ CAhandler._config.check() no api_user """ self.cahandler.api_host = 'api_host' with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -403,7 +403,7 @@ def test_032__config_check(self): self.assertEqual('api_user to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"api_user" to be set in config file', lcm.output) - def test_033__config_check(self): + def test_034__config_check(self): """ CAhandler._config.check() no api_user """ self.cahandler.api_host = 'api_host' self.cahandler.credential_dic = {'api_user': False} @@ -412,7 +412,7 @@ def test_033__config_check(self): self.assertEqual('api_user to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"api_user" to be set in config file', lcm.output) - def test_034__config_check(self): + def test_035__config_check(self): """ CAhandler._config.check() no api_password """ self.cahandler.api_host = 'api_host' self.cahandler.credential_dic = {'api_user': 'api_user'} @@ -421,7 +421,7 @@ def test_034__config_check(self): self.assertEqual('api_password to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"api_password" to be set in config file', lcm.output) - def test_035__config_check(self): + def test_036__config_check(self): """ CAhandler._config.check() no api_password """ self.cahandler.api_host = 'api_host' self.cahandler.credential_dic = {'api_user': 'api_user', 'api_password': False} @@ -430,7 +430,7 @@ def test_035__config_check(self): self.assertEqual('api_password to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"api_password" to be set in config file', lcm.output) - def test_036__config_check(self): + def test_037__config_check(self): """ CAhandler._config.check() no tsg_name """ self.cahandler.api_host = 'api_host' self.cahandler.credential_dic = {'api_user': 'api_user', 'api_password': 'api_password'} @@ -439,7 +439,7 @@ def test_036__config_check(self): self.assertEqual('tsg_name to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"tsg_name" to be set in config file', lcm.output) - def test_037__config_check(self): + def test_038__config_check(self): """ CAhandler._config.check() no tsg_name """ self.cahandler.api_host = 'api_host' self.cahandler.credential_dic = {'api_user': 'api_user', 'api_password': 'api_password'} @@ -449,7 +449,7 @@ def test_037__config_check(self): self.assertEqual('tsg_name to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"tsg_name" to be set in config file', lcm.output) - def test_038__config_check(self): + def test_039__config_check(self): """ CAhandler._config.check() no ca_name """ self.cahandler.api_host = 'api_host' self.cahandler.credential_dic = {'api_user': 'api_user', 'api_password': 'api_password'} @@ -459,7 +459,7 @@ def test_038__config_check(self): self.assertEqual('ca_name to be set in config file', self.cahandler.error) self.assertIn('ERROR:test_a2c:"ca_name" to be set in config file', lcm.output) - def test_039__config_check(self): + def test_040__config_check(self): """ CAhandler._config.check() ca_bundle False """ self.cahandler.api_host = 'api_host' self.cahandler.credential_dic = {'api_user': 'api_user', 'api_password': 'api_password'} @@ -473,7 +473,7 @@ def test_039__config_check(self): self.assertIn('WARNING:test_a2c:"ca_bundle" set to "False" - validation of server certificate disabled', lcm.output) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_040_config_load(self, mock_load_cfg): + def test_041_config_load(self, mock_load_cfg): """ CAhandler._config_load no cahandler section """ mock_load_cfg.return_value = {} self.cahandler._config_load() @@ -485,7 +485,7 @@ def test_040_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_041_config_load(self, mock_load_cfg): + def test_042_config_load(self, mock_load_cfg): """ CAhandler._config_load api_host """ mock_load_cfg.return_value = {'CAhandler': {'api_host': 'api_host'}} self.cahandler._config_load() @@ -497,7 +497,7 @@ def test_041_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_042_config_load(self, mock_load_cfg): + def test_043_config_load(self, mock_load_cfg): """ CAhandler._config_load api_user """ mock_load_cfg.return_value = {'CAhandler': {'api_user': 'api_user'}} self.cahandler._config_load() @@ -509,7 +509,7 @@ def test_042_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_043_config_load(self, mock_load_cfg): + def test_044_config_load(self, mock_load_cfg): """ CAhandler._config_load api_password """ mock_load_cfg.return_value = {'CAhandler': {'api_password': 'api_password'}} self.cahandler._config_load() @@ -521,7 +521,7 @@ def test_043_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_044_config_load(self, mock_load_cfg): + def test_045_config_load(self, mock_load_cfg): """ CAhandler._config_load ca_name """ mock_load_cfg.return_value = {'CAhandler': {'ca_name': 'ca_name'}} self.cahandler._config_load() @@ -533,7 +533,7 @@ def test_044_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_045_config_load(self, mock_load_cfg): + def test_046_config_load(self, mock_load_cfg): """ CAhandler._config_load tsg_name """ mock_load_cfg.return_value = {'CAhandler': {'tsg_name': 'tsg_name'}} self.cahandler._config_load() @@ -545,7 +545,7 @@ def test_045_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_046_config_load(self, mock_load_cfg): + def test_047_config_load(self, mock_load_cfg): """ CAhandler._config_load ca_bundle string """ mock_load_cfg.return_value = {'CAhandler': {'ca_bundle': 'ca_bundle'}} self.cahandler._config_load() @@ -557,7 +557,7 @@ def test_046_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_047_config_load(self, mock_load_cfg): + def test_048_config_load(self, mock_load_cfg): """ CAhandler._config_load ca_bundle False """ mock_load_cfg.return_value = {'CAhandler': {'ca_bundle': False}} self.cahandler._config_load() @@ -569,7 +569,7 @@ def test_047_config_load(self, mock_load_cfg): self.assertEqual({'name': None, 'id': None}, self.cahandler.template_info_dic) @patch('examples.ca_handler.nclm_ca_handler.load_config') - def test_048_config_load(self, mock_load_cfg): + def test_049_config_load(self, mock_load_cfg): """ CAhandler._config_load template_name """ mock_load_cfg.return_value = {'CAhandler': {'template_name': 'template_name'}} self.cahandler._config_load() @@ -582,7 +582,7 @@ def test_048_config_load(self, mock_load_cfg): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_048__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_050__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - all ok """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -592,7 +592,7 @@ def test_048__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_049__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_051__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - no requestID in list """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -602,7 +602,7 @@ def test_049__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_050__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_052__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - cn in mock_unureq not correctly ordered """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -612,7 +612,7 @@ def test_050__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_051__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_053__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - empty subjectName """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -622,7 +622,7 @@ def test_051__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_052__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_054__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - no subjectName """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -632,7 +632,7 @@ def test_052__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_053__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_055__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - requests to old """ mock_utsnow.return_value = 1000 mock_uts.return_value = 100 @@ -644,7 +644,7 @@ def test_053__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_054__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_056__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn one san """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -661,7 +661,7 @@ def test_054__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_055__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_057__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn two sans """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -678,7 +678,7 @@ def test_055__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_056__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_058__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn two sans to be reordered """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -695,7 +695,7 @@ def test_056__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_057__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_059__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn two sans to be reordered """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -712,7 +712,7 @@ def test_057__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_058__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_060__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn no requestID """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -729,7 +729,7 @@ def test_058__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_059__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_061__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn sans are not matching """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -746,7 +746,7 @@ def test_059__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_060__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_062__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn no pkcs10 """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -763,7 +763,7 @@ def test_060__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_061__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_063__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn request throws an exception """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -776,14 +776,14 @@ def test_061__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, self.assertIn('ERROR:test_a2c:CAhandler._csr_id_lookup() returned error: exc_csr_id_lookup', lcm.output) @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') - def test_062__request_import(self, mock_req): + def test_064__request_import(self, mock_req): """ CAhandler._request_import """ self.cahandler.api_host = 'api_host' mock_req.return_value = 'foo' self.assertEqual('foo', self.cahandler._request_import('csr')) @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') - def test_063__request_import(self, mock_req): + def test_065__request_import(self, mock_req): """ CAhandler._request_import - req raises an exception """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('exc_req_import') @@ -792,7 +792,7 @@ def test_063__request_import(self, mock_req): self.assertIn('ERROR:test_a2c:CAhandler._request_import() returned error: exc_req_import', lcm.output) @patch('requests.get') - def test_064__unusedrequests_get(self, mock_req): + def test_066__unusedrequests_get(self, mock_req): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -801,7 +801,7 @@ def test_064__unusedrequests_get(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._unusedrequests_get()) @patch('requests.get') - def test_065__unusedrequests_get(self, mock_req): + def test_067__unusedrequests_get(self, mock_req): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('exc_req_unused') @@ -810,7 +810,7 @@ def test_065__unusedrequests_get(self, mock_req): self.assertIn('ERROR:test_a2c:CAhandler._unusedrequests_get() returned error: exc_req_unused', lcm.output) @patch('requests.get') - def test_065__login(self, mock_get): + def test_068__login(self, mock_get): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -825,7 +825,7 @@ def test_065__login(self, mock_get): @patch('requests.post') @patch('requests.get') - def test_066__login(self, mock_get, mock_post): + def test_069__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -839,7 +839,7 @@ def test_066__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_067__login(self, mock_get, mock_post): + def test_070__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without username""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -853,7 +853,7 @@ def test_067__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_167__login(self, mock_get, mock_post): + def test_071__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without username""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -870,7 +870,7 @@ def test_167__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_068__login(self, mock_get, mock_post): + def test_072__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without realms""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -884,7 +884,7 @@ def test_068__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_069__login(self, mock_get, mock_post): + def test_073__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without access tooken""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -899,40 +899,40 @@ def test_069__login(self, mock_get, mock_post): self.assertFalse(self.cahandler.headers) self.assertIn('ERROR:test_a2c:CAhandler._login(): No token returned. Aborting...', lcm.output) - def test_070__san_compare(self): + def test_074__san_compare(self): """ CAhandler._san_compare all ok """ csr_san_list = ['foo:foo'] cert_san_list = {'foo': ['foo']} self.assertTrue(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_071__san_compare(self): + def test_075__san_compare(self): """ CAhandler._san_compare multiple """ csr_san_list = ['foo:foo', 'foo:bar'] cert_san_list = {'foo': ['foo', 'bar']} self.assertTrue(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_072__san_compare(self): + def test_076__san_compare(self): """ CAhandler._san_compare multiple """ csr_san_list = ['foo:foo,foo:bar'] cert_san_list = {'foo': ['foo', 'bar']} self.assertTrue(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_073__san_compare(self): + def test_077__san_compare(self): """ CAhandler._san_compare multiple """ csr_san_list = ['foo:foo,foo:bar1'] cert_san_list = {'foo': ['foo', 'bar']} self.assertFalse(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_074_poll(self): + def test_078_poll(self): """ CAhandler.poll() """ self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) - def test_075_trigger(self): + def test_079_trigger(self): """ CAhandler.trigger() """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) @patch('requests.get') - def test_076___tsg_id_lookup(self, mock_get): + def test_080___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - all ok """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -943,7 +943,7 @@ def test_076___tsg_id_lookup(self, mock_get): self.assertEqual({'name': 'name', 'id': 'id'}, self.cahandler.tsg_info_dic) @patch('requests.get') - def test_077___tsg_id_lookup(self, mock_get): + def test_081___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - multipe returned 1st matches """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -954,7 +954,7 @@ def test_077___tsg_id_lookup(self, mock_get): self.assertEqual({'name': 'name', 'id': 'id'}, self.cahandler.tsg_info_dic) @patch('requests.get') - def test_078___tsg_id_lookup(self, mock_get): + def test_082___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - multipe returned 2nd matches """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -965,7 +965,7 @@ def test_078___tsg_id_lookup(self, mock_get): self.assertEqual({'name': 'name', 'id': 'id'}, self.cahandler.tsg_info_dic) @patch('requests.get') - def test_079___tsg_id_lookup(self, mock_get): + def test_083___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - id is missing """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -978,7 +978,7 @@ def test_079___tsg_id_lookup(self, mock_get): self.assertIn("ERROR:test_a2c:CAhandler._tsg_id_lookup() incomplete response: {'name': 'name'}", lcm.output) @patch('requests.get') - def test_080___tsg_id_lookup(self, mock_get): + def test_084___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - name is missing """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -991,7 +991,7 @@ def test_080___tsg_id_lookup(self, mock_get): self.assertIn("ERROR:test_a2c:CAhandler._tsg_id_lookup() incomplete response: {'foo': 'bar', 'id': 'id'}", lcm.output) @patch('requests.get') - def test_081___tsg_id_lookup(self, mock_get): + def test_085___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - targetSystemGroups is missing """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1004,7 +1004,7 @@ def test_081___tsg_id_lookup(self, mock_get): self.assertIn('ERROR:test_a2c:CAhandler._tsg_id_lookup() no target-system-groups found for filter: name...', lcm.output) @patch('requests.get') - def test_082__tsg_id_lookup(self, mock_req): + def test_086__tsg_id_lookup(self, mock_req): """ CAhandler._request_import - req raises an exception """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('exc_tsg_id_lookup') @@ -1013,7 +1013,7 @@ def test_082__tsg_id_lookup(self, mock_req): self.assertIn('ERROR:test_a2c:CAhandler._tsg_id_lookup() returned error: exc_tsg_id_lookup', lcm.output) @patch('requests.get') - def test_083__template_id_lookup(self, mock_get): + def test_087__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - all ok """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1024,7 +1024,7 @@ def test_083__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': 10}, self.cahandler.template_info_dic) @patch('requests.get') - def test_084__template_id_lookup(self, mock_get): + def test_088__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - linkId None """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1035,7 +1035,7 @@ def test_084__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_085__template_id_lookup(self, mock_get): + def test_089__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - No linkId """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1046,7 +1046,7 @@ def test_085__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_086__template_id_lookup(self, mock_get): + def test_090__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no match in template names """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1057,7 +1057,7 @@ def test_086__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_088__template_id_lookup(self, mock_get): + def test_091__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - allowed false """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1068,7 +1068,7 @@ def test_088__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_089__template_id_lookup(self, mock_get): + def test_092__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - template in lower cases """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1079,7 +1079,7 @@ def test_089__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': 10}, self.cahandler.template_info_dic) @patch('requests.get') - def test_090__template_id_lookup(self, mock_get): + def test_093__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no template """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1090,7 +1090,7 @@ def test_090__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_091__template_id_lookup(self, mock_get): + def test_094__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no linktype """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1101,7 +1101,7 @@ def test_091__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_092__template_id_lookup(self, mock_get): + def test_095__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - empty list """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1112,7 +1112,7 @@ def test_092__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_093__template_id_lookup(self, mock_get): + def test_096__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no items """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1123,7 +1123,7 @@ def test_093__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_094__template_id_lookup(self, mock_get): + def test_097__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - wrong dict """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1134,7 +1134,7 @@ def test_094__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_095__template_id_lookup(self, mock_get): + def test_098__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - wrong dict """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1145,7 +1145,7 @@ def test_095__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_096__template_id_lookup(self, mock_get): + def test_099__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - empty response """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1156,7 +1156,7 @@ def test_096__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_097__template_id_lookup(self, mock_req): + def test_100__template_id_lookup(self, mock_req): """ CAhandler._cert_id_lookup() - request raises exception """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('req_exc') @@ -1170,7 +1170,7 @@ def test_097__template_id_lookup(self, mock_req): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_098__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_101__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter """ self.cahandler.__enter__() self.assertTrue(mock_load.called) @@ -1182,7 +1182,7 @@ def test_098__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_099__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_102__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with host already defined """ self.cahandler.api_host = 'api_host' self.cahandler.__enter__() @@ -1195,7 +1195,7 @@ def test_099__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_100__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_103__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with header defined """ self.cahandler.headers = 'header' self.cahandler.__enter__() @@ -1208,7 +1208,7 @@ def test_100__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_101__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_104__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with error defined """ self.cahandler.error = 'error' self.cahandler.__enter__() @@ -1221,7 +1221,7 @@ def test_101__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_102__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_105__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with tst_info_dic defined """ self.cahandler.tsg_info_dic = {'id': 'foo'} self.cahandler.__enter__() @@ -1234,7 +1234,7 @@ def test_102__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_103__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_106__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with error defined """ self.cahandler.tsg_info_dic = {'id': 'foo'} self.cahandler.error = 'error' @@ -1246,8 +1246,8 @@ def test_103__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') @patch('requests.get') - def test_104_revoke(self, mock_get, mock_serial): - """ test revoke """ + def test_107_revoke(self, mock_get, mock_serial): + """ test revoke empty certificate list has been returned """ self.cahandler.api_host = 'api_host' mock_serial.return_value = 11 mockresponse = Mock() @@ -1255,6 +1255,195 @@ def test_104_revoke(self, mock_get, mock_serial): mock_get.return_value = mockresponse self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'Cert could not be found'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') + @patch('requests.get') + def test_108_revoke(self, mock_get, mock_serial): + """ test revoke request get aborted with exception """ + self.cahandler.api_host = 'api_host' + mock_serial.return_value = 11 + mock_get.side_effect = Exception('ex_req_get') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'Cert could not be found'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + self.assertIn('ERROR:test_a2c:CAhandler.revoke(): request get aborted with err:', lcm.output) + + @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') + @patch('requests.get') + def test_109_revoke(self, mock_get, mock_serial): + """ test revoke certificates in certificate_list but content is bogus """ + self.cahandler.api_host = 'api_host' + mock_serial.return_value = 11 + mockresponse = Mock() + mockresponse.json = lambda: {'certificates': [{'foo': 'bar'}]} + mock_get.return_value = mockresponse + self.assertEqual((404, 'urn:ietf:params:acme:error:serverInternal', 'CertificateID could not be found'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + + @patch('requests.post') + @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') + @patch('requests.get') + def test_110_revoke(self, mock_get, mock_serial, mock_post): + """ test revoke certificates in certificate_list all good """ + self.cahandler.api_host = 'api_host' + mock_serial.return_value = 11 + mockresponse = Mock() + mockresponse.json = lambda: {'certificates': [{'certificateId': 100}]} + mock_get.return_value = mockresponse + mockresponse2 = Mock() + mockresponse2.json = lambda: {'foo': 'bar'} + mock_post.return_value = mockresponse2 + self.assertEqual((200, None, {'foo': 'bar'}), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') + @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') + @patch('requests.get') + def test_111_revoke(self, mock_get, mock_serial, mock_post): + """ test revoke certificates in certificate_list but request.post returns execption """ + self.cahandler.api_host = 'api_host' + mock_serial.return_value = 11 + mockresponse = Mock() + mockresponse.json = lambda: {'certificates': [{'certificateId': 100}]} + mock_get.return_value = mockresponse + mock_post.side_effect = Exception('ex_req_post') + self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'Revocation operation failed'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + + def test_112_enroll(self): + """ enroll() if there is an error """ + self.cahandler.error = 'foo' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, None, None, None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:foo', lcm.output) + + def test_113_enroll(self): + """ enroll() no target-system-id """ + self.cahandler.tsg_info_dic = {'id': None, 'name': 'name'} + self.assertEqual(('CAhandler.eroll(): ID lookup for targetSystemGroup "name" failed.', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._template_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._csr_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._request_import') + @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') + @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') + def test_114_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup): + """ enroll() without certid """ + self.cahandler.api_host = 'api_host' + self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} + self.cahandler.wait_interval = 0 + mock_lookup.return_value = 10 + mock_cn_get.return_value = 'cn' + mock_san_get.return_value = ['foo.bar.local'] + mock_reqimp.return_value = True + mock_csr_lookup.return_value = 10 + mock_post.return_value = True + mock_cert_lookup.return_value = None + self.assertEqual(("certifcate id lookup failed for: cn, ['foo.bar.local']", None, None, None), self.cahandler.enroll('csr')) + self.assertFalse(mock_tmpl_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_bundle_build') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._template_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._csr_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._request_import') + @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') + @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') + def test_115_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + """ enroll() with certid """ + self.cahandler.api_host = 'api_host' + self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} + self.cahandler.wait_interval = 0 + mock_lookup.return_value = 10 + mock_cn_get.return_value = 'cn' + mock_san_get.return_value = ['foo.bar.local'] + mock_reqimp.return_value = True + mock_csr_lookup.return_value = 10 + mock_post.return_value = True + mock_cert_lookup.return_value = 10 + mock_bundle.return_value = ('error', 'cert_bundle', 'cert_raw') + self.assertEqual(('error', 'cert_bundle', 'cert_raw', None), self.cahandler.enroll('csr')) + self.assertFalse(mock_tmpl_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_bundle_build') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._template_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._csr_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._request_import') + @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') + @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') + def test_116_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + """ enroll() no tmpload """ + self.cahandler.api_host = 'api_host' + self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} + self.cahandler.wait_interval = 0 + self.cahandler.template_info_dic = {'name': 'name', 'id': 'id'} + mock_lookup.return_value = 10 + mock_cn_get.return_value = 'cn' + mock_san_get.return_value = ['foo.bar.local'] + mock_reqimp.return_value = True + mock_csr_lookup.return_value = 10 + mock_post.return_value = True + mock_cert_lookup.return_value = 10 + mock_bundle.return_value = ('error', 'cert_bundle', 'cert_raw') + self.assertEqual(('error', 'cert_bundle', 'cert_raw', None), self.cahandler.enroll('csr')) + self.assertFalse(mock_tmpl_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_bundle_build') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._template_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._csr_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._request_import') + @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') + @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') + def test_117_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + """ enroll() tmpload """ + self.cahandler.api_host = 'api_host' + self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} + self.cahandler.wait_interval = 0 + self.cahandler.template_info_dic = {'name': 'name', 'id': None} + mock_lookup.return_value = 10 + mock_cn_get.return_value = 'cn' + mock_san_get.return_value = ['foo.bar.local'] + mock_reqimp.return_value = True + mock_csr_lookup.return_value = 10 + mock_post.return_value = True + mock_cert_lookup.return_value = 10 + mock_bundle.return_value = ('error', 'cert_bundle', 'cert_raw') + self.assertEqual(('error', 'cert_bundle', 'cert_raw', None), self.cahandler.enroll('csr')) + self.assertTrue(mock_tmpl_lookup.called) + + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_bundle_build') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._template_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._cert_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._csr_id_lookup') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._request_import') + @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') + @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') + @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') + def test_118_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + """ enroll() tmpload """ + self.cahandler.api_host = 'api_host' + self.cahandler.tsg_info_dic = {'id': 'id', 'name': 'name'} + self.cahandler.wait_interval = 0 + self.cahandler.template_info_dic = {'name': 'name', 'id': None} + mock_lookup.return_value = 0 + mock_cn_get.return_value = 'cn' + mock_san_get.return_value = ['foo.bar.local'] + mock_reqimp.return_value = True + mock_csr_lookup.return_value = 10 + mock_post.return_value = True + mock_cert_lookup.return_value = 10 + mock_bundle.return_value = ('error', 'cert_bundle', 'cert_raw') + self.assertEqual(('enrollment aborted. ca_id: 0, csr_id: 10, tsg_id: id', None, None, None), self.cahandler.enroll('csr')) + self.assertFalse(mock_tmpl_lookup.called) + + if __name__ == '__main__': if os.path.exists('acme_test.db'): diff --git a/test/test_openssl_ca_handler.py b/test/test_openssl_ca_handler.py index 930cc72e..c0ad6254 100644 --- a/test/test_openssl_ca_handler.py +++ b/test/test_openssl_ca_handler.py @@ -1,11 +1,12 @@ #!/usr/bin/python # -*- coding: utf-8 -*- """ unittests for openssl_ca_handler """ -# pylint: disable=C0415, R0904, W0212 +# pylint: disable=C0415, R0904, W0212 import sys import os import unittest -from unittest.mock import patch, mock_open +import configparser +from unittest.mock import patch, mock_open, Mock from OpenSSL import crypto sys.path.insert(0, '.') @@ -19,7 +20,7 @@ def setUp(self): import logging from examples.ca_handler.openssl_ca_handler import CAhandler logging.basicConfig(level=logging.CRITICAL) - self.logger = logging.getLogger('test_acme2certifier') + self.logger = logging.getLogger('test_a2c') self.cahandler = CAhandler(False, self.logger) self.dir_path = os.path.dirname(os.path.realpath(__file__)) @@ -149,22 +150,22 @@ def test_018_check_serialagainstcrl(self): crl = crypto.load_crl(crypto.FILETYPE_PEM, fso.read()) self.assertTrue(self.cahandler._crl_check(crl, '0bcc30c544ef26a4')) - def test_018_generate_pem_chain(self): + def test_019_generate_pem_chain(self): """ CAhandler._pemcertchain_generate with EE cert but no ca cert""" self.assertEqual('ee-cert', self.cahandler._pemcertchain_generate('ee-cert', None)) - def test_019_generate_pem_chain(self): + def test_020_generate_pem_chain(self): """ CAhandler._pemcertchain_generate with EE cert and ca cert""" self.assertEqual('ee-certca-cert', self.cahandler._pemcertchain_generate('ee-cert', 'ca-cert')) - def test_020_generate_pem_chain(self): + def test_021_generate_pem_chain(self): """ CAhandler._pemcertchain_generate with EE cert ca and an invalit entry in cert_cain_list cert""" self.cahandler.ca_cert_chain_list = ['foo.pem'] self.assertEqual('ee-certca-cert', self.cahandler._pemcertchain_generate('ee-cert', 'ca-cert')) @patch("builtins.open", mock_open(read_data='_fakeroot-cert-1'), create=True) @patch('os.path.exists') - def test_021_generate_pem_chain(self, mock_file): + def test_022_generate_pem_chain(self, mock_file): """ CAhandler._pemcertchain_generate with EE cert ca and an valid entry in cert_cain_list cert""" self.cahandler.ca_cert_chain_list = [self.dir_path + '/ca/fr1.txt'] mock_file.return_value = True @@ -173,7 +174,7 @@ def test_021_generate_pem_chain(self, mock_file): @patch("builtins.open", mock_open(read_data='_fakeroot-cert-1'), create=True) @patch('os.path.exists') - def test_022_generate_pem_chain(self, mock_file): + def test_023_generate_pem_chain(self, mock_file): """ CAhandler._pemcertchain_generate with EE cert ca and two valid entry in cert_cain_list""" self.cahandler.ca_cert_chain_list = [self.dir_path + '/ca/fr1.txt', self.dir_path + '/ca/fr2.txt'] mock_file.side_effect = [True, True] @@ -181,18 +182,18 @@ def test_022_generate_pem_chain(self, mock_file): @patch("builtins.open", mock_open(read_data='_fakeroot-cert-1'), create=True) @patch('os.path.exists') - def test_023_generate_pem_chain(self, mock_file): + def test_024_generate_pem_chain(self, mock_file): """ CAhandler._pemcertchain_generate with EE cert ca and two valid entry in cert_cain_list and two invalid entriest""" self.cahandler.ca_cert_chain_list = [self.dir_path + '/ca/fr1.txt', 'foo1', self.dir_path + '/ca/fr2.txt', 'foo2'] mock_file.side_effect = [True, False, True, False] self.assertEqual('ee-cert_ca-cert_fakeroot-cert-1_fakeroot-cert-1', self.cahandler._pemcertchain_generate('ee-cert', '_ca-cert')) - def test_024_load_ca_key_cert(self): + def test_025_load_ca_key_cert(self): """ CAhandler._ca_load() with empty issuer_dict """ self.cahandler.issuer_dict = {} self.assertEqual((None, None), self.cahandler._ca_load()) - def test_025_load_ca_key_cert(self): + def test_026_load_ca_key_cert(self): """ CAhandler._ca_load() with issuer_dict containing invalid key """ self.cahandler.issuer_dict = {'issuing_ca_key': 'foo.pem'} self.assertEqual((None, None), self.cahandler._ca_load()) @@ -200,7 +201,7 @@ def test_025_load_ca_key_cert(self): @patch("builtins.open", mock_open(read_data='test'), create=True) @patch('os.path.exists') @patch('OpenSSL.crypto.load_privatekey') - def test_026_load_ca_key_cert(self, mock_crypto, mock_file): + def test_027_load_ca_key_cert(self, mock_crypto, mock_file): """ CAhandler._ca_load() with issuer_dict containing valid key """ self.cahandler.issuer_dict = {'issuing_ca_key': self.dir_path + '/ca/sub-ca-key.pem'} mock_crypto.return_value = 'foo' @@ -211,7 +212,7 @@ def test_026_load_ca_key_cert(self, mock_crypto, mock_file): @patch('os.path.exists') @patch('OpenSSL.crypto.load_certificate') @patch('OpenSSL.crypto.load_privatekey') - def test_027_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file): + def test_028_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file): """ CAhandler._ca_load() with issuer_dict containing key and passphrase """ self.cahandler.issuer_dict = {'issuing_ca_key': self.dir_path + '/ca/sub-ca-key.pem', 'passphrase': 'Test1234'} mock_crypto_cert.return_value = 'cert' @@ -223,7 +224,7 @@ def test_027_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file @patch('os.path.exists') @patch('OpenSSL.crypto.load_certificate') @patch('OpenSSL.crypto.load_privatekey') - def test_028_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file): + def test_029_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file): """ CAhandler._ca_load() with issuer_dict containing key and invalid cert """ self.cahandler.issuer_dict = {'issuing_ca_key': self.dir_path + '/ca/sub-ca-key.pem', 'passphrase': 'Test1234', 'issuing_ca_cert': 'foo.pem'} mock_crypto_cert.return_value = None @@ -235,7 +236,7 @@ def test_028_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file @patch('os.path.exists') @patch('OpenSSL.crypto.load_certificate') @patch('OpenSSL.crypto.load_privatekey') - def test_029_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file): + def test_030_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file): """ CAhandler._ca_load() with issuer_dict containing key and invalid cert """ self.cahandler.issuer_dict = {'issuing_ca_key': self.dir_path + '/ca/sub-ca-key.pem', 'passphrase': 'Test1234', 'issuing_ca_cert': self.dir_path + '/ca/sub-ca-cert.pem'} mock_crypto_key.return_value = 'foo' @@ -243,7 +244,7 @@ def test_029_load_ca_key_cert(self, mock_crypto_key, mock_crypto_cert, mock_file mock_file.return_value = True self.assertEqual(('foo', 'bar'), self.cahandler._ca_load()) - def test_030_verifycertificatechain(self): + def test_031_verifycertificatechain(self): """ successful verification of one level certificate chain """ with open(self.dir_path + '/ca/root-ca-client.txt', 'r') as fso: cert = fso.read() @@ -251,7 +252,7 @@ def test_030_verifycertificatechain(self): ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, fso.read()) self.assertFalse(self.cahandler._certificate_chain_verify(cert, ca_cert)) - def test_031_verifycertificatechain(self): + def test_032_verifycertificatechain(self): """ unsuccessful verification of one level certificate chain """ with open(self.dir_path + '/ca/sub-ca-client.txt', 'r') as fso: cert = fso.read() @@ -259,7 +260,7 @@ def test_031_verifycertificatechain(self): ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, fso.read()) self.assertEqual("[20, 0, 'unable to get local issuer certificate']", self.cahandler._certificate_chain_verify(cert, ca_cert)) - def test_032_verifycertificatechain(self): + def test_033_verifycertificatechain(self): """ unsuccessful verification of two level certificate chain with incomplete chain""" with open(self.dir_path + '/ca/sub-ca-client.txt', 'r') as fso: cert = fso.read() @@ -267,7 +268,7 @@ def test_032_verifycertificatechain(self): ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, fso.read()) self.assertEqual("[2, 1, 'unable to get issuer certificate']", self.cahandler._certificate_chain_verify(cert, ca_cert)) - def test_033_verifycertificatechain(self): + def test_034_verifycertificatechain(self): """ successful verification of two level certificate chain with complete chain""" self.cahandler.ca_cert_chain_list = [self.dir_path + '/ca/root-ca-cert.pem'] with open(self.dir_path + '/ca/sub-ca-client.txt', 'r') as fso: @@ -276,21 +277,21 @@ def test_033_verifycertificatechain(self): ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, fso.read()) self.assertFalse(self.cahandler._certificate_chain_verify(cert, ca_cert)) - def test_034_verifycertificatechain(self): + def test_035_verifycertificatechain(self): """ unsuccessful verification as certificate is damaged""" cert = 'foo' with open(self.dir_path + '/ca/root-ca-cert.pem', 'r') as fso: ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, fso.read()) self.assertEqual('certificate could not get parsed', (self.cahandler._certificate_chain_verify(cert, ca_cert))) - def test_035_verifycertificatechain(self): + def test_036_verifycertificatechain(self): """ unsuccessful verification as ca-certificate is damaged""" with open(self.dir_path + '/ca/root-ca-client.txt', 'r') as fso: cert = fso.read() ca_cert = 'foo' self.assertEqual('issuing certificate could not be added to trust-store', self.cahandler._certificate_chain_verify(cert, ca_cert)) - def test_036_verifycertificatechain(self): + def test_037_verifycertificatechain(self): """ unsuccessful verification of two level certificate chain as cain cert is damaged""" self.cahandler.ca_cert_chain_list = ['ca/root-.pem'] with open(self.dir_path + '/ca/sub-ca-client.txt', 'r') as fso: @@ -299,13 +300,13 @@ def test_036_verifycertificatechain(self): ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, fso.read()) self.assertEqual('certificate ca/root-.pem could not be added to trust store', self.cahandler._certificate_chain_verify(cert, ca_cert)) - def test_037_revocation(self): + def test_038_revocation(self): """ revocation without having a CRL in issuer_dic """ with open(self.dir_path + '/ca/sub-ca-client.txt', 'r') as fso: cert = fso.read() self.assertEqual((400, 'urn:ietf:params:acme:error:serverInternal', 'Unsupported operation'), self.cahandler.revoke(cert)) - def test_038_revocation(self): + def test_039_revocation(self): """ revocation without having a CRL in issuer_dic but none""" self.cahandler.issuer_dict = {'crl' : None} with open(self.dir_path + '/ca/sub-ca-client.txt', 'r') as fso: @@ -385,203 +386,203 @@ def test_044_revocation(self, mock_vrf, mock_serial, mock_crl): mock_crl.return_value = True self.assertEqual((400, 'urn:ietf:params:acme:error:alreadyRevoked', 'Certificate has already been revoked'), self.cahandler.revoke(cert)) - def test_044_list_check(self): + def test_045_list_check(self): """ CAhandler._list_check failed check as empty entry""" list_ = ['bar.foo$', 'foo.bar$'] entry = None self.assertFalse(self.cahandler._list_check(entry, list_)) - def test_045_list_check(self): + def test_046_list_check(self): """ CAhandler._list_check check against empty list""" list_ = [] entry = 'host.bar.foo' self.assertTrue(self.cahandler._list_check(entry, list_)) - def test_046_list_check(self): + def test_047_list_check(self): """ CAhandler._list_check successful check against 1st element of a list""" list_ = ['bar.foo$', 'foo.bar$'] entry = 'host.bar.foo' self.assertTrue(self.cahandler._list_check(entry, list_)) - def test_047_list_check(self): + def test_048_list_check(self): """ CAhandler._list_check unsuccessful as endcheck failed""" list_ = ['bar.foo$', 'foo.bar$'] entry = 'host.bar.foo.bar_' self.assertFalse(self.cahandler._list_check(entry, list_)) - def test_048_list_check(self): + def test_049_list_check(self): """ CAhandler._list_check successful without $""" list_ = ['bar.foo', 'foo.bar$'] entry = 'host.bar.foo.bar_' self.assertTrue(self.cahandler._list_check(entry, list_)) - def test_049_list_check(self): + def test_050_list_check(self): """ CAhandler._list_check wildcard check""" list_ = ['bar.foo$', 'foo.bar$'] entry = '*.bar.foo' self.assertTrue(self.cahandler._list_check(entry, list_)) - def test_050_list_check(self): + def test_051_list_check(self): """ CAhandler._list_check failed wildcard check""" list_ = ['bar.foo$', 'foo.bar$'] entry = '*.bar.foo_' self.assertFalse(self.cahandler._list_check(entry, list_)) - def test_051_list_check(self): + def test_052_list_check(self): """ CAhandler._list_check not end check""" list_ = ['bar.foo$', 'foo.bar$'] entry = 'bar.foo gna' self.assertFalse(self.cahandler._list_check(entry, list_)) - def test_052_list_check(self): + def test_053_list_check(self): """ CAhandler._list_check $ at the end""" list_ = ['bar.foo$', 'foo.bar$'] entry = 'bar.foo$' self.assertFalse(self.cahandler._list_check(entry, list_)) - def test_053_list_check(self): + def test_054_list_check(self): """ CAhandler._list_check check against empty list flip""" list_ = [] entry = 'host.bar.foo' self.assertFalse(self.cahandler._list_check(entry, list_, True)) - def test_054_list_check(self): + def test_055_list_check(self): """ CAhandler._list_check flip successful check """ list_ = ['bar.foo$', 'foo.bar$'] entry = 'host.bar.foo' self.assertFalse(self.cahandler._list_check(entry, list_, True)) - def test_055_list_check(self): + def test_056_list_check(self): """ CAhandler._list_check flip unsuccessful check""" list_ = ['bar.foo$', 'foo.bar$'] entry = 'host.bar.foo' self.assertFalse(self.cahandler._list_check(entry, list_, True)) - def test_056_list_check(self): + def test_057_list_check(self): """ CAhandler._list_check unsuccessful whildcard check""" list_ = ['foo.bar$', r'\*.bar.foo'] entry = 'host.bar.foo' self.assertFalse(self.cahandler._list_check(entry, list_)) - def test_057_list_check(self): + def test_058_list_check(self): """ CAhandler._list_check successful whildcard check""" list_ = ['foo.bar$', r'\*.bar.foo'] entry = '*.bar.foo' self.assertTrue(self.cahandler._list_check(entry, list_)) - def test_056_string_wlbl_check(self): + def test_059_string_wlbl_check(self): """ CAhandler._string_wlbl_check against empty lists""" white_list = [] black_list = [] entry = 'host.bar.foo' self.assertTrue(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_057_string_wlbl_check(self): + def test_060_string_wlbl_check(self): """ CAhandler._string_wlbl_check against empty whitlist but match in blacklist """ white_list = [] black_list = ['host.bar.foo$'] entry = 'host.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_058_string_wlbl_check(self): + def test_061_string_wlbl_check(self): """ CAhandler._string_wlbl_check against empty whitlist but no match in blacklist """ white_list = [] black_list = ['faulty.bar.foo$'] entry = 'host.bar.foo' self.assertTrue(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_060_string_wlbl_check(self): + def test_062_string_wlbl_check(self): """ CAhandler._string_wlbl_check against empty whitlist wildcard check does not hit """ white_list = [] black_list = [r'\*.bar.foo$'] entry = 'host.bar.foo' self.assertTrue(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_061_string_wlbl_check(self): + def test_063_string_wlbl_check(self): """ CAhandler._string_wlbl_check against empty whitlist wildcard check hit """ white_list = [] black_list = [r'\*.bar.foo$'] entry = '*.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_062_string_wlbl_check(self): + def test_064_string_wlbl_check(self): """ CAhandler._string_wlbl_check successful wl check with empty bl""" white_list = ['foo.foo', 'bar.foo$'] black_list = [] entry = 'host.bar.foo' self.assertTrue(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_063_string_wlbl_check(self): + def test_065_string_wlbl_check(self): """ CAhandler._string_wlbl_check unsuccessful empty bl """ white_list = ['foo.foo$', 'host.bar.foo$'] black_list = [] entry = 'host.bar.foo.bar' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_064_string_wlbl_check(self): + def test_066_string_wlbl_check(self): """ CAhandler._string_wlbl_check unsuccessful host in bl""" white_list = ['foo.foo', 'bar.foo$'] black_list = ['host.bar.foo'] entry = 'host.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_065_string_wlbl_check(self): + def test_067_string_wlbl_check(self): """ CAhandler._string_wlbl_check unsuccessful host in bl but not on first position""" white_list = ['foo.foo', 'bar.foo$'] black_list = ['foo.bar$', 'host.bar.foo', 'foo.foo'] entry = 'host.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_066_string_wlbl_check(self): + def test_068_string_wlbl_check(self): """ CAhandler._string_wlbl_check successful wildcard in entry not n bl """ white_list = ['foo.foo', 'bar.foo$'] black_list = ['host.bar.foo'] entry = '*.bar.foo' self.assertTrue(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_067_string_wlbl_check(self): + def test_069_string_wlbl_check(self): """ CAhandler._string_wlbl_check successful wildcard blacklisting - no match""" white_list = ['foo.foo', 'bar.foo$'] black_list = [r'\*.bar.foo'] entry = 'host.bar.foo' self.assertTrue(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_068_string_wlbl_check(self): + def test_070_string_wlbl_check(self): """ CAhandler._string_wlbl_check failed wildcard black-listing """ white_list = ['foo.foo', 'bar.foo$'] black_list = [r'\*.bar.foo'] entry = '*.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_069_string_wlbl_check(self): + def test_071_string_wlbl_check(self): """ CAhandler._string_wlbl_check faked domain""" white_list = ['foo.foo', 'bar.foo$'] black_list = ['google.com.bar.foo'] entry = 'foo.google.com.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_070_string_wlbl_check(self): + def test_072_string_wlbl_check(self): """ CAhandler._string_wlbl_check faked wc domain""" white_list = ['foo.foo', 'bar.foo$'] black_list = ['google.com.bar.foo$'] entry = '*.google.com.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_071_string_wlbl_check(self): + def test_073_string_wlbl_check(self): """ CAhandler._string_wlbl_check faked domain""" white_list = ['foo.foo', 'bar.foo$'] black_list = ['google.com'] entry = '*.google.com.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_072_string_wlbl_check(self): + def test_074_string_wlbl_check(self): """ CAhandler._string_wlbl_check faked hostname and domain""" white_list = ['foo.foo', 'bar.foo$'] black_list = ['google.com'] entry = 'www.google.com.bar.foo' self.assertFalse(self.cahandler._string_wlbl_check(entry, white_list, black_list)) - def test_073_csr_check(self): + def test_075_csr_check(self): """ CAhandler._check_csr with empty whitelist and blacklists """ self.cahandler.whitelist = [] self.cahandler.blacklist = [] @@ -591,7 +592,7 @@ def test_073_csr_check(self): @patch('examples.ca_handler.openssl_ca_handler.CAhandler._string_wlbl_check') @patch('examples.ca_handler.openssl_ca_handler.csr_cn_get') @patch('examples.ca_handler.openssl_ca_handler.csr_san_get') - def test_074_csr_check(self, mock_san, mock_cn, mock_lcheck): + def test_076_csr_check(self, mock_san, mock_cn, mock_lcheck): """ CAhandler._check_csr with list and failed check """ self.cahandler.whitelist = ['foo.bar'] self.cahandler.blacklist = [] @@ -604,7 +605,7 @@ def test_074_csr_check(self, mock_san, mock_cn, mock_lcheck): @patch('examples.ca_handler.openssl_ca_handler.CAhandler._string_wlbl_check') @patch('examples.ca_handler.openssl_ca_handler.csr_cn_get') @patch('examples.ca_handler.openssl_ca_handler.csr_san_get') - def test_075_csr_check(self, mock_san, mock_cn, mock_lcheck): + def test_077_csr_check(self, mock_san, mock_cn, mock_lcheck): """ CAhandler._check_csr with list and successful check """ self.cahandler.whitelist = ['foo.bar'] self.cahandler.blacklist = [] @@ -617,7 +618,7 @@ def test_075_csr_check(self, mock_san, mock_cn, mock_lcheck): @patch('examples.ca_handler.openssl_ca_handler.CAhandler._string_wlbl_check') @patch('examples.ca_handler.openssl_ca_handler.csr_cn_get') @patch('examples.ca_handler.openssl_ca_handler.csr_san_get') - def test_076_csr_check(self, mock_san, mock_cn, mock_lcheck): + def test_078_csr_check(self, mock_san, mock_cn, mock_lcheck): """ CAhandler._check_csr san parsing failed """ self.cahandler.whitelist = ['foo.bar'] self.cahandler.blacklist = [] @@ -629,7 +630,7 @@ def test_076_csr_check(self, mock_san, mock_cn, mock_lcheck): @patch('examples.ca_handler.openssl_ca_handler.csr_cn_get') @patch('examples.ca_handler.openssl_ca_handler.csr_san_get') - def test_077_csr_check(self, mock_san, mock_cn): + def test_079_csr_check(self, mock_san, mock_cn): """ CAhandler._check_csr san parsing failed """ self.cahandler.whitelist = ['foo.bar'] self.cahandler.blacklist = [] @@ -638,6 +639,494 @@ def test_077_csr_check(self, mock_san, mock_cn): csr = 'csr' self.assertFalse(self.cahandler._csr_check(csr)) + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_load') + def test_080__enter__(self, mock_cfg): + """ test enter """ + mock_cfg.return_value = True + self.cahandler.__enter__() + self.assertTrue(mock_cfg.called) + + def test_081_trigger(self): + """ test trigger """ + self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) + + def test_082_poll(self): + """ test poll """ + self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier','csr')) + + def test_083_certificate_store(self): + """ _certificate_store() """ + cert = Mock() + cert.get_serial_number = Mock(return_value=42) + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._certificate_store(cert) + self.assertIn('ERROR:test_a2c:CAhandler._certificate_store() handler configuration incomplete: cert_save_path is missing', lcm.output) + + @patch('OpenSSL.crypto.dump_certificate') + @patch('builtins.open', mock_open(read_data="foo")) + @patch('os.mkdir') + @patch('os.path.isdir') + def test_084_certificate_store(self, mock_os, mock_mkdir, mock_dump): + """ _certificate_store() """ + mock_os.return_value = True + mock_mkdir.return_value = Mock() + cert = Mock() + cert.get_serial_number = Mock(return_value=42) + self.cahandler.cert_save_path = 'template' + mock_dump.return_value = 'foo' + self.cahandler._certificate_store(cert) + self.assertFalse(mock_mkdir.called) + + @patch('OpenSSL.crypto.dump_certificate') + @patch('builtins.open', mock_open(read_data="foo")) + @patch('os.mkdir') + @patch('os.path.isdir') + def test_085_certificate_store(self, mock_os, mock_mkdir, mock_dump): + """ _certificate_store() """ + mock_os.return_value = False + mock_mkdir.return_value = Mock() + cert = Mock() + cert.get_serial_number = Mock(return_value=42) + self.cahandler.cert_save_path = 'template' + mock_dump.return_value = 'foo' + self.cahandler._certificate_store(cert) + self.assertTrue(mock_mkdir.called) + + @patch('OpenSSL.crypto.dump_certificate') + @patch('builtins.open', mock_open(read_data="foo")) + @patch('os.mkdir') + @patch('os.path.isdir') + def test_086_certificate_store(self, mock_os, mock_mkdir, mock_dump): + """ _certificate_store() """ + mock_os.return_value = True + mock_mkdir.return_value = Mock() + cert = Mock() + cert.get_serial_number = Mock(return_value=42) + self.cahandler.cert_save_path = 'template' + self.cahandler.save_cert_as_hex = True + mock_dump.return_value = 'foo' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._certificate_store(cert) + self.assertIn('INFO:test_a2c:convert serial to hex: 42: 2A', lcm.output) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_087__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'save_cert_as_hex': False} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertFalse(self.cahandler.save_cert_as_hex ) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_088__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'save_cert_as_hex': True} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertTrue(self.cahandler.save_cert_as_hex ) + + @patch('json.loads') + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_089__config_load(self, mock_load_cfg, mock_jl): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'blacklist': 'foo.json'} + mock_load_cfg.return_value = parser + mock_jl.return_value = 'blacklist' + self.cahandler._config_load() + self.assertEqual('blacklist', self.cahandler.blacklist) + + @patch('json.loads') + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_090__config_load(self, mock_load_cfg, mock_jl): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'whitelist': 'foo.json'} + mock_load_cfg.return_value = parser + mock_jl.return_value = 'whitelist' + self.cahandler._config_load() + self.assertEqual('whitelist', self.cahandler.whitelist) + + @patch('json.loads') + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_091__config_load(self, mock_load_cfg, mock_jl): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'openssl_conf': 'openssl_conf'} + mock_load_cfg.return_value = parser + mock_jl.return_value = 'openssl_conf' + self.cahandler._config_load() + self.assertEqual('openssl_conf', self.cahandler.openssl_conf) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_092__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'issuing_ca_key': 'issuing_ca_key'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual('issuing_ca_key', self.cahandler.issuer_dict['issuing_ca_key']) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_093__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'issuing_ca_cert': 'issuing_ca_cert'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual('issuing_ca_cert', self.cahandler.issuer_dict['issuing_ca_cert']) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_094__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'issuing_ca_key_passphrase': 'issuing_ca_key_passphrase'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual(b'issuing_ca_key_passphrase', self.cahandler.issuer_dict['passphrase']) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_095__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'cert_validity_days': 10} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual(10, self.cahandler.cert_validity_days ) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_096__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'cert_save_path': 'cert_save_path'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual('cert_save_path', self.cahandler.cert_save_path) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_097__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'ca_cert_chain_list': '["root_ca"]'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual(['root_ca'], self.cahandler.ca_cert_chain_list) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_098__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'ca_cert_chain_list': '["root_ca", "sub_ca"]'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual(['root_ca', 'sub_ca'], self.cahandler.ca_cert_chain_list) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_099__config_load(self, mock_load_cfg): + """ config load """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'issuing_ca_crl': 'issuing_ca_crl'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual('issuing_ca_crl', self.cahandler.issuer_dict['issuing_ca_crl']) + + @patch.dict('os.environ', {'foo': 'foo_var'}) + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_100_config_load(self, mock_load_cfg): + """ test _config_load - load template with passphrase variable """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'issuing_ca_key_passphrase_variable': 'foo'} + mock_load_cfg.return_value = parser + self.cahandler._config_load() + self.assertEqual(b'foo_var', self.cahandler.issuer_dict['passphrase']) + + @patch.dict('os.environ', {'foo': 'foo_var'}) + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_101_config_load(self, mock_load_cfg): + """ test _config_load - load template passpharese variable configured but does not exist """ + parser = configparser.ConfigParser() + parser['CAhandler'] = {'issuing_ca_key_passphrase_variable': 'does_not_exist'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load issuing_ca_key_passphrase_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'foo': 'foo_var'}) + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_102_config_load(self, mock_load_cfg): + """ test _config_load - load template with passphrase variable - overwritten bei cfg file""" + parser = configparser.ConfigParser() + parser['CAhandler'] = {'issuing_ca_key_passphrase_variable': 'foo', 'issuing_ca_key_passphrase': 'foo_file'} + mock_load_cfg.return_value = parser + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual(b'foo_file', self.cahandler.issuer_dict['passphrase']) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite issuing_ca_key_passphrase_variable', lcm.output) + + @patch('OpenSSL.crypto.X509Extension') + def test_103___certificate_extensions_add(self, mock_ext): + """ extension list add """ + cert_extension_dic = {'foo1': {'critical': False, 'value': 'bar'}} + mock_ext.side_effect = ['foo1'] + result = ['foo1'] + self.assertEqual(result, self.cahandler._certificate_extensions_add(cert_extension_dic, 'cert', 'ca_cert')) + + @patch('OpenSSL.crypto.X509Extension') + def test_104___certificate_extensions_add(self, mock_ext): + """ extension list add """ + cert_extension_dic = {'subjectKeyIdentifier': {'critical': False, 'value': 'bar'}} + mock_ext.side_effect = ['foo1'] + result = ['foo1'] + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(result, self.cahandler._certificate_extensions_add(cert_extension_dic, 'cert', 'ca_cert')) + self.assertIn('INFO:test_a2c:_certificate_extensions_add(): subjectKeyIdentifier', lcm.output) + + @patch('OpenSSL.crypto.X509Extension') + def test_105___certificate_extensions_add(self, mock_ext): + """ extension list add """ + cert_extension_dic = {'foo': {'critical': False, 'value': 'bar', 'subject': True}} + mock_ext.side_effect = ['foo1'] + result = ['foo1'] + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(result, self.cahandler._certificate_extensions_add(cert_extension_dic, 'cert', 'ca_cert')) + self.assertIn('INFO:test_a2c:_certificate_extensions_add(): subject', lcm.output) + + @patch('OpenSSL.crypto.X509Extension') + def test_106___certificate_extensions_add(self, mock_ext): + """ extension list add """ + cert_extension_dic = {'foo': {'critical': False, 'value': 'bar', 'issuer': True}} + mock_ext.side_effect = ['foo1'] + result = ['foo1'] + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(result, self.cahandler._certificate_extensions_add(cert_extension_dic, 'cert', 'ca_cert')) + self.assertIn('INFO:test_a2c:_certificate_extensions_add(): issuer', lcm.output) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_107___certificate_extensions_load(self, mock_load_cfg): + """ extension list load - empty list """ + # mock_load_cfg.return_value = {'extensions': {'foo': 'critical, serverAuth'}} + mock_load_cfg.return_value = {'extensions': {'foo': 'bar'}} + result = {'foo': {'critical': False, 'value': 'bar'}} + self.assertEqual(result, self.cahandler._certificate_extensions_load()) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_108___certificate_extensions_load(self, mock_load_cfg): + """ extension list load - empty list """ + # mock_load_cfg.return_value = {'extensions': {'foo': 'critical, serverAuth'}} + mock_load_cfg.return_value = {'extensions': {'foo': 'bar, foobar'}} + result = {'foo': {'critical': False, 'value': 'bar, foobar'}} + self.assertEqual(result, self.cahandler._certificate_extensions_load()) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_109___certificate_extensions_load(self, mock_load_cfg): + """ extension list load - empty list """ + # mock_load_cfg.return_value = {'extensions': {'foo': 'critical, serverAuth'}} + mock_load_cfg.return_value = {'extensions': {'foo': 'bar', 'foo1': 'bar1'}} + result = {'foo': {'critical': False, 'value': 'bar'}, 'foo1': {'critical': False, 'value': 'bar1'}} + self.assertEqual(result, self.cahandler._certificate_extensions_load()) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_110___certificate_extensions_load(self, mock_load_cfg): + """ extension list load - empty list """ + mock_load_cfg.return_value = {'extensions': {'foo': 'critical, bar'}} + result = {'foo': {'critical': True, 'value': 'bar'}} + self.assertEqual(result, self.cahandler._certificate_extensions_load()) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_111___certificate_extensions_load(self, mock_load_cfg): + """ extension list load - empty list """ + # mock_load_cfg.return_value = {'extensions': {'foo': 'critical, serverAuth'}} + mock_load_cfg.return_value = {'extensions': {'foo': ' bar, foobar'}} + result = {'foo': {'critical': False, 'value': 'bar, foobar'}} + self.assertEqual(result, self.cahandler._certificate_extensions_load()) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_112___certificate_extensions_load(self, mock_load_cfg): + """ extension list load - empty list """ + # mock_load_cfg.return_value = {'extensions': {'foo': 'critical, serverAuth'}} + mock_load_cfg.return_value = {'extensions': {'foo': ' bar, issuer:'}} + result = {'foo': {'critical': False, 'issuer': True, 'value': 'bar'}} + self.assertEqual(result, self.cahandler._certificate_extensions_load()) + + @patch('examples.ca_handler.openssl_ca_handler.load_config') + def test_113___certificate_extensions_load(self, mock_load_cfg): + """ extension list load - empty list """ + # mock_load_cfg.return_value = {'extensions': {'foo': 'critical, serverAuth'}} + mock_load_cfg.return_value = {'extensions': {'foo': ' bar, subject:'}} + result = {'foo': {'critical': False, 'subject': True, 'value': 'bar'}} + self.assertEqual(result, self.cahandler._certificate_extensions_load()) + + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_check') + def test_114_enroll(self, mock_chk): + """ enroll test error returned from config_check""" + mock_chk.return_value = 'error' + self.assertEqual(('error', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._csr_check') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_check') + def test_115_enroll(self, mock_cfgchk, mock_csrchk): + """ enroll test error returned from config_check""" + mock_cfgchk.return_value = None + mock_csrchk.return_value = False + self.assertEqual(('urn:ietf:params:acme:badCSR', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._csr_check') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_check') + def test_116_enroll(self, mock_cfgchk, mock_csrchk): + """ enroll test error returned from config_check""" + mock_cfgchk.return_value = None + mock_csrchk.side_effect = Exception('exc_csr_check') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('Unknown exception', None, None, None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:CAhandler.enroll() error: exc_csr_check', lcm.output) + + @patch("builtins.open", mock_open(read_data='cacert'), create=True) + @patch('base64.b64encode') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._pemcertchain_generate') + @patch('examples.ca_handler.openssl_ca_handler.convert_byte_to_string') + @patch('OpenSSL.crypto.dump_certificate') + @patch('OpenSSL.crypto.X509Extension') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._csr_check') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_check') + def test_117_enroll(self, mock_cfgchk, mock_csrchk, mock_caload, mock_csrload, mock_x509, mock_ext, mock_dmp, mock_b2s, mock_pem, mock_b64e): + """ enroll test error cert_save_path is missing """ + mock_ext = Mock() + mock_cfgchk.return_value = None + mock_csrchk.return_value = True + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_caload.return_value = ('ca_key', ca_obj) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csrload.return_value = Mock() + mock_csrload.return_value.get_subject = Mock(return_value=dn_obj) + extension = Mock() + extension.get_short_name(return_value='short_name') + mock_csrload.return_value.get_extensions = Mock(return_value=[extension, extension]) + mock_x509 = Mock() + mock_dmp.return_value = 'dump' + mock_b2s.return_value = 'b2s' + mock_pem.return_value = 'pem' + mock_b64e.return_value = 'b64e' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, 'pem', 'b2s', None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:CAhandler._certificate_store() handler configuration incomplete: cert_save_path is missing', lcm.output) + + @patch("builtins.open", mock_open(read_data='cacert'), create=True) + @patch('base64.b64encode') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._pemcertchain_generate') + @patch('examples.ca_handler.openssl_ca_handler.convert_byte_to_string') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._certificate_store') + @patch('OpenSSL.crypto.dump_certificate') + @patch('OpenSSL.crypto.X509Extension') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._csr_check') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_check') + def test_118_enroll(self, mock_cfgchk, mock_csrchk, mock_caload, mock_csrload, mock_x509, mock_ext, mock_dmp, mock_store, mock_b2s, mock_pem, mock_b64e): + """ enroll """ + mock_ext = Mock() + mock_cfgchk.return_value = None + mock_csrchk.return_value = True + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_caload.return_value = ('ca_key', ca_obj) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csrload.return_value = Mock() + mock_csrload.return_value.get_subject = Mock(return_value=dn_obj) + extension = Mock() + extension.get_short_name(return_value='short_name') + mock_csrload.return_value.get_extensions = Mock(return_value=[extension, extension]) + mock_x509 = Mock() + mock_dmp.return_value = 'dump' + mock_store.return_value = True + mock_b2s.return_value = 'b2s' + mock_pem.return_value = 'pem' + mock_b64e.return_value = 'b64e' + self.assertEqual((None, 'pem', 'b2s', None), self.cahandler.enroll('csr')) + + @patch("builtins.open", mock_open(read_data='cacert'), create=True) + @patch('base64.b64encode') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._pemcertchain_generate') + @patch('examples.ca_handler.openssl_ca_handler.convert_byte_to_string') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._certificate_extensions_load') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._certificate_store') + @patch('OpenSSL.crypto.dump_certificate') + @patch('OpenSSL.crypto.X509Extension') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._csr_check') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_check') + def test_119_enroll(self, mock_cfgchk, mock_csrchk, mock_caload, mock_csrload, mock_x509, mock_ext, mock_dmp, mock_store, mock_ext_load, mock_b2s, mock_pem, mock_b64e): + """ enroll with extensions from openssl.cnf """ + mock_ext_load.return_value = {'foo': 'bar'} + mock_ext = Mock() + mock_cfgchk.return_value = None + mock_csrchk.return_value = True + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_caload.return_value = ('ca_key', ca_obj) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csrload.return_value = Mock() + mock_csrload.return_value.get_subject = Mock(return_value=dn_obj) + extension = Mock() + extension.get_short_name(return_value='short_name') + mock_csrload.return_value.get_extensions = Mock(return_value=[extension, extension]) + mock_x509 = Mock() + mock_dmp.return_value = 'dump' + mock_store.return_value = True + mock_b2s.return_value = 'b2s' + mock_pem.return_value = 'pem' + mock_b64e.return_value = 'b64e' + self.cahandler.openssl_conf = 'openssl.cnf' + self.assertEqual((None, 'pem', 'b2s', None), self.cahandler.enroll('csr')) + + @patch("builtins.open", mock_open(read_data='cacert'), create=True) + @patch('base64.b64encode') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._pemcertchain_generate') + @patch('examples.ca_handler.openssl_ca_handler.convert_byte_to_string') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._certificate_store') + @patch('OpenSSL.crypto.dump_certificate') + @patch('OpenSSL.crypto.X509Extension') + @patch('OpenSSL.crypto.X509') + @patch('OpenSSL.crypto.load_certificate_request') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._ca_load') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._csr_check') + @patch('examples.ca_handler.openssl_ca_handler.CAhandler._config_check') + def test_120_enroll(self, mock_cfgchk, mock_csrchk, mock_caload, mock_csrload, mock_x509, mock_ext, mock_dmp, mock_store, mock_b2s, mock_pem, mock_b64e): + """ enroll enrollment without extenstions """ + mock_ext = Mock() + mock_cfgchk.return_value = None + mock_csrchk.return_value = True + ca_obj = Mock() + ca_obj.subject_name_hash = Mock(return_value=42) + mock_caload.return_value = ('ca_key', ca_obj) + dn_obj = Mock() + dn_obj.CN = 'foo' + mock_csrload.return_value = Mock() + mock_csrload.return_value.get_subject = Mock(return_value=dn_obj) + extension = Mock() + extension.get_short_name = Mock(return_value='keyUsage') + mock_csrload.return_value.get_extensions = Mock(return_value=[extension]) + mock_x509 = Mock() + mock_dmp.return_value = 'dump' + mock_store.return_value = True + mock_b2s.return_value = 'b2s' + mock_pem.return_value = 'pem' + mock_b64e.return_value = 'b64e' + self.assertEqual((None, 'pem', 'b2s', None), self.cahandler.enroll('csr')) + + + if __name__ == '__main__': unittest.main() From 4f9e2bbf7cbcef72c0ce3ae333d635406a6131da Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 25 May 2021 15:21:17 +0200 Subject: [PATCH 21/51] [tst] unittests est-handler --- examples/ca_handler/est_ca_handler.py | 2 + test/ca/certs.p7b | 61 +++++++++++++++ test/ca/certs.pem | 63 ++++++++++++++++ test/test_est_ca_handler.py | 103 ++++++++++++++++++++++---- 4 files changed, 215 insertions(+), 14 deletions(-) create mode 100644 test/ca/certs.p7b create mode 100644 test/ca/certs.pem diff --git a/examples/ca_handler/est_ca_handler.py b/examples/ca_handler/est_ca_handler.py index 459a3394..d5875926 100644 --- a/examples/ca_handler/est_ca_handler.py +++ b/examples/ca_handler/est_ca_handler.py @@ -67,9 +67,11 @@ def _cacerts_get(self): if self.est_host: try: if self.est_client_cert: + self.logger.debug('CAhandler._cacerts_get() by using client-certs') # client auth response = requests.get(self.est_host + '/cacerts', cert=self.est_client_cert, verify=self.ca_bundle) else: + self.logger.debug('CAhandler._cacerts_get() by using userid/password') response = requests.get(self.est_host + '/cacerts', auth=HTTPBasicAuth(self.est_user, self.est_password), verify=self.ca_bundle) pem = self._pkcs7_to_pem(b64_decode(self.logger, response.text)) except BaseException as err_: diff --git a/test/ca/certs.p7b b/test/ca/certs.p7b new file mode 100644 index 00000000..dffb5416 --- /dev/null +++ b/test/ca/certs.p7b @@ -0,0 +1,61 @@ +-----BEGIN PKCS7----- +MIIK9AYJKoZIhvcNAQcCoIIK5TCCCuECAQExADALBgkqhkiG9w0BBwGgggrHMIIF +TzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UECxMO +YWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1NDAw +WhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEPMA0G +A1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxXHa +GZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8jqqx +kJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/qkzm +oO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT//Wrs +ChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCVXcB9 +ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9hcym +qchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLBZQjb +CPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB15Y5f +0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilMGueQ +ihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8hH2C +KnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dmKxzt +WBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0TAQH/ +BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYDVR0P +AQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNh +IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc31UV +yDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77WvDhy +1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP96YrR +cHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqHJh4s +KRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa7gdQ +J7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwCzM4p +tXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ32tUi +l9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/M7sI +BcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5Z3XW +WXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsFzfv6 +ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4tjX1v +lY35Ofonc4+6dRVamBiF9DCCBXAwggNYoAMCAQICCHry008TjKGYMA0GCSqGSIb3 +DQEBCwUAMCsxFzAVBgNVBAsTDmFjbWUyY2VydGlmaWVyMRAwDgYDVQQDEwdyb290 +LWNhMB4XDTIwMDUyNzAwMDAwMFoXDTMwMDUyNjIzNTk1OVowKzEXMBUGA1UECxMO +YWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCcuFGR3WYGLeuJP6xWpqAuu+rWL7Wm3roqlcNXOqFW +SPPe3BSxugWMMq9hGo+7Ra6kyQ3jDeL2UrnS7Jiw6upvCsF/64j81EyJXIzOWiDA +DWa/ayxLNzVrXIr6JQeWkNbJYXVYrVDy7sbBZ2HkE8sRcj+5Z4PTP2eNNyixvKYX +ZiozNLyZGo+Drijl391LFqlkGMkZf5rNO8VY9NrqtPC5KHjvo7UIrL8lV1EXWgnH +mbciv2QUOzRQrGytddnFUdXtmiaJezSQAOlpuogcwHZAANpd5IeNEi6BG2omlTIs +Szdr4pSGTjgKA11+Pk+oq/ipw1UidsruXPziTMLl8B64ey4INb7BUeUzXoZJ4Y1L +ljlDvtE5Cj4NgOyk4O9jmdpjnC2SG8c69T+UUb3Zi0Cz60xdhCb6UDzZm16jd2VV +hL3x045JExWP3bDk7xU4Eq4tec2CnIfL6LXFO8/gUIYJjLcDtiYTzJmegAXfbJCO +4o1qcDpbQIcbXaATuk+ggQqxNsl3Olfz8sgCnBYJTZiIIbeaF7JxPrm/3bcfH/SH +mv8TT3aOWhsvH3WoraJQytepHdym+zhOBzByMDscRdQRAKnq8cYWyzEQa/IUUmSO +XLy81i76QEOc7oYw+ld2/QWBXeLowLt85d5m83W2IxaBjl+mgWWhg8ZXODtlux8Z +7QIDAQABo4GXMIGUMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFAxlb7kxWGbR +AJM92n/cESgw7wLMMB8GA1UdIwQYMBaAFAxlb7kxWGbRAJM92n/cESgw7wLMMA4G +A1UdDwEB/wQEAwIBhjARBglghkgBhvhCAQEEBAMCAAcwHgYJYIZIAYb4QgENBBEW +D3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAI5KO3V/ogoE/ptyM +tVYOo+zEXrzwM6tZah0UTTXbdnLed9KSLrexb+VdsWJN+ZGvovxvl8jr012vbwFC +ogbYkZ1D7F7uFHEuwnKwlxMx8eHjrR56ecA4TtBcefzlGU2j/i+z3dRg/4/ed4m8 +eWzGvzPUY/kuPOp7Lee7bg0ZhAGrxQ4jHei94x+GEnJI5iB9rkngyGkWvZOmoNO+ +15lob1WEPbbke0Rm0rrldxXOqanBW21qaC4TUXBXPoW1CjrCpdnD/kBCj/x9rN1j +JZaoACimXjvtSjrBqNQg7OO+WyF8ggaRWx9hzj2rZrt8mUUPX4/bWvRFuOp99wxU +TS4pxVmuFibOMi1T9Y7oHtkwjsgNbetYsvvkUV0ht3uzRWKxGbgobdRHQwHcyFGP +PZvTQj8KA2EuAmoYJ35JDu2EHun+sqiuorMn/GRXKdbhefHhEQ4hfxQ6kvJy5gnV +EbiOegw6Dbw6YoOSf/UTVhvLxL7dqe0K43mdxAGrceSbmLcvzSkx2cCVpOdQoMxI +Mw8MxNiSIqnpXbS+XdEpenlbr9BtOARMrl8RFqYFVcwUuKhBSAUp0yc4LtT15iHd +8i74Nja/DSr8MmZjecShadAPQVqNec1tT1w2g/pd/aE2A+2oI15M0wI2CHHzSewE +yGBQ9MQLzQDn+9LO2jbqRX75BtmhADEA +-----END PKCS7----- diff --git a/test/ca/certs.pem b/test/ca/certs.pem new file mode 100644 index 00000000..4220cc0e --- /dev/null +++ b/test/ca/certs.pem @@ -0,0 +1,63 @@ +-----BEGIN CERTIFICATE----- +MIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE +CxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1 +NDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP +MA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +xXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8 +jqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/ +qkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/ +/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV +XcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9 +hcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB +ZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1 +5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM +GueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8 +hH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm +KxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T +AQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD +VR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP +eGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc +31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W +vDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9 +6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH +Jh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa +7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC +zM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3 +2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/ +M7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5 +Z3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF +zfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t +jX1vlY35Ofonc4+6dRVamBiF9A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE +CxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw +MDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ +MA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF +rqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ +1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW +qWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR +1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir ++KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ +2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS +ri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB +CrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK +16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9 +BYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD +VR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG +CWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl +MA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN +Ndt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX +EzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu +DRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3 +Fc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs +475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge +2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO +7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW +G8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6 +eVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp +0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF +fvkG2Q== +-----END CERTIFICATE----- diff --git a/test/test_est_ca_handler.py b/test/test_est_ca_handler.py index 982374d3..93f7e25f 100644 --- a/test/test_est_ca_handler.py +++ b/test/test_est_ca_handler.py @@ -7,6 +7,8 @@ import unittest from unittest.mock import patch, Mock import requests +import base64 +from OpenSSL import crypto sys.path.insert(0, '.') sys.path.insert(1, '..') @@ -17,10 +19,11 @@ class TestACMEHandler(unittest.TestCase): def setUp(self): """ setup unittest """ import logging - from examples.ca_handler.est_ca_handler import CAhandler + from examples.ca_handler.est_ca_handler import CAhandler, _get_certificates logging.basicConfig(level=logging.CRITICAL) self.logger = logging.getLogger('test_a2c') self.cahandler = CAhandler(False, self.logger) + self._get_certificates = _get_certificates self.dir_path = os.path.dirname(os.path.realpath(__file__)) def test_001_default(self): @@ -165,7 +168,7 @@ def test_018_trigger(self): @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch.object(requests, 'get') def test_019__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): - """ test _cacerts_get() successful run """ + """ test _cacerts_get() successful run by using client certs """ mockresponse = Mock() mock_req.return_value = mockresponse mockresponse.text = 'mock return' @@ -179,6 +182,21 @@ def test_019__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch.object(requests, 'get') def test_020__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): + """ test _cacerts_get() successful run by using client certs """ + mockresponse = Mock() + mock_req.return_value = mockresponse + mockresponse.text = 'mock return' + mock_to_pem.return_value = 'pem' + self.cahandler.est_host = 'foo' + self.cahandler.ca_bundle = ['foo_bundle'] + self.cahandler.est_user = 'est_user' + self.cahandler.est_password = 'est_password' + self.assertEqual((None, 'pem'), self.cahandler._cacerts_get()) + + @patch('examples.ca_handler.est_ca_handler.b64_decode') + @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') + @patch.object(requests, 'get') + def test_021__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() no est_host parameter """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -193,7 +211,7 @@ def test_020__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch('requests.get') - def test_021__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): + def test_022__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() request.get triggers exception """ mock_req.side_effect = Exception('exc_cacerts_get') mock_to_pem.return_value = 'pem' @@ -207,7 +225,7 @@ def test_021__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch.object(requests, 'post') - def test_022__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): + def test_023__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() successful run """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -221,7 +239,7 @@ def test_022__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch('requests.post') - def test_023__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): + def test_024__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() successful run """ mock_req.side_effect = Exception('exc_simple_enroll') mock_to_pem.return_value = 'pem' @@ -233,7 +251,7 @@ def test_023__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): self.assertIn('ERROR:test_a2c:CAhandler._simpleenroll() returned an error: exc_simple_enroll', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_024_enroll(self, mock_ca): + def test_025_enroll(self, mock_ca): """ test certificate enrollment _cacert_get returns error """ mock_ca.return_value = ('Error', None) self.cahandler.est_host = 'foo' @@ -242,7 +260,7 @@ def test_024_enroll(self, mock_ca): self.assertIn('ERROR:test_a2c:CAhandler.enroll(): Error', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_025_enroll(self, mock_ca): + def test_026_enroll(self, mock_ca): """ test certificate enrollment no error but now ca_certs """ mock_ca.return_value = (None, None) self.cahandler.est_host = 'foo' @@ -251,7 +269,7 @@ def test_025_enroll(self, mock_ca): self.assertIn('ERROR:test_a2c:CAhandler.enroll(): no CA certificates found', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_026_enroll(self, mock_ca): + def test_027_enroll(self, mock_ca): """ test certificate enrollment authentication information are missing """ mock_ca.return_value = (None, 'ca_pem') self.cahandler.est_host = 'foo' @@ -261,7 +279,7 @@ def test_026_enroll(self, mock_ca): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_027_enroll(self, mock_ca, mock_enroll): + def test_028_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment _simpleenroll returns error """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = ('Error', None) @@ -273,7 +291,7 @@ def test_027_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_028_enroll(self, mock_ca, mock_enroll): + def test_029_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment _simpleenroll returns certificate """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, 'cert') @@ -283,7 +301,7 @@ def test_028_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_029_enroll(self, mock_ca, mock_enroll): + def test_030_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert') @@ -293,7 +311,7 @@ def test_029_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_030_enroll(self, mock_ca, mock_enroll): + def test_031_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT END """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, 'cert-----END CERTIFICATE-----\n') @@ -303,7 +321,7 @@ def test_030_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_031_enroll(self, mock_ca, mock_enroll): + def test_032_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN AND END """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert-----END CERTIFICATE-----\n') @@ -313,7 +331,7 @@ def test_031_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_032_enroll(self, mock_ca, mock_enroll): + def test_033_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN AND END and \n""" mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n\n') @@ -321,6 +339,63 @@ def test_032_enroll(self, mock_ca, mock_enroll): self.cahandler.est_user = 'est_usr' self.assertEqual((None, '-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n\nca_pem', 'cert', None), self.cahandler.enroll('csr')) + @patch('examples.ca_handler.est_ca_handler.CAhandler._config_load') + def test_034__enter__(self, mock_cfg): + """ test enter called """ + mock_cfg.return_value = True + self.cahandler.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('examples.ca_handler.est_ca_handler.CAhandler._config_load') + def test_035__enter__(self, mock_cfg): + """ test enter api hosts defined """ + mock_cfg.return_value = True + self.cahandler.est_host = 'api_host' + self.cahandler.__enter__() + self.assertFalse(mock_cfg.called) + + def test_036_get_certificates(self): + """ test pkcs7 convrt to pem """ + cert_pem_list = [] + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_PEM, fso.read()) + cert_list = self._get_certificates(pkcs7) + + for cert in cert_list: + cert_pem_list.append(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) + result = [b'-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', b'-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] + self.assertEqual(result, cert_pem_list) + + def test_037__pkcs7_to_pem(self): + """ test pkcs7 to pem default output """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + with open(self.dir_path + '/ca/certs.pem', 'r') as fso: + result = fso.read() + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content)) + + def test_038__pkcs7_to_pem(self): + """ test pkcs7 to pem output string """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + with open(self.dir_path + '/ca/certs.pem', 'r') as fso: + result = fso.read() + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'string')) + + def test_039__pkcs7_to_pem(self): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + result = ['-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', '-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'list')) + + def test_040__pkcs7_to_pem(self): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + result = None + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) + if __name__ == '__main__': unittest.main() From def0c5da777dfe1b94c6dc06c9e1597e1d4bf96a Mon Sep 17 00:00:00 2001 From: grindsa Date: Wed, 26 May 2021 09:00:56 +0200 Subject: [PATCH 22/51] [doc] documenation of variables in certifier and openssl handlers --- docs/certifier.md | 2 + docs/openssl.md | 1 + examples/ca_handler/est_ca_handler.py | 3 +- test/test_est_ca_handler.py | 68 ++++++++++++++++++++------- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/docs/certifier.md b/docs/certifier.md index 7565e512..49c92ac4 100644 --- a/docs/certifier.md +++ b/docs/certifier.md @@ -29,7 +29,9 @@ polling_timeout: - api_host - URL of the Certifier-REST service - api_user - REST user +- api_user_variable - *optional* - name of the environment variable containing the REST username (a configured `api_user` parameter in acme_srv.cfg takes precedence) - api_password - password for REST user +- api_password_variable - *optional* - name of the environment variable containing the password for the REST user (a configured `api_password` parameter in acme_srv.cfg takes precedence) - ca_bundle - optional - certificate bundle needed to validate the server certificate - can be True/False or a filename (default: True) - ca_name - name of the CA used to enroll certificates - polling_timeout - optional - polling timeout (default: 60s) diff --git a/docs/openssl.md b/docs/openssl.md index 4188cd04..4c3dfd37 100644 --- a/docs/openssl.md +++ b/docs/openssl.md @@ -55,6 +55,7 @@ save_cert_as_hex: True - `issuing_ca_key` - private key of the issuing CA (in PEM format) used to sign certificates and CRLs - `issuing_ca_key_passphrase` - password to access the private key +- `issuing_ca_key_passphrase_variable` - *optional* - name of the environment variable containing the passphrase to access the CA key (a configured `issuing_ca_key_passphrase` parameter in acme_srv.cfg takes precedence) - `issuing_ca_cert` - Certificate of issuing CA in PEM format - `issuing_ca_crl` - CRL of issuing CA in PEM format - `ca_cert_chain_list` - List of root and intermediate CA certificates to be added to the bundle return to an ACME-client (the issueing CA cert must not be included) diff --git a/examples/ca_handler/est_ca_handler.py b/examples/ca_handler/est_ca_handler.py index d5875926..0f6fb070 100644 --- a/examples/ca_handler/est_ca_handler.py +++ b/examples/ca_handler/est_ca_handler.py @@ -133,9 +133,8 @@ def _pkcs7_to_pem(self, pkcs7_content, outform='string'): try: pkcs7 = crypto.load_pkcs7_data(filetype, pkcs7_content) break - except crypto.Error as _err: + except BaseException as _err: pkcs7 = None - # print(err) cert_pem_list = [] if pkcs7: diff --git a/test/test_est_ca_handler.py b/test/test_est_ca_handler.py index 93f7e25f..ad164b1f 100644 --- a/test/test_est_ca_handler.py +++ b/test/test_est_ca_handler.py @@ -250,8 +250,23 @@ def test_024__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): self.assertEqual(('exc_simple_enroll', None), self.cahandler._simpleenroll('csr')) self.assertIn('ERROR:test_a2c:CAhandler._simpleenroll() returned an error: exc_simple_enroll', lcm.output) + @patch('examples.ca_handler.est_ca_handler.b64_decode') + @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') + @patch('requests.post') + def test_025__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): + """ test _cacerts_get() successful run """ + mock_req.side_effect = Exception('exc_simple_enroll') + mock_to_pem.return_value = 'pem' + self.cahandler.est_host = 'foo' + self.cahandler.ca_bundle = ['foo_bundle'] + self.cahandler.est_user = 'est_user' + self.cahandler.est_password = 'est_password' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('exc_simple_enroll', None), self.cahandler._simpleenroll('csr')) + self.assertIn('ERROR:test_a2c:CAhandler._simpleenroll() returned an error: exc_simple_enroll', lcm.output) + @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_025_enroll(self, mock_ca): + def test_026_enroll(self, mock_ca): """ test certificate enrollment _cacert_get returns error """ mock_ca.return_value = ('Error', None) self.cahandler.est_host = 'foo' @@ -260,7 +275,7 @@ def test_025_enroll(self, mock_ca): self.assertIn('ERROR:test_a2c:CAhandler.enroll(): Error', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_026_enroll(self, mock_ca): + def test_027_enroll(self, mock_ca): """ test certificate enrollment no error but now ca_certs """ mock_ca.return_value = (None, None) self.cahandler.est_host = 'foo' @@ -269,7 +284,7 @@ def test_026_enroll(self, mock_ca): self.assertIn('ERROR:test_a2c:CAhandler.enroll(): no CA certificates found', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_027_enroll(self, mock_ca): + def test_028_enroll(self, mock_ca): """ test certificate enrollment authentication information are missing """ mock_ca.return_value = (None, 'ca_pem') self.cahandler.est_host = 'foo' @@ -279,7 +294,7 @@ def test_027_enroll(self, mock_ca): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_028_enroll(self, mock_ca, mock_enroll): + def test_029_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment _simpleenroll returns error """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = ('Error', None) @@ -291,7 +306,7 @@ def test_028_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_029_enroll(self, mock_ca, mock_enroll): + def test_030_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment _simpleenroll returns certificate """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, 'cert') @@ -301,7 +316,7 @@ def test_029_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_030_enroll(self, mock_ca, mock_enroll): + def test_031_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert') @@ -311,7 +326,7 @@ def test_030_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_031_enroll(self, mock_ca, mock_enroll): + def test_032_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT END """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, 'cert-----END CERTIFICATE-----\n') @@ -321,7 +336,7 @@ def test_031_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_032_enroll(self, mock_ca, mock_enroll): + def test_033_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN AND END """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert-----END CERTIFICATE-----\n') @@ -331,7 +346,7 @@ def test_032_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_033_enroll(self, mock_ca, mock_enroll): + def test_034_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN AND END and \n""" mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n\n') @@ -340,21 +355,21 @@ def test_033_enroll(self, mock_ca, mock_enroll): self.assertEqual((None, '-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n\nca_pem', 'cert', None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.est_ca_handler.CAhandler._config_load') - def test_034__enter__(self, mock_cfg): + def test_035__enter__(self, mock_cfg): """ test enter called """ mock_cfg.return_value = True self.cahandler.__enter__() self.assertTrue(mock_cfg.called) @patch('examples.ca_handler.est_ca_handler.CAhandler._config_load') - def test_035__enter__(self, mock_cfg): + def test_036__enter__(self, mock_cfg): """ test enter api hosts defined """ mock_cfg.return_value = True self.cahandler.est_host = 'api_host' self.cahandler.__enter__() self.assertFalse(mock_cfg.called) - def test_036_get_certificates(self): + def test_037_get_certificates(self): """ test pkcs7 convrt to pem """ cert_pem_list = [] with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: @@ -366,7 +381,7 @@ def test_036_get_certificates(self): result = [b'-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', b'-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] self.assertEqual(result, cert_pem_list) - def test_037__pkcs7_to_pem(self): + def test_038__pkcs7_to_pem(self): """ test pkcs7 to pem default output """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() @@ -374,7 +389,7 @@ def test_037__pkcs7_to_pem(self): result = fso.read() self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content)) - def test_038__pkcs7_to_pem(self): + def test_039__pkcs7_to_pem(self): """ test pkcs7 to pem output string """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() @@ -382,17 +397,38 @@ def test_038__pkcs7_to_pem(self): result = fso.read() self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'string')) - def test_039__pkcs7_to_pem(self): + def test_040__pkcs7_to_pem(self): """ test pkcs7 to pem output list """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() result = ['-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', '-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'list')) - def test_040__pkcs7_to_pem(self): + def test_041__pkcs7_to_pem(self): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + result = None + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) + + @patch('OpenSSL.crypto.load_pkcs7_data') + def test_042__pkcs7_to_pem(self, mock_load): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + # mock_load.side_effects = Exception('exc_load_pkcs7') + mock_load.return_value = None + result = None + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) + + @patch('OpenSSL.crypto') + def test_043__pkcs7_to_pem(self, mock_load): """ test pkcs7 to pem output list """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() + response = Mock() + response.load_pkcs7_data = Exception('exc_load_pkcs7') + mock_load.return_value = response result = None self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) From 996fcf74c22a3d2eac9f63b0116b8b8efdc4a17b Mon Sep 17 00:00:00 2001 From: grindsa Date: Thu, 27 May 2021 16:25:56 +0200 Subject: [PATCH 23/51] [tst] unittests --- examples/ca_handler/cmp_ca_handler.py | 1 - test/test_cmp_ca_handler.py | 140 +++++++++++++++++++++++++- 2 files changed, 138 insertions(+), 3 deletions(-) diff --git a/examples/ca_handler/cmp_ca_handler.py b/examples/ca_handler/cmp_ca_handler.py index 1c688d76..e1d161c5 100644 --- a/examples/ca_handler/cmp_ca_handler.py +++ b/examples/ca_handler/cmp_ca_handler.py @@ -158,7 +158,6 @@ def _pubkey_save(self, uts, pubkey): fso.write(pubkey) self.logger.debug('CAhandler._pubkey_save() ended') - def _tmp_files_delete(self, uts): """ delete temp files """ self.logger.debug('CAhandler._tmp_files_delete({0})'.format(uts)) diff --git a/test/test_cmp_ca_handler.py b/test/test_cmp_ca_handler.py index 496eeca4..d8e2ac21 100644 --- a/test/test_cmp_ca_handler.py +++ b/test/test_cmp_ca_handler.py @@ -5,7 +5,7 @@ import sys import os import unittest -from unittest.mock import patch +from unittest.mock import patch, mock_open, Mock # from OpenSSL import crypto import shutil @@ -14,7 +14,6 @@ class TestACMEHandler(unittest.TestCase): """ test class for cgi_handler """ - def setUp(self): """ setup unittest """ import logging @@ -220,6 +219,143 @@ def test_023_csr_san_get(self, mock_san): olist = [] self.assertEqual('"bar1, bar2"', self.cahandler._csr_san_get('csr')) + def test_023_poll(self): + """ test trigger """ + self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) + + def test_024_trigger(self): + """ test trigger """ + self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) + + def test_025_revoke(self): + """ test revoke """ + self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'Revocation is not supported.'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._config_load') + def test_026__enter__(self, mock_load): + """ test enter """ + self.cahandler.__enter__() + self.assertTrue(mock_load.called) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._config_load') + def test_027__enter__(self, mock_load): + """ test enter """ + self.cahandler.openssl_bin = 'openssl_bin' + self.cahandler.__enter__() + self.assertFalse(mock_load.called) + + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_028__pubkey_save(self): + """ test pubkey save """ + self.assertFalse(self.cahandler._pubkey_save('uts', 'pubkey')) + + @patch('os.remove') + @patch('os.path.isfile') + def test_029_tmp_files_delete(self, mock_exists, mock_remove): + """ test files_delete if file exists """ + mock_exists.return_value = True + self.cahandler._tmp_files_delete('uts') + self.assertTrue(mock_remove.called) + + @patch('os.remove') + @patch('os.path.isfile') + def test_030_tmp_files_delete(self, mock_exists, mock_remove): + """ test files_delete if file exists """ + mock_exists.return_value = False + self.cahandler._tmp_files_delete('uts') + self.assertFalse(mock_remove.called) + + @patch("builtins.open", mock_open(read_data='foo'), create=True) + @patch('os.path.isfile') + def test_031_certs_bundle(self, mock_exists): + """ certs bundle if no file exists """ + mock_exists.return_value = False + self.assertEqual((None, None), self.cahandler._certs_bundle('foo')) + + @patch("builtins.open", mock_open(read_data='foo'), create=True) + @patch('os.path.isfile') + def test_032_certs_bundle(self, mock_exists): + """ certs bundle if only capubs exists """ + mock_exists.side_effect = (True, False) + self.assertEqual((None, None), self.cahandler._certs_bundle('uts')) + + @patch("builtins.open", mock_open(read_data='foo'), create=True) + @patch('os.path.isfile') + def test_033_certs_bundle(self, mock_exists): + """ certs bundle if only cert exists """ + mock_exists.side_effect = (False, True) + self.assertEqual(('foo', 'foo'), self.cahandler._certs_bundle('uts')) + + @patch("builtins.open", mock_open(read_data='foo'), create=True) + @patch('os.path.isfile') + def test_034_certs_bundle(self, mock_exists): + """ certs bundle if all exists """ + mock_exists.side_effect = (True, True) + self.assertEqual(('foofoo', 'foo'), self.cahandler._certs_bundle('uts')) + + @patch("builtins.open", mock_open(read_data='-----BEGIN CERTIFICATE-----\nfoo'), create=True) + @patch('os.path.isfile') + def test_035_certs_bundle(self, mock_exists): + """ certs bundle if cert exists replace begin tag """ + mock_exists.side_effect = (False, True) + self.assertEqual(('-----BEGIN CERTIFICATE-----\nfoo', 'foo'), self.cahandler._certs_bundle('uts')) + + @patch("builtins.open", mock_open(read_data='-----BEGIN CERTIFICATE-----\nfoo-----END CERTIFICATE-----\n'), create=True) + @patch('os.path.isfile') + def test_036_certs_bundle(self, mock_exists): + """ certs bundle if cert exists replace end tag """ + mock_exists.side_effect = (False, True) + self.assertEqual(('-----BEGIN CERTIFICATE-----\nfoo-----END CERTIFICATE-----\n', 'foo'), self.cahandler._certs_bundle('uts')) + + @patch("builtins.open", mock_open(read_data='foo\n'), create=True) + @patch('os.path.isfile') + def test_037_certs_bundle(self, mock_exists): + """ certs bundle if cert exists replace end tag """ + mock_exists.side_effect = (False, True) + self.assertEqual(('foo\n', 'foo'), self.cahandler._certs_bundle('uts')) + + def test_038_opensslcmd_build(self): + """test _openssl_cmd_build()""" + self.cahandler.openssl_bin = 'openssl_bin' + self.cahandler.tmp_dir = '/tmp' + uts = 1234 + subject = 'subject' + san_list = 'foo1.bar.local' + result = ['openssl_bin', 'cmp', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] + self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) + + def test_039_opensslcmd_build(self): + """test _openssl_cmd_build() with option including in config dic""" + self.cahandler.openssl_bin = 'openssl_bin' + self.cahandler.tmp_dir = '/tmp' + self.cahandler.config_dic = {'foo1': 'bar1', 'foo2': 'bar2'} + uts = 1234 + subject = 'subject' + san_list = 'foo1.bar.local' + result = ['openssl_bin', 'cmp', '-foo1', 'bar1', '-foo2', 'bar2', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] + self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) + + def test_040_opensslcmd_build(self): + """test _openssl_cmd_build()""" + self.cahandler.openssl_bin = 'openssl_bin' + self.cahandler.tmp_dir = '/tmp' + self.cahandler.config_dic = {'-msgtimeout': 10} + uts = 1234 + subject = 'subject' + san_list = 'foo1.bar.local' + result = ['openssl_bin', 'cmp', '--msgtimeout', '10', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] + self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) + + def test_041_opensslcmd_build(self): + """test _openssl_cmd_build()""" + self.cahandler.openssl_bin = 'openssl_bin' + self.cahandler.tmp_dir = '/tmp' + self.cahandler.config_dic = {'-totaltimeout': 10} + uts = 1234 + subject = 'subject' + san_list = 'foo1.bar.local' + result = ['openssl_bin', 'cmp', '--totaltimeout', '10', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] + self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) if __name__ == '__main__': From 7a53ef4dd95ddc4c18fa68ff32b1354a3800e0d1 Mon Sep 17 00:00:00 2001 From: grindsa Date: Fri, 28 May 2021 07:37:27 +0200 Subject: [PATCH 24/51] [tst] unitests --- examples/ca_handler/cmp_ca_handler.py | 11 +- test/test_cmp_ca_handler.py | 165 ++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 4 deletions(-) diff --git a/examples/ca_handler/cmp_ca_handler.py b/examples/ca_handler/cmp_ca_handler.py index e1d161c5..b8223443 100644 --- a/examples/ca_handler/cmp_ca_handler.py +++ b/examples/ca_handler/cmp_ca_handler.py @@ -187,17 +187,20 @@ def enroll(self, csr): subject = csr_dn_get(self.logger, csr) if not subject: subject = '/CN=acme2certifier' - except BaseException: + except BaseException as err_: + self.logger.error('CAhandler.enroll(): csr_dn_get() failed with error: {0}'.format(err_)) subject = None # get public key from csr try: pubkey = csr_pubkey_get(self.logger, csr) - except BaseException: + except BaseException as err_: + self.logger.error('CAhandler.enroll(): csr_pubkey_get() failed with error: {0}'.format(err_)) pubkey = None # get subject alternate names try: san_list = self._csr_san_get(csr) - except BaseException: + except BaseException as err_: + self.logger.error('CAhandler.enroll(): _csr_san_get() failed with error: {0}'.format(err_)) san_list = [] if subject and pubkey and san_list: @@ -207,7 +210,7 @@ def enroll(self, csr): openssl_cmd = self._opensslcmd_build(uts, subject, san_list) rcode = subprocess.call(openssl_cmd) if rcode: - self.logger.warning('CAhandler enrollment failed: {0}'.format(rcode)) + self.logger.error('CAhandler.enroll(): failed: {0}'.format(rcode)) error = 'rc from enrollment not 0' # generate certificates we need to return if os.path.isfile('{0}/{1}_cert.pem'.format(self.tmp_dir, uts)): diff --git a/test/test_cmp_ca_handler.py b/test/test_cmp_ca_handler.py index d8e2ac21..27a5d9ad 100644 --- a/test/test_cmp_ca_handler.py +++ b/test/test_cmp_ca_handler.py @@ -357,6 +357,171 @@ def test_041_opensslcmd_build(self): result = ['openssl_bin', 'cmp', '--totaltimeout', '10', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) + def test_042_enroll(self): + """ test enroll without openssl_bin """ + self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') + def test_043_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): + """ test enroll csr_dn_get returns_exception """ + self.cahandler.openssl_bin = 'openssl_bin' + mock_dn_get.side_effect = Exception('ex_dn_get') + mock_pkey_get.return_value = 'pkey' + mock_san_get.return_value = 'san.foo.bar' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('CSR invalid', None, None, None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:CAhandler.enroll(): csr_dn_get() failed with error: ex_dn_get', lcm.output) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._certs_bundle') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._tmp_files_delete') + @patch('os.path.isfile') + @patch('subprocess.call') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._opensslcmd_build') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._pubkey_save') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') + def test_043_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + """ test enroll csr_dn_get returns None and gets corrected """ + self.cahandler.openssl_bin = 'openssl_bin' + mock_dn_get.return_value = None + mock_pkey_get.return_value = 'pkey' + mock_san_get.return_value = 'san.foo.bar' + mock_save.return_value = True + mock_build.return_value = 'opensslcmd' + mock_call.return_value = 0 + mock_exists.return_value = True + mock_bundle.return_value = ('cert_bundle', 'cert_raw') + mock_del.return_value = True + #with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, 'cert_bundle', 'cert_raw', None), self.cahandler.enroll('csr')) + #self.assertIn('ERROR:test_a2c:CAhandler.enroll(): csr_dn_get() failed with error: ex_dn_get', lcm.output) + self.assertTrue(mock_save.called) + self.assertTrue(mock_build.called) + self.assertTrue(mock_call.called) + self.assertTrue(mock_exists.called) + self.assertTrue(mock_del.called) + self.assertTrue(mock_bundle.called) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') + def test_045_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): + """ test enroll csr_pubkey_get returns_exception """ + self.cahandler.openssl_bin = 'openssl_bin' + mock_dn_get.return_value = 'dn' + mock_pkey_get.side_effect = Exception('ex_pubkey_get') + mock_san_get.return_value = 'san.foo.bar' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('CSR invalid', None, None, None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:CAhandler.enroll(): csr_pubkey_get() failed with error: ex_pubkey_get', lcm.output) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') + def test_046_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): + """ test enroll _csr_san_get returns_exception """ + self.cahandler.openssl_bin = 'openssl_bin' + mock_dn_get.return_value = 'dn' + mock_pkey_get.return_value = 'pkey' + mock_san_get.side_effect = Exception('ex_san_get') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('CSR invalid', None, None, None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:CAhandler.enroll(): _csr_san_get() failed with error: ex_san_get', lcm.output) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._certs_bundle') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._tmp_files_delete') + @patch('os.path.isfile') + @patch('subprocess.call') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._opensslcmd_build') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._pubkey_save') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') + def test_047_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + """ test enroll csr_dn_get runs through without issues """ + self.cahandler.openssl_bin = 'openssl_bin' + mock_dn_get.return_value = 'dn' + mock_pkey_get.return_value = 'pkey' + mock_san_get.return_value = 'san.foo.bar' + mock_save.return_value = True + mock_build.return_value = 'opensslcmd' + mock_call.return_value = 0 + mock_exists.return_value = True + mock_bundle.return_value = ('cert_bundle', 'cert_raw') + mock_del.return_value = True + #with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual((None, 'cert_bundle', 'cert_raw', None), self.cahandler.enroll('csr')) + #self.assertIn('ERROR:test_a2c:CAhandler.enroll(): csr_dn_get() failed with error: ex_dn_get', lcm.output) + self.assertTrue(mock_save.called) + self.assertTrue(mock_build.called) + self.assertTrue(mock_call.called) + self.assertTrue(mock_exists.called) + self.assertTrue(mock_del.called) + self.assertTrue(mock_bundle.called) + + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._certs_bundle') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._tmp_files_delete') + @patch('os.path.isfile') + @patch('subprocess.call') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._opensslcmd_build') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._pubkey_save') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') + def test_048_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + """ test enroll subprocess.call returns other than 0 """ + self.cahandler.openssl_bin = 'openssl_bin' + mock_dn_get.return_value = 'dn' + mock_pkey_get.return_value = 'pkey' + mock_san_get.return_value = 'san.foo.bar' + mock_save.return_value = True + mock_build.return_value = 'opensslcmd' + mock_call.return_value = 25 + mock_exists.return_value = True + mock_bundle.return_value = ('cert_bundle', 'cert_raw') + mock_del.return_value = True + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('rc from enrollment not 0', 'cert_bundle', 'cert_raw', None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:CAhandler.enroll(): failed: 25', lcm.output) + self.assertTrue(mock_save.called) + self.assertTrue(mock_build.called) + self.assertTrue(mock_call.called) + self.assertTrue(mock_exists.called) + self.assertTrue(mock_del.called) + self.assertTrue(mock_bundle.called) + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._certs_bundle') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._tmp_files_delete') + @patch('os.path.isfile') + @patch('subprocess.call') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._opensslcmd_build') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._pubkey_save') + @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') + @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') + + def test_049_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + """ test enroll subprocess.call files do not exist """ + self.cahandler.openssl_bin = 'openssl_bin' + mock_dn_get.return_value = 'dn' + mock_pkey_get.return_value = 'pkey' + mock_san_get.return_value = 'san.foo.bar' + mock_save.return_value = True + mock_build.return_value = 'opensslcmd' + mock_call.return_value = 0 + mock_exists.return_value = False + mock_bundle.return_value = ('cert_bundle', 'cert_raw') + mock_del.return_value = True + self.assertEqual(('Enrollment failed', None, None, None), self.cahandler.enroll('csr')) + self.assertTrue(mock_save.called) + self.assertTrue(mock_build.called) + self.assertTrue(mock_call.called) + self.assertTrue(mock_exists.called) + self.assertTrue(mock_del.called) + self.assertFalse(mock_bundle.called) + if __name__ == '__main__': unittest.main() From 68aa34d27b892b5bce7cfd4082d801bb661b5d2a Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 30 May 2021 12:06:40 +0200 Subject: [PATCH 25/51] Update eab.md --- docs/eab.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/eab.md b/docs/eab.md index bef0700b..9fd745fd 100644 --- a/docs/eab.md +++ b/docs/eab.md @@ -6,7 +6,7 @@ To enable EAB the CA operator needs to provide both ACME client and acme2certifier with a key identifier (kid) and a MAC key (mac_key) which will we be used to authenticate `NewAccount` requests. -kid and mac_key will be loaded into acme2certifer by using a plugin based mechanism. Two plugins will be shipped by default and are stored in the `example/eab_handler` directory. +Kid and mac_key will be loaded into acme2certifer by using a plugin based mechanism. Two plugins will be shipped by default and are stored in the `example/eab_handler` directory. The key identifers will be part of the reports created by [Housekeeping](housekeeping.md) class. From 1fa76eb66fd92adf060e6db7eeefbad2235d08d0 Mon Sep 17 00:00:00 2001 From: grindsa Date: Mon, 31 May 2021 08:07:43 +0200 Subject: [PATCH 26/51] [feat] ref/secret support via environtment variables --- examples/ca_handler/cmp_ca_handler.py | 31 +++++- test/test_cmp_ca_handler.py | 149 ++++++++++++++++++-------- 2 files changed, 130 insertions(+), 50 deletions(-) diff --git a/examples/ca_handler/cmp_ca_handler.py b/examples/ca_handler/cmp_ca_handler.py index b8223443..9f0c1219 100644 --- a/examples/ca_handler/cmp_ca_handler.py +++ b/examples/ca_handler/cmp_ca_handler.py @@ -17,6 +17,8 @@ def __init__(self, _debug=None, logger=None): self.openssl_bin = None self.tmp_dir = None self.recipient = None + self.ref = None + self.secret = None def __enter__(self): """ Makes CAhandler a Context Manager """ @@ -39,13 +41,13 @@ def _certs_bundle(self, uts): if os.path.isfile('{0}/{1}_capubs.pem'.format(self.tmp_dir, uts)): fso = open('{0}/{1}_capubs.pem'.format(self.tmp_dir, uts), 'r') ca_pem = fso.read() - fso.close + fso.close() # open certificate if os.path.isfile('{0}/{1}_cert.pem'.format(self.tmp_dir, uts)): fso = open('{0}/{1}_cert.pem'.format(self.tmp_dir, uts), 'r') cert_raw = fso.read() - fso.close + fso.close() # create bundle and raw cert if cert_raw and ca_pem: cert_bundle = cert_raw + ca_pem @@ -99,12 +101,33 @@ def _config_load(self): value = value.replace(', ', '/') value = value.replace(',', '/') self.config_dic['recipient'] = value + elif ele == 'cmp_ref_variable': + try: + self.ref = os.environ[config_dic['CAhandler']['cmp_ref_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load cmp_ref:{0}'.format(err)) + elif ele == 'cmp_secret_variable': + try: + self.secret = os.environ[config_dic['CAhandler']['cmp_secret_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load cmp_secret_variable:{0}'.format(err)) + elif ele in ('cmp_secret', 'cmp_ref'): + continue else: if config_dic['CAhandler'][ele] == 'True' or config_dic['CAhandler'][ele] == 'False': self.config_dic[ele[4:]] = config_dic.getboolean('CAhandler', ele, fallback=False) else: self.config_dic[ele[4:]] = config_dic['CAhandler'][ele] + if 'CAhandler' in config_dic and 'cmp_ref' in config_dic['CAhandler']: + if self.ref: + self.logger.info('CAhandler._config_load() overwrite cmp_ref variable') + self.ref = config_dic['CAhandler']['cmp_ref'] + if 'CAhandler' in config_dic and 'cmp_secret' in config_dic['CAhandler']: + if self.secret: + self.logger.info('CAhandler._config_load() overwrite cmp_secret variable') + self.secret = config_dic['CAhandler']['cmp_secret'] + if 'cmd' not in self.config_dic: self.config_dic['cmd'] = 'ir' if 'popo' not in self.config_dic: @@ -227,7 +250,7 @@ def enroll(self, csr): self.logger.debug('Certificate.enroll() ended with error: {0}'.format(error)) return(error, cert_bundle, cert_raw, None) - def poll(self, cert_name, poll_identifier, _csr): + def poll(self, _cert_name, poll_identifier, _csr): """ poll status of pending CSR and download certificates """ self.logger.debug('CAhandler.poll()') @@ -250,7 +273,7 @@ def revoke(self, _cert, _rev_reason, _rev_date): return(code, message, detail) - def trigger(self, payload): + def trigger(self, _payload): """ process trigger message and return certificate """ self.logger.debug('CAhandler.trigger()') diff --git a/test/test_cmp_ca_handler.py b/test/test_cmp_ca_handler.py index 27a5d9ad..ef472b03 100644 --- a/test/test_cmp_ca_handler.py +++ b/test/test_cmp_ca_handler.py @@ -71,7 +71,7 @@ def test_006_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_006_config_load(self, mock_load_cfg): + def test_007_config_load(self, mock_load_cfg): """ test _config_load - cmp_openssl_bin parameter""" mock_load_cfg.return_value = {'CAhandler': {'cmp_openssl_bin': 'foo'}} self.cahandler._config_load() @@ -80,7 +80,7 @@ def test_006_config_load(self, mock_load_cfg): self.assertEqual('foo', self.cahandler.openssl_bin) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_007_config_load(self, mock_load_cfg): + def test_008_config_load(self, mock_load_cfg): """ test _config_load - cmd_tmp-dir parameter """ mock_load_cfg.return_value = {'CAhandler': {'cmp_tmp_dir': 'foo_tmp'}} self.cahandler._config_load() @@ -89,7 +89,7 @@ def test_007_config_load(self, mock_load_cfg): self.assertEqual('foo_tmp', self.cahandler.tmp_dir) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_008_config_load(self, mock_load_cfg): + def test_009_config_load(self, mock_load_cfg): """ test _config_load - cmp_recipient-dir parameter """ mock_load_cfg.return_value = {'CAhandler': {'cmp_recipient': 'foo'}} self.cahandler._config_load() @@ -97,7 +97,7 @@ def test_008_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_009_config_load(self, mock_load_cfg): + def test_010_config_load(self, mock_load_cfg): """ test _config_load - cmd_tmp-cmp_recipient startwith '/' """ mock_load_cfg.return_value = {'CAhandler': {'cmp_recipient': '/foo'}} self.cahandler._config_load() @@ -105,7 +105,7 @@ def test_009_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_010_config_load(self, mock_load_cfg): + def test_011_config_load(self, mock_load_cfg): """ test _config_load - cmd_tmp-cmp_recipient contains , """ mock_load_cfg.return_value = {'CAhandler': {'cmp_recipient': 'fo,o'}} self.cahandler._config_load() @@ -113,7 +113,7 @@ def test_010_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_011_config_load(self, mock_load_cfg): + def test_012_config_load(self, mock_load_cfg): """ test _config_load - cmd_tmp-cmp_recipient contains ,blank """ mock_load_cfg.return_value = {'CAhandler': {'cmp_recipient': 'fo, o'}} self.cahandler._config_load() @@ -121,7 +121,7 @@ def test_011_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_012_config_load(self, mock_load_cfg): + def test_013_config_load(self, mock_load_cfg): """ test _config_load - cmd_tmp-cmp_recipient contains ,blank and ,""" mock_load_cfg.return_value = {'CAhandler': {'cmp_recipient': 'foo, bar,doo'}} self.cahandler._config_load() @@ -129,7 +129,7 @@ def test_012_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_013_config_load(self, mock_load_cfg): + def test_014_config_load(self, mock_load_cfg): """ test _config_load - cmd_tmp-cmp_recipient contains ,blank and ,""" mock_load_cfg.return_value = {'CAhandler': {'cmp_recipient': 'foo, bar, doo,bar,doo'}} self.cahandler._config_load() @@ -137,7 +137,7 @@ def test_013_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_014_config_load(self, mock_load_cfg): + def test_015_config_load(self, mock_load_cfg): """ test _config_load - any parameter string """ mock_load_cfg.return_value = {'CAhandler': {'cmp_foo': 'bar'}} self.cahandler._config_load() @@ -145,7 +145,7 @@ def test_014_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_015_config_load(self, mock_load_cfg): + def test_016_config_load(self, mock_load_cfg): """ test _config_load - any parameter int """ mock_load_cfg.return_value = {'CAhandler': {'cmp_foo': 1}} self.cahandler._config_load() @@ -153,7 +153,7 @@ def test_015_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_016_config_load(self, mock_load_cfg): + def test_017_config_load(self, mock_load_cfg): """ test _config_load - any parameter float """ mock_load_cfg.return_value = {'CAhandler': {'cmp_foo': 0.1}} self.cahandler._config_load() @@ -161,7 +161,7 @@ def test_016_config_load(self, mock_load_cfg): self.assertEqual(odict, self.cahandler.config_dic) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_017_config_load(self, mock_load_cfg): + def test_018_config_load(self, mock_load_cfg): """ test _config_load - tmp_dir not configured """ mock_load_cfg.return_value = {} with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -169,7 +169,7 @@ def test_017_config_load(self, mock_load_cfg): self.assertIn('ERROR:test_a2c:CAhandler config error: "cmp_tmp_dir" parameter must be specified in config_file', lcm.output) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_018_config_load(self, mock_load_cfg): + def test_019_config_load(self, mock_load_cfg): """ test _config_load - cmp_openssl_bin not configured """ mock_load_cfg.return_value = {} with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -177,81 +177,138 @@ def test_018_config_load(self, mock_load_cfg): self.assertIn('WARNING:test_a2c:CAhandler config error: "cmp_openssl_bin" parameter not in config_file. Using default (/usr/bin/openssl)', lcm.output) @patch('examples.ca_handler.cmp_ca_handler.load_config') - def test_019_config_load(self, mock_load_cfg): + def test_020_config_load(self, mock_load_cfg): """ test _config_load - cmp_recipient not configured """ mock_load_cfg.return_value = {} with self.assertLogs('test_a2c', level='INFO') as lcm: self.cahandler._config_load() self.assertIn('ERROR:test_a2c:CAhandler config error: "cmp_recipient" is missing in config_file.', lcm.output) + @patch.dict('os.environ', {'cmp_ref': 'cmp_ref'}) + @patch('examples.ca_handler.cmp_ca_handler.load_config') + def test_021_config_load(self, mock_load_cfg): + """ test _config_load - load template with ref variable """ + mock_load_cfg.return_value = {'CAhandler': {'cmp_ref_variable': 'cmp_ref'}} + self.cahandler._config_load() + self.assertEqual('cmp_ref', self.cahandler.ref) + + @patch.dict('os.environ', {'cmp_ref': 'user_var'}) + @patch('examples.ca_handler.cmp_ca_handler.load_config') + def test_022_config_load(self, mock_load_cfg): + """ test _config_load - load template with not existing ref variable """ + mock_load_cfg.return_value = {'CAhandler': {'cmp_ref_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.ref) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load cmp_ref:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'cmp_ref': 'cmp_ref'}) + @patch('examples.ca_handler.cmp_ca_handler.load_config') + def test_023_config_load(self, mock_load_cfg): + """ test _config_load - load template overwrite ref variable """ + mock_load_cfg.return_value = {'CAhandler': {'cmp_ref_variable': 'cmp_ref', 'cmp_ref': 'cmp_ref_local'}} + self.cahandler._config_load() + # with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual('cmp_ref_local', self.cahandler.ref) + # self.assertIn("foo", lcm.output) + + @patch.dict('os.environ', {'cmp_secret': 'cmp_secret'}) + @patch('examples.ca_handler.cmp_ca_handler.load_config') + def test_024_config_load(self, mock_load_cfg): + """ test _config_load - load template with secret variable """ + mock_load_cfg.return_value = {'CAhandler': {'cmp_secret_variable': 'cmp_secret'}} + self.cahandler._config_load() + self.assertEqual('cmp_secret', self.cahandler.secret) + + @patch.dict('os.environ', {'cmp_secret': 'cmp_secret'}) + @patch('examples.ca_handler.cmp_ca_handler.load_config') + def test_025_config_load(self, mock_load_cfg): + """ test _config_load - load template with not existing secret variable """ + mock_load_cfg.return_value = {'CAhandler': {'cmp_secret_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.secret) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load cmp_secret_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'cmp_ref': 'cmp_ref'}) + @patch('examples.ca_handler.cmp_ca_handler.load_config') + def test_026_config_load(self, mock_load_cfg): + """ test _config_load - load template overwrite ref variable """ + mock_load_cfg.return_value = {'CAhandler': {'cmp_secret_variable': 'cmp_secret', 'cmp_secret': 'cmp_secret_local'}} + self.cahandler._config_load() + # with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual('cmp_secret_local', self.cahandler.secret) + # self.assertIn("foo", lcm.output) + + @patch('examples.ca_handler.cmp_ca_handler.csr_san_get') - def test_020_csr_san_get(self, mock_san): + def test_027_csr_san_get(self, mock_san): """ test _config_load - empty san list """ mock_san.return_value = [] olist = [] self.assertFalse(self.cahandler._csr_san_get('csr')) @patch('examples.ca_handler.cmp_ca_handler.csr_san_get') - def test_021_csr_san_get(self, mock_san): + def test_028_csr_san_get(self, mock_san): """ test _csr_san_get - incomplete san returned """ mock_san.return_value = ['foo'] olist = [] self.assertFalse(self.cahandler._csr_san_get('csr')) @patch('examples.ca_handler.cmp_ca_handler.csr_san_get') - def test_022_csr_san_get(self, mock_san): + def test_029_csr_san_get(self, mock_san): """ test _csr_san_get - single san returned """ mock_san.return_value = ['foo1:bar1'] olist = [] self.assertEqual('"bar1"', self.cahandler._csr_san_get('csr')) @patch('examples.ca_handler.cmp_ca_handler.csr_san_get') - def test_022_csr_san_get(self, mock_san): + def test_030_csr_san_get(self, mock_san): """ test _csr_san_get - single san returned mix upper and lower cases """ mock_san.return_value = ['fOo1:BaR1'] olist = [] self.assertEqual('"bar1"', self.cahandler._csr_san_get('csr')) @patch('examples.ca_handler.cmp_ca_handler.csr_san_get') - def test_023_csr_san_get(self, mock_san): + def test_031_csr_san_get(self, mock_san): """ test _csr_san_get - single san returned mix upper and lower cases """ mock_san.return_value = ['fOo1:BaR1', 'foo2:bar2'] olist = [] self.assertEqual('"bar1, bar2"', self.cahandler._csr_san_get('csr')) - def test_023_poll(self): + def test_032_poll(self): """ test trigger """ self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) - def test_024_trigger(self): + def test_033_trigger(self): """ test trigger """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) - def test_025_revoke(self): + def test_034_revoke(self): """ test revoke """ self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'Revocation is not supported.'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) @patch('examples.ca_handler.cmp_ca_handler.CAhandler._config_load') - def test_026__enter__(self, mock_load): + def test_035__enter__(self, mock_load): """ test enter """ self.cahandler.__enter__() self.assertTrue(mock_load.called) @patch('examples.ca_handler.cmp_ca_handler.CAhandler._config_load') - def test_027__enter__(self, mock_load): + def test_036__enter__(self, mock_load): """ test enter """ self.cahandler.openssl_bin = 'openssl_bin' self.cahandler.__enter__() self.assertFalse(mock_load.called) @patch("builtins.open", mock_open(read_data='foo'), create=True) - def test_028__pubkey_save(self): + def test_037__pubkey_save(self): """ test pubkey save """ self.assertFalse(self.cahandler._pubkey_save('uts', 'pubkey')) @patch('os.remove') @patch('os.path.isfile') - def test_029_tmp_files_delete(self, mock_exists, mock_remove): + def test_038_tmp_files_delete(self, mock_exists, mock_remove): """ test files_delete if file exists """ mock_exists.return_value = True self.cahandler._tmp_files_delete('uts') @@ -259,7 +316,7 @@ def test_029_tmp_files_delete(self, mock_exists, mock_remove): @patch('os.remove') @patch('os.path.isfile') - def test_030_tmp_files_delete(self, mock_exists, mock_remove): + def test_039_tmp_files_delete(self, mock_exists, mock_remove): """ test files_delete if file exists """ mock_exists.return_value = False self.cahandler._tmp_files_delete('uts') @@ -267,54 +324,54 @@ def test_030_tmp_files_delete(self, mock_exists, mock_remove): @patch("builtins.open", mock_open(read_data='foo'), create=True) @patch('os.path.isfile') - def test_031_certs_bundle(self, mock_exists): + def test_040_certs_bundle(self, mock_exists): """ certs bundle if no file exists """ mock_exists.return_value = False self.assertEqual((None, None), self.cahandler._certs_bundle('foo')) @patch("builtins.open", mock_open(read_data='foo'), create=True) @patch('os.path.isfile') - def test_032_certs_bundle(self, mock_exists): + def test_041_certs_bundle(self, mock_exists): """ certs bundle if only capubs exists """ mock_exists.side_effect = (True, False) self.assertEqual((None, None), self.cahandler._certs_bundle('uts')) @patch("builtins.open", mock_open(read_data='foo'), create=True) @patch('os.path.isfile') - def test_033_certs_bundle(self, mock_exists): + def test_042_certs_bundle(self, mock_exists): """ certs bundle if only cert exists """ mock_exists.side_effect = (False, True) self.assertEqual(('foo', 'foo'), self.cahandler._certs_bundle('uts')) @patch("builtins.open", mock_open(read_data='foo'), create=True) @patch('os.path.isfile') - def test_034_certs_bundle(self, mock_exists): + def test_043_certs_bundle(self, mock_exists): """ certs bundle if all exists """ mock_exists.side_effect = (True, True) self.assertEqual(('foofoo', 'foo'), self.cahandler._certs_bundle('uts')) @patch("builtins.open", mock_open(read_data='-----BEGIN CERTIFICATE-----\nfoo'), create=True) @patch('os.path.isfile') - def test_035_certs_bundle(self, mock_exists): + def test_044_certs_bundle(self, mock_exists): """ certs bundle if cert exists replace begin tag """ mock_exists.side_effect = (False, True) self.assertEqual(('-----BEGIN CERTIFICATE-----\nfoo', 'foo'), self.cahandler._certs_bundle('uts')) @patch("builtins.open", mock_open(read_data='-----BEGIN CERTIFICATE-----\nfoo-----END CERTIFICATE-----\n'), create=True) @patch('os.path.isfile') - def test_036_certs_bundle(self, mock_exists): + def test_045_certs_bundle(self, mock_exists): """ certs bundle if cert exists replace end tag """ mock_exists.side_effect = (False, True) self.assertEqual(('-----BEGIN CERTIFICATE-----\nfoo-----END CERTIFICATE-----\n', 'foo'), self.cahandler._certs_bundle('uts')) @patch("builtins.open", mock_open(read_data='foo\n'), create=True) @patch('os.path.isfile') - def test_037_certs_bundle(self, mock_exists): + def test_046_certs_bundle(self, mock_exists): """ certs bundle if cert exists replace end tag """ mock_exists.side_effect = (False, True) self.assertEqual(('foo\n', 'foo'), self.cahandler._certs_bundle('uts')) - def test_038_opensslcmd_build(self): + def test_047_opensslcmd_build(self): """test _openssl_cmd_build()""" self.cahandler.openssl_bin = 'openssl_bin' self.cahandler.tmp_dir = '/tmp' @@ -324,7 +381,7 @@ def test_038_opensslcmd_build(self): result = ['openssl_bin', 'cmp', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) - def test_039_opensslcmd_build(self): + def test_048_opensslcmd_build(self): """test _openssl_cmd_build() with option including in config dic""" self.cahandler.openssl_bin = 'openssl_bin' self.cahandler.tmp_dir = '/tmp' @@ -335,7 +392,7 @@ def test_039_opensslcmd_build(self): result = ['openssl_bin', 'cmp', '-foo1', 'bar1', '-foo2', 'bar2', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) - def test_040_opensslcmd_build(self): + def test_049_opensslcmd_build(self): """test _openssl_cmd_build()""" self.cahandler.openssl_bin = 'openssl_bin' self.cahandler.tmp_dir = '/tmp' @@ -346,7 +403,7 @@ def test_040_opensslcmd_build(self): result = ['openssl_bin', 'cmp', '--msgtimeout', '10', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) - def test_041_opensslcmd_build(self): + def test_050_opensslcmd_build(self): """test _openssl_cmd_build()""" self.cahandler.openssl_bin = 'openssl_bin' self.cahandler.tmp_dir = '/tmp' @@ -357,14 +414,14 @@ def test_041_opensslcmd_build(self): result = ['openssl_bin', 'cmp', '--totaltimeout', '10', '-subject', 'subject', '-newkey', '/tmp/1234_pubkey.pem', '-sans', 'foo1.bar.local', '-extracertsout', '/tmp/1234_capubs.pem', '-certout', '/tmp/1234_cert.pem', '-msgtimeout', '5', '-totaltimeout', '10'] self.assertEqual(result, self.cahandler._opensslcmd_build(uts, subject, san_list)) - def test_042_enroll(self): + def test_051_enroll(self): """ test enroll without openssl_bin """ self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') - def test_043_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): + def test_052_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): """ test enroll csr_dn_get returns_exception """ self.cahandler.openssl_bin = 'openssl_bin' mock_dn_get.side_effect = Exception('ex_dn_get') @@ -383,7 +440,7 @@ def test_043_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') - def test_043_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + def test_053_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): """ test enroll csr_dn_get returns None and gets corrected """ self.cahandler.openssl_bin = 'openssl_bin' mock_dn_get.return_value = None @@ -408,7 +465,7 @@ def test_043_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, m @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') - def test_045_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): + def test_054_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): """ test enroll csr_pubkey_get returns_exception """ self.cahandler.openssl_bin = 'openssl_bin' mock_dn_get.return_value = 'dn' @@ -421,7 +478,7 @@ def test_045_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') - def test_046_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): + def test_055_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): """ test enroll _csr_san_get returns_exception """ self.cahandler.openssl_bin = 'openssl_bin' mock_dn_get.return_value = 'dn' @@ -440,7 +497,7 @@ def test_046_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get): @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') - def test_047_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + def test_056_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): """ test enroll csr_dn_get runs through without issues """ self.cahandler.openssl_bin = 'openssl_bin' mock_dn_get.return_value = 'dn' @@ -471,7 +528,7 @@ def test_047_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, m @patch('examples.ca_handler.cmp_ca_handler.CAhandler._csr_san_get') @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') - def test_048_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + def test_057_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): """ test enroll subprocess.call returns other than 0 """ self.cahandler.openssl_bin = 'openssl_bin' mock_dn_get.return_value = 'dn' @@ -502,7 +559,7 @@ def test_048_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, m @patch('examples.ca_handler.cmp_ca_handler.csr_pubkey_get') @patch('examples.ca_handler.cmp_ca_handler.csr_dn_get') - def test_049_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): + def test_058_enroll(self, mock_dn_get, mock_pkey_get, mock_san_get, mock_save, mock_build, mock_call, mock_exists, mock_del, mock_bundle): """ test enroll subprocess.call files do not exist """ self.cahandler.openssl_bin = 'openssl_bin' mock_dn_get.return_value = 'dn' From 66a1d1c740ddbec58e598a479c2803079dab95d6 Mon Sep 17 00:00:00 2001 From: grindsa Date: Mon, 31 May 2021 19:44:34 +0200 Subject: [PATCH 27/51] [tst] unittests mscertsrv_handler --- examples/ca_handler/mscertsrv_ca_handler.py | 39 ++-- test/test_msca_handler.py | 229 ++++++++++++++++++++ 2 files changed, 249 insertions(+), 19 deletions(-) create mode 100644 test/test_msca_handler.py diff --git a/examples/ca_handler/mscertsrv_ca_handler.py b/examples/ca_handler/mscertsrv_ca_handler.py index 3ef24007..d4e9d108 100644 --- a/examples/ca_handler/mscertsrv_ca_handler.py +++ b/examples/ca_handler/mscertsrv_ca_handler.py @@ -56,7 +56,7 @@ def __init__(self, _debug=None, logger=None): def __enter__(self): """ Makes CAhandler a Context Manager """ if not self.host: - self.load_config() + self._config_load() return self def __exit__(self, *args): @@ -151,24 +151,25 @@ def enroll(self, csr): self.logger.debug('Certificate.enroll() ended') return(error, cert_bundle, cert_raw, None) - def load_config(self): + def _config_load(self): """" load config from file """ - self.logger.debug('CAhandler.load_config()') + self.logger.debug('CAhandler._config_load()') config_dic = load_config(self.logger, 'CAhandler') - if 'host' in config_dic['CAhandler']: - self.host = config_dic['CAhandler']['host'] - if 'user' in config_dic['CAhandler']: - self.user = config_dic['CAhandler']['user'] - if 'password' in config_dic['CAhandler']: - self.password = config_dic['CAhandler']['password'] - if 'template' in config_dic['CAhandler']: - self.template = config_dic['CAhandler']['template'] - if 'auth_method' in config_dic['CAhandler']: - self.auth_method = config_dic['CAhandler']['auth_method'] - # check if we get a ca bundle for verification - if 'ca_bundle' in config_dic['CAhandler']: - self.ca_bundle = config_dic['CAhandler']['ca_bundle'] - self.logger.debug('CAhandler.load_config() ended') + if 'CAhandler' in config_dic: + if 'host' in config_dic['CAhandler']: + self.host = config_dic['CAhandler']['host'] + if 'user' in config_dic['CAhandler']: + self.user = config_dic['CAhandler']['user'] + if 'password' in config_dic['CAhandler']: + self.password = config_dic['CAhandler']['password'] + if 'template' in config_dic['CAhandler']: + self.template = config_dic['CAhandler']['template'] + if 'auth_method' in config_dic['CAhandler'] and config_dic['CAhandler']['auth_method'] == 'ntlm': + self.auth_method = config_dic['CAhandler']['auth_method'] + # check if we get a ca bundle for verification + if 'ca_bundle' in config_dic['CAhandler']: + self.ca_bundle = config_dic['CAhandler']['ca_bundle'] + self.logger.debug('CAhandler._config_load() ended') def poll(self, _cert_name, poll_identifier, _csr): """ poll status of pending CSR and download certificates """ @@ -197,8 +198,8 @@ def trigger(self, _payload): """ process trigger message and return certificate """ self.logger.debug('CAhandler.trigger()') - error = None - cert_bundle = 'Method not implemented.' + error = 'Method not implemented.' + cert_bundle = None cert_raw = None self.logger.debug('CAhandler.trigger() ended with error: {0}'.format(error)) diff --git a/test/test_msca_handler.py b/test/test_msca_handler.py new file mode 100644 index 00000000..bee9efa7 --- /dev/null +++ b/test/test_msca_handler.py @@ -0,0 +1,229 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +""" unittests for acme2certifier """ +# pylint: disable= C0415, W0212 +import unittest +import sys +import os +from OpenSSL import crypto +from unittest.mock import patch, Mock +import requests + +sys.path.insert(0, '.') +sys.path.insert(1, '..') + +class TestACMEHandler(unittest.TestCase): + """ test class for cgi_handler """ + + def setUp(self): + """ setup unittest """ + import logging + logging.basicConfig(level=logging.CRITICAL) + self.logger = logging.getLogger('test_a2c') + from examples.ca_handler.mscertsrv_ca_handler import CAhandler, _get_certificates + self.cahandler = CAhandler(False, self.logger) + self._get_certificates = _get_certificates + self.dir_path = os.path.dirname(os.path.realpath(__file__)) + + def test_001_default(self): + """ default test which always passes """ + self.assertEqual('foo', 'foo') + + def test_002_get_certificates(self): + """ test pkcs7 convrt to pem """ + cert_pem_list = [] + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_PEM, fso.read()) + cert_list = self._get_certificates(pkcs7) + + for cert in cert_list: + cert_pem_list.append(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) + result = [b'-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', b'-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] + self.assertEqual(result, cert_pem_list) + + def test_003__pkcs7_to_pem(self): + """ test pkcs7 to pem default output """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + with open(self.dir_path + '/ca/certs.pem', 'r') as fso: + result = fso.read() + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content)) + + def test_004__pkcs7_to_pem(self): + """ test pkcs7 to pem output string """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + with open(self.dir_path + '/ca/certs.pem', 'r') as fso: + result = fso.read() + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'string')) + + def test_005__pkcs7_to_pem(self): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + result = ['-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', '-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'list')) + + def test_006__pkcs7_to_pem(self): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + result = None + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) + + @patch('OpenSSL.crypto.load_pkcs7_data') + def test_007__pkcs7_to_pem(self, mock_load): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + # mock_load.side_effects = Exception('exc_load_pkcs7') + mock_load.return_value = None + result = None + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) + + @patch('OpenSSL.crypto') + def test_008__pkcs7_to_pem(self, mock_load): + """ test pkcs7 to pem output list """ + with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: + file_content = fso.read() + response = Mock() + response.load_pkcs7_data = Exception('exc_load_pkcs7') + mock_load.return_value = response + result = None + self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_009_config_load(self, mock_load_cfg): + """ test _config_load no cahandler section """ + mock_load_cfg.return_value = {} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_010_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with unknown values """ + mock_load_cfg.return_value = {'CAhandler': {'foo': 'bar'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_011_config_load(self, mock_load_cfg): + """ test _config_load no cahandler section with host value """ + mock_load_cfg.return_value = {'CAhandler': {'host': 'host'}} + self.cahandler._config_load() + self.assertEqual('host', self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_012_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with user values """ + mock_load_cfg.return_value = {'CAhandler': {'user': 'user'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertEqual('user', self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_013_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with password values """ + mock_load_cfg.return_value = {'CAhandler': {'password': 'password'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertEqual('password', self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_014_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with authmethod basic """ + mock_load_cfg.return_value = {'CAhandler': {'auth_method': 'basic'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_015_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with authmethod ntlm """ + mock_load_cfg.return_value = {'CAhandler': {'auth_method': 'ntlm'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('ntlm', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_016_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with authmethod unknown """ + mock_load_cfg.return_value = {'CAhandler': {'auth_method': 'unknown'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_017_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with ca_bundle value """ + mock_load_cfg.return_value = {'CAhandler': {'ca_bundle': 'ca_bundle'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertEqual('ca_bundle', self.cahandler.ca_bundle) + self.assertFalse(self.cahandler.template) + + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_018_config_load(self, mock_load_cfg): + """ test _config_load cahandler section with template value """ + mock_load_cfg.return_value = {'CAhandler': {'template': 'template'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertFalse(self.cahandler.user) + self.assertFalse(self.cahandler.password) + self.assertEqual('basic', self.cahandler.auth_method) + self.assertFalse(self.cahandler.ca_bundle) + self.assertEqual('template', self.cahandler.template) + + def test_019_revoke(self): + """ test revocation """ + self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'Revocation is not supported.'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) + + def test_020_poll(self): + """ test polling """ + self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) + + def test_021_trigger(self): + """ test polling """ + self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) + +if __name__ == '__main__': + + unittest.main() From e2fa93d81e5893eaa814d87144ca2ed568800a5c Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 1 Jun 2021 06:35:15 +0200 Subject: [PATCH 28/51] [tst] unittests --- test/test_msca_handler.py | 125 +++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/test/test_msca_handler.py b/test/test_msca_handler.py index bee9efa7..9923dec1 100644 --- a/test/test_msca_handler.py +++ b/test/test_msca_handler.py @@ -6,12 +6,13 @@ import sys import os from OpenSSL import crypto -from unittest.mock import patch, Mock +from unittest.mock import patch, Mock, MagicMock import requests sys.path.insert(0, '.') sys.path.insert(1, '..') + class TestACMEHandler(unittest.TestCase): """ test class for cgi_handler """ @@ -224,6 +225,128 @@ def test_021_trigger(self): """ test polling """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) + def test_022_check_credentials(self): + """ test polling """ + ca_server = Mock() + ca_server.check_credentials = Mock(return_value=True) + self.assertTrue(self.cahandler._check_credentials(ca_server)) + + def test_023_check_credentials(self): + """ test polling """ + ca_server = Mock() + ca_server.check_credentials = Mock(return_value=False) + self.assertFalse(self.cahandler._check_credentials(ca_server)) + + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._config_load') + def test_024__enter__(self, mock_cfg): + """ test enter called """ + mock_cfg.return_value = True + self.cahandler.__enter__() + self.assertTrue(mock_cfg.called) + + def test_025_enroll(self): + """ enroll without having self.host """ + self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) + + def test_026_enroll(self): + """ enroll without having self.user """ + self.cahandler.host = 'host' + self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) + + def test_027_enroll(self): + """ enroll without having self.password """ + self.cahandler.host = 'host' + self.cahandler.user = 'user' + self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) + + def test_028_enroll(self): + """ enroll without having self.template """ + self.cahandler.host = 'host' + self.cahandler.user = 'user' + self.cahandler.password = 'password' + self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') + @patch('certsrv.Certsrv') + def test_029_enroll(self, mock_certserver, mock_credchk): + """ enroll credential check failed """ + self.cahandler.host = 'host' + self.cahandler.user = 'user' + self.cahandler.password = 'password' + self.cahandler.template = 'template' + mock_certserver.return_value = 'foo' + mock_credchk.return_value = False + self.assertEqual(('Connection or Credentialcheck failed.', None, None, None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._pkcs7_to_pem') + @patch('examples.ca_handler.mscertsrv_ca_handler.convert_byte_to_string') + @patch('textwrap.fill') + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') + @patch('examples.ca_handler.mscertsrv_ca_handler.Certsrv') + def test_030_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): + """ enroll enroll successful """ + self.cahandler.host = 'host' + self.cahandler.user = 'user' + self.cahandler.password = 'password' + self.cahandler.template = 'template' + mockresponse = MagicMock() + mockresponse.get_chain.return_value = "get_chain" + mockresponse.get_cert.return_value = "get_cert" + mock_certserver = mockresponse + mock_credchk.return_value = True + mockwrap.return_value = 'mockwrap' + mock_b2s.side_effect = ['get_chain', 'get_cert'] + mock_p2p.return_value = 'p2p' + self.assertEqual((None, 'get_certp2p', 'get_cert', None), self.cahandler.enroll('csr')) + + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._pkcs7_to_pem') + @patch('examples.ca_handler.mscertsrv_ca_handler.convert_byte_to_string') + @patch('textwrap.fill') + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') + @patch('examples.ca_handler.mscertsrv_ca_handler.Certsrv') + def test_031_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): + """ enroll exceütption in get chain """ + self.cahandler.host = 'host' + self.cahandler.user = 'user' + self.cahandler.password = 'password' + self.cahandler.template = 'template' + mockresponse = MagicMock() + mockresponse.get_chain.return_value = 'get_chain' + mockresponse.get_cert.return_value = "get_cert" + mock_certserver = mockresponse + mock_credchk.return_value = True + mockwrap.return_value = 'mockwrap' + mock_b2s.side_effect = [Exception('exc_get_chain'), 'get_cert'] + mock_p2p.return_value = 'p2p' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('cert bundling failed', None, 'get_cert', None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:ca_server.get_chain() failed with error: exc_get_chain', lcm.output) + self.assertIn('ERROR:test_a2c:cert bundling failed', lcm.output) + + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._pkcs7_to_pem') + @patch('examples.ca_handler.mscertsrv_ca_handler.convert_byte_to_string') + @patch('textwrap.fill') + @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') + @patch('examples.ca_handler.mscertsrv_ca_handler.Certsrv') + def test_032_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): + """ enroll exceütption in get cert """ + self.cahandler.host = 'host' + self.cahandler.user = 'user' + self.cahandler.password = 'password' + self.cahandler.template = 'template' + mockresponse = MagicMock() + mockresponse.get_chain.return_value = 'get_chain' + mockresponse.get_cert.return_value = "get_cert" + mock_certserver = mockresponse + mock_credchk.return_value = True + mockwrap.return_value = 'mockwrap' + mock_b2s.side_effect = ['exc_get_chain', Exception('get_cert')] + mock_p2p.return_value = 'p2p' + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual(('cert bundling failed', None, None, None), self.cahandler.enroll('csr')) + self.assertIn('ERROR:test_a2c:ca_server.get_cert() failed with error: get_cert', lcm.output) + self.assertIn('ERROR:test_a2c:cert bundling failed', lcm.output) + if __name__ == '__main__': unittest.main() From fbfc0ae36db4f5449d7b25216f4272ec9665021a Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 1 Jun 2021 08:33:56 +0200 Subject: [PATCH 29/51] [wf] mscertsrv_ca_handler.py --- .github/workflows/ca_handler_tests.yml | 24 ++++++++++++++++++- test/ca/certsrv_ca_certs.pem | 32 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 test/ca/certsrv_ca_certs.pem diff --git a/.github/workflows/ca_handler_tests.yml b/.github/workflows/ca_handler_tests.yml index c33e0b79..87b75975 100644 --- a/.github/workflows/ca_handler_tests.yml +++ b/.github/workflows/ca_handler_tests.yml @@ -68,6 +68,28 @@ jobs: docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force # openssl verify -CAfile acme.sh/acme-sh.acme/ca.cer acme-sh/acme-sh.acme/acme-sh.acme.cer + - name: "[ PREPARE ] setup msca ca_handler" + run: | + sudo cp examples/ca_handler/mscertsrv_ca_handler.py examples/Docker/data/ca_handler.py + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem + sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "host: ${{ secrets.MSCA_NAME }}" >> examples/Docker/data/acme_srv.cfg + sudo echo "user: ${{ secrets.NCLM_API_USER }}" >> examples/Docker/data/acme_srv.cfg + sudo echo "password: ${{ secrets.NCLM_API_PASSWORD }}" >> examples/Docker/data/acme_srv.cfg + sudo echo "auth_method: ${{ secrets.MSCA_AUTHMETHOD }}" >> examples/Docker/data/acme_srv.cfg + sudo echo "template: ${{ secrets.MSCA_TEMPLATE }}" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: volume/ca_certs.pem" >> examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + docker-compose logs + + - name: "[ ENROLL ] via msca ca_handler" + run: | + docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force + # openssl verify -CAfile acme.sh/acme-sh.acme/ca.cer acme-sh/acme-sh.acme/acme-sh.acme.cer + - name: "[ PREPARE ] setup nclm ca_handler" run: | sudo cp examples/ca_handler/nclm_ca_handler.py examples/Docker/data/ca_handler.py @@ -172,5 +194,5 @@ jobs: uses: actions/upload-artifact@v2 if: ${{ failure() }} with: - name: acme.sh_acc-${{ matrix.accountkeylength }}_key-${{ matrix.keylength }}.tar.gz + name: acme.sh.tar.gz path: ${{ github.workspace }}/artifact/upload/ diff --git a/test/ca/certsrv_ca_certs.pem b/test/ca/certsrv_ca_certs.pem new file mode 100644 index 00000000..c733b5fc --- /dev/null +++ b/test/ca/certsrv_ca_certs.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFizCCA3OgAwIBAgIQTMegIi+5oJVMhnXtdJZylzANBgkqhkiG9w0BAQsFADBY +MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFDASBgoJkiaJk/IsZAEZFgRuY2xtMRgw +FgYKCZImiZPyLGQBGRYIbm90YWRlbW8xDzANBgNVBAMTBlJvb3RDQTAeFw0yMDA5 +MDEwNjQ1MDJaFw00MDA5MDEwNjU1MDFaMFgxFTATBgoJkiaJk/IsZAEZFgVsb2Nh +bDEUMBIGCgmSJomT8ixkARkWBG5jbG0xGDAWBgoJkiaJk/IsZAEZFghub3RhZGVt +bzEPMA0GA1UEAxMGUm9vdENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEAxMIVkgSvPB6ggSpVrcmk/9XNnAUdSU8Eleqg7MCBWqReLHl4NL7CbdwFJr49 +YHmhuoanuhnOFNVDMzJa8qry8Nb52Istnw6bbkTqNkMOoU2ocDZBb8n4cpOoYhaB +52u8cmIUR1vM3OBnELS+/FKbU6c/EN/T77WKdcDYs0VJSS0moGZcMFGuB0EJDiM/ +uxjhE8I7+sdRK174tW6Lm72MAMwfFQbOqa1ufHAFjzPB/V966Kdzx8EFW2O8RXbM +oL2uPaz/4323iEYNc93XY38gg+NykvicvAj9+xdE5hO3Kue7AAAf782yghqWpW1+ +6LJtv7iwFZYOFPn6VWynU4RDBEF7Jz7lIV+uyexs1KTDACgNFUVCEzvQtl2ubw9t +P9WJrFwb8IZxx40ObrP6OzuY0T6T8Bc4Yq5pF23446ftQutz0ekBpHKAtWOmgpeR +w6C2svb7531/IADqjYx9JlvGhzEI7ytIel9HQajYR6/HeP4mE6qgeU0OAKn4pDhy +Nj/Q2SRCFnsXnn8d6rz1cwnyxXoZeziUL8u81xogiAUxx8KuJwMdtDlkRL7fAe8x +sYEeVi18FOjQuMLy8hE9XEGybvRZyCwkHtKdReMM1LMwwUSkiOwOZuFNe3o/9BAf +Ya65OQCiyPmTpRrg4PBS/rWjrFJpM4nn/nhWSwy7QUgC84ECAwEAAaNRME8wCwYD +VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFK2mJQL1KxBrlbWh +vwF8Qk18z7VnMBAGCSsGAQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBCwUAA4ICAQCz +M9zPg69pXE0TZRL8rMcct77cnQUkBR8TLM3S8p5CshYEmthgS1REbeFzTbO+QHcm +gicRk29QkOG+Huu9LaHtAzgikpGiPe8sRjlFvXliefBjFtbeUxUdPm7WwyNC4KYP +r9eg8svEKEiPtegwonyw5r/+CvExpdQVnxP9U9I7+TKASgS+6mSsCoTzwLCnIrNp +ZBThb8pIXmJNx8KWNzRE08SJY91VonqAVRGMqDta9u8FdA1rv+m7yuG2FitCMMRn +SYsVoqFyKsUW+WEiSOG78MbIIFtzpZ0Te1SVbvc+Th1PdXSXCHr+/exW2BUFBjgz +l7Jesy9iBYWg8PUucpPZHJG2qhB6B4KHn2b4PikGWHR7h60BR9M+zLalzGbHPWc0 +p5FnWcRE9/FCVbuIfNoocaA4t8MvYcYyXOuqR0NeFHbai4WTbKZzwyfGX34oA36U +Hd8FPH7Rom8vdK06pJvjyEriKBaE9Yzh17j5A+q0KOteDk0TOHpZjsqnpf8yo9f6 +X/I0KQ03VKj0W2GkC5Kft4nZYIcoHfYJAMRLOkzcid1ko6Kn1kfZ4fPaNiL9PsGN +N9kNxQHy8R9wEvB0Kl393mymH+A/d+QuU8CrzG8hxc0mPwiPnjesGsv/jQ6KheIM +KBJgf/D2RRMDq1/EeIEBDS1b1beTqeDcirbjAbqkMw== +-----END CERTIFICATE----- From d4561238da06a73b571e287f588e4fe41bd1c766 Mon Sep 17 00:00:00 2001 From: grindsa Date: Wed, 2 Jun 2021 12:24:25 +0200 Subject: [PATCH 30/51] [feat] support of environment variables in mscertserv_handler --- docs/mscertsrv.md | 3 + examples/ca_handler/mscertsrv_ca_handler.py | 23 ++++ test/test_msca_handler.py | 112 +++++++++++++++++--- 3 files changed, 124 insertions(+), 14 deletions(-) diff --git a/docs/mscertsrv.md b/docs/mscertsrv.md index 6de2fbff..00e2bf38 100644 --- a/docs/mscertsrv.md +++ b/docs/mscertsrv.md @@ -69,8 +69,11 @@ template: ``` - host - hostname of the system providing the Web enrollment service +- host_variable - *optional* - name of the environment variable containing host address (a configured `host` parameter in acme_srv.cfg takes precedence) - user - username used to access the service +- user_variable - *optional* - name of the environment variable containing the username used for service access (a configured `user` parameter in acme_srv.cfg takes precedence) - password - password +- password_variable - *optional* - name of the environment variable containing the password used for service access (a configured `password` parameter in acme_srv.cfg takes precedence) - ca_bundle - CA certificate bundle in pem format needed to valiate the server certificate - auth_method - authentication method (either "basic" or "ntlm") - template - certificate template used for enrollment diff --git a/examples/ca_handler/mscertsrv_ca_handler.py b/examples/ca_handler/mscertsrv_ca_handler.py index d4e9d108..dfdee745 100644 --- a/examples/ca_handler/mscertsrv_ca_handler.py +++ b/examples/ca_handler/mscertsrv_ca_handler.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- """ ca handler for Microsoft Webenrollment service (certsrv) """ from __future__ import print_function +import os import textwrap from OpenSSL import crypto from OpenSSL.crypto import _lib, _ffi, X509 @@ -156,11 +157,33 @@ def _config_load(self): self.logger.debug('CAhandler._config_load()') config_dic = load_config(self.logger, 'CAhandler') if 'CAhandler' in config_dic: + + if 'host_variable' in config_dic['CAhandler']: + try: + self.host = os.environ[config_dic['CAhandler']['host_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load host_variable:{0}'.format(err)) if 'host' in config_dic['CAhandler']: + if self.host: + self.logger.info('CAhandler._config_load() overwrite host') self.host = config_dic['CAhandler']['host'] + if 'user_variable' in config_dic['CAhandler']: + try: + self.user = os.environ[config_dic['CAhandler']['user_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load user_variable:{0}'.format(err)) if 'user' in config_dic['CAhandler']: + if self.user: + self.logger.info('CAhandler._config_load() overwrite user') self.user = config_dic['CAhandler']['user'] + if 'password_variable' in config_dic['CAhandler']: + try: + self.password = os.environ[config_dic['CAhandler']['password_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load password_variable:{0}'.format(err)) if 'password' in config_dic['CAhandler']: + if self.password: + self.logger.info('CAhandler._config_load() overwrite password') self.password = config_dic['CAhandler']['password'] if 'template' in config_dic['CAhandler']: self.template = config_dic['CAhandler']['template'] diff --git a/test/test_msca_handler.py b/test/test_msca_handler.py index 9923dec1..4581f037 100644 --- a/test/test_msca_handler.py +++ b/test/test_msca_handler.py @@ -213,53 +213,137 @@ def test_018_config_load(self, mock_load_cfg): self.assertFalse(self.cahandler.ca_bundle) self.assertEqual('template', self.cahandler.template) - def test_019_revoke(self): + @patch.dict('os.environ', {'host_variable': 'host'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_019_config_load(self, mock_load_cfg): + """ test _config_load - load with host variable """ + mock_load_cfg.return_value = {'CAhandler': {'host_variable': 'host_variable'}} + self.cahandler._config_load() + self.assertEqual('host', self.cahandler.host) + + @patch.dict('os.environ', {'host_variable': 'host'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_020_config_load(self, mock_load_cfg): + """ test _config_load - load with host variable which does not exist """ + mock_load_cfg.return_value = {'CAhandler': {'host_variable': 'doesnotexist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.host) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load host_variable:'doesnotexist'", lcm.output) + + @patch.dict('os.environ', {'host_variable': 'host'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_021_config_load(self, mock_load_cfg): + """ test _config_load - load with host variable which gets overwritten """ + mock_load_cfg.return_value = {'CAhandler': {'host_variable': 'host_variable', 'host': 'host_local'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('host_local', self.cahandler.host) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite host', lcm.output) + + @patch.dict('os.environ', {'user_variable': 'user'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_022_config_load(self, mock_load_cfg): + """ test _config_load - load with user variable """ + mock_load_cfg.return_value = {'CAhandler': {'user_variable': 'user_variable'}} + self.cahandler._config_load() + self.assertEqual('user', self.cahandler.user) + + @patch.dict('os.environ', {'user_variable': 'user'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_023_config_load(self, mock_load_cfg): + """ test _config_load - load with user variable which does not exist """ + mock_load_cfg.return_value = {'CAhandler': {'host_variable': 'doesnotexist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.user) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load host_variable:'doesnotexist'", lcm.output) + + @patch.dict('os.environ', {'user_variable': 'user'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_024_config_load(self, mock_load_cfg): + """ test _config_load - load with user variable which gets overwritten """ + mock_load_cfg.return_value = {'CAhandler': {'user_variable': 'user_variable', 'user': 'user_local'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('user_local', self.cahandler.user) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite user', lcm.output) + + @patch.dict('os.environ', {'password_variable': 'password'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_025_config_load(self, mock_load_cfg): + """ test _config_load - load with password variable """ + mock_load_cfg.return_value = {'CAhandler': {'password_variable': 'password_variable'}} + self.cahandler._config_load() + self.assertEqual('password', self.cahandler.password) + + @patch.dict('os.environ', {'password_variable': 'password'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_026_config_load(self, mock_load_cfg): + """ test _config_load - load with password variable which does not exist """ + mock_load_cfg.return_value = {'CAhandler': {'password_variable': 'doesnotexist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.password) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load password_variable:'doesnotexist'", lcm.output) + + @patch.dict('os.environ', {'password_variable': 'password'}) + @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') + def test_027_config_load(self, mock_load_cfg): + """ test _config_load - load with password variable which gets overwritten """ + mock_load_cfg.return_value = {'CAhandler': {'password_variable': 'password_variable', 'password': 'password_local'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('password_local', self.cahandler.password) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite password', lcm.output) + + def test_028_revoke(self): """ test revocation """ self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'Revocation is not supported.'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) - def test_020_poll(self): + def test_029_poll(self): """ test polling """ self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) - def test_021_trigger(self): + def test_030_trigger(self): """ test polling """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) - def test_022_check_credentials(self): + def test_031_check_credentials(self): """ test polling """ ca_server = Mock() ca_server.check_credentials = Mock(return_value=True) self.assertTrue(self.cahandler._check_credentials(ca_server)) - def test_023_check_credentials(self): + def test_032_check_credentials(self): """ test polling """ ca_server = Mock() ca_server.check_credentials = Mock(return_value=False) self.assertFalse(self.cahandler._check_credentials(ca_server)) @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._config_load') - def test_024__enter__(self, mock_cfg): + def test_033__enter__(self, mock_cfg): """ test enter called """ mock_cfg.return_value = True self.cahandler.__enter__() self.assertTrue(mock_cfg.called) - def test_025_enroll(self): + def test_034_enroll(self): """ enroll without having self.host """ self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) - def test_026_enroll(self): + def test_035_enroll(self): """ enroll without having self.user """ self.cahandler.host = 'host' self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) - def test_027_enroll(self): + def test_036_enroll(self): """ enroll without having self.password """ self.cahandler.host = 'host' self.cahandler.user = 'user' self.assertEqual(('Config incomplete', None, None, None), self.cahandler.enroll('csr')) - def test_028_enroll(self): + def test_037_enroll(self): """ enroll without having self.template """ self.cahandler.host = 'host' self.cahandler.user = 'user' @@ -268,7 +352,7 @@ def test_028_enroll(self): @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') @patch('certsrv.Certsrv') - def test_029_enroll(self, mock_certserver, mock_credchk): + def test_038_enroll(self, mock_certserver, mock_credchk): """ enroll credential check failed """ self.cahandler.host = 'host' self.cahandler.user = 'user' @@ -283,7 +367,7 @@ def test_029_enroll(self, mock_certserver, mock_credchk): @patch('textwrap.fill') @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') @patch('examples.ca_handler.mscertsrv_ca_handler.Certsrv') - def test_030_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): + def test_039_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): """ enroll enroll successful """ self.cahandler.host = 'host' self.cahandler.user = 'user' @@ -304,7 +388,7 @@ def test_030_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, moc @patch('textwrap.fill') @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') @patch('examples.ca_handler.mscertsrv_ca_handler.Certsrv') - def test_031_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): + def test_040_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): """ enroll exceütption in get chain """ self.cahandler.host = 'host' self.cahandler.user = 'user' @@ -328,7 +412,7 @@ def test_031_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, moc @patch('textwrap.fill') @patch('examples.ca_handler.mscertsrv_ca_handler.CAhandler._check_credentials') @patch('examples.ca_handler.mscertsrv_ca_handler.Certsrv') - def test_032_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): + def test_041_enroll(self, mock_certserver, mock_credchk, mockwrap, mock_b2s, mock_p2p): """ enroll exceütption in get cert """ self.cahandler.host = 'host' self.cahandler.user = 'user' From 7e040684d944ea3d403f30e7e38972b96f860400 Mon Sep 17 00:00:00 2001 From: grindsa Date: Wed, 2 Jun 2021 15:22:00 +0200 Subject: [PATCH 31/51] [tst] unittests for EAB-Handler --- .github/.codecov.yml | 3 + examples/eab_handler/file_handler.py | 24 +++-- examples/eab_handler/json_handler.py | 17 ++-- test/test_eabfile_handler.py | 145 +++++++++++++++++++++++++++ test/test_eabjson_handler.py | 113 +++++++++++++++++++++ 5 files changed, 287 insertions(+), 15 deletions(-) create mode 100644 test/test_eabfile_handler.py create mode 100644 test/test_eabjson_handler.py diff --git a/.github/.codecov.yml b/.github/.codecov.yml index 7d547d4e..40de1f90 100644 --- a/.github/.codecov.yml +++ b/.github/.codecov.yml @@ -1,3 +1,6 @@ ignore: - "examples/ca_handler/skeleton_ca_handler.py" + - "examples/eab_handler/skeleton_eab_handler.py" + - "docs/__init__.py" + - "setup.py" - "test" # wildcards accepted diff --git a/examples/eab_handler/file_handler.py b/examples/eab_handler/file_handler.py index 4dde85e9..c3d6f478 100644 --- a/examples/eab_handler/file_handler.py +++ b/examples/eab_handler/file_handler.py @@ -27,8 +27,9 @@ def _config_load(self): self.logger.debug('EABhandler._config_load()') config_dic = load_config(self.logger, 'EABhandler') - if 'key_file' in config_dic['EABhandler']: - self.key_file = config_dic['EABhandler']['key_file'] + if 'EABhandler' in config_dic: + if 'key_file' in config_dic['EABhandler']: + self.key_file = config_dic['EABhandler']['key_file'] self.logger.debug('EABhandler._config_load() ended') @@ -37,11 +38,16 @@ def mac_key_get(self, kid=None): self.logger.debug('EABhandler.mac_key_get({})'.format(kid)) mac_key = None - with open(self.key_file, mode='r') as csv_file: - csv_reader = csv.DictReader(csv_file) - for row in csv_reader: - if 'eab_kid' in row and 'eab_mac' in row and row['eab_kid'] == kid: - mac_key = row['eab_mac'] - break - self.logger.debug('EABhandler.mac_key_get() ended with: {0}'.format(bool(mac_key))) + if self.key_file and kid: + try: + with open(self.key_file, mode='r') as csv_file: + csv_reader = csv.DictReader(csv_file) + for row in csv_reader: + if 'eab_kid' in row and 'eab_mac' in row and row['eab_kid'] == kid: + mac_key = row['eab_mac'] + break + except BaseException as err: + self.logger.error('EABhandler.mac_key_get() error: {0}'.format(err)) + + self.logger.debug('EABhandler.mac_key_get() ended with: {0}'.format(bool(mac_key))) return mac_key diff --git a/examples/eab_handler/json_handler.py b/examples/eab_handler/json_handler.py index 77f2e614..219ee421 100644 --- a/examples/eab_handler/json_handler.py +++ b/examples/eab_handler/json_handler.py @@ -27,8 +27,9 @@ def _config_load(self): self.logger.debug('EABhandler._config_load()') config_dic = load_config(self.logger, 'EABhandler') - if 'key_file' in config_dic['EABhandler']: - self.key_file = config_dic['EABhandler']['key_file'] + if 'EABhandler' in config_dic: + if 'key_file' in config_dic['EABhandler']: + self.key_file = config_dic['EABhandler']['key_file'] self.logger.debug('EABhandler._config_load() ended') @@ -37,10 +38,14 @@ def mac_key_get(self, kid=None): self.logger.debug('EABhandler.mac_key_get({})'.format(kid)) mac_key = None - with open(self.key_file, encoding='utf8') as json_file: - data_dic = json.load(json_file) - if kid in data_dic: - mac_key = data_dic[kid] + try: + if self.key_file and kid: + with open(self.key_file, encoding='utf8') as json_file: + data_dic = json.load(json_file) + if kid in data_dic: + mac_key = data_dic[kid] + except BaseException as err: + self.logger.error('EABhandler.mac_key_get() error: {0}'.format(err)) self.logger.debug('EABhandler.mac_key_get() ended with: {0}'.format(bool(mac_key))) return mac_key diff --git a/test/test_eabfile_handler.py b/test/test_eabfile_handler.py new file mode 100644 index 00000000..22bd62b6 --- /dev/null +++ b/test/test_eabfile_handler.py @@ -0,0 +1,145 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +""" unittests for acme2certifier """ +# pylint: disable= C0415, W0212 +import unittest +import sys +import os +from OpenSSL import crypto +from unittest.mock import patch, Mock, MagicMock, mock_open +import requests + +sys.path.insert(0, '.') +sys.path.insert(1, '..') + + +class TestACMEHandler(unittest.TestCase): + """ test class for cgi_handler """ + + def setUp(self): + """ setup unittest """ + import logging + logging.basicConfig(level=logging.CRITICAL) + self.logger = logging.getLogger('test_a2c') + from examples.eab_handler.file_handler import EABhandler + self.eabhandler = EABhandler(self.logger) + self.dir_path = os.path.dirname(os.path.realpath(__file__)) + + def test_001_default(self): + """ default test which always passes """ + self.assertEqual('foo', 'foo') + + @patch('examples.eab_handler.file_handler.EABhandler._config_load') + def test_002__enter__(self, mock_cfg): + """ test enter called """ + mock_cfg.return_value = True + self.eabhandler.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('examples.eab_handler.file_handler.load_config') + def test_003_config_load(self, mock_load_cfg): + """ test _config_load - empty dictionary """ + mock_load_cfg.return_value = {} + self.eabhandler._config_load() + self.assertFalse(self.eabhandler.key_file) + + @patch('examples.eab_handler.file_handler.load_config') + def test_004_config_load(self, mock_load_cfg): + """ test _config_load - bogus values """ + mock_load_cfg.return_value = {'foo': 'bar'} + self.eabhandler._config_load() + self.assertFalse(self.eabhandler.key_file) + + @patch('examples.eab_handler.file_handler.load_config') + def test_005_config_load(self, mock_load_cfg): + """ test _config_load - bogus values """ + mock_load_cfg.return_value = {'EABhandler': {'foo': 'bar'}} + self.eabhandler._config_load() + self.assertFalse(self.eabhandler.key_file) + + @patch('examples.eab_handler.file_handler.load_config') + def test_006_config_load(self, mock_load_cfg): + """ test _config_load - bogus values """ + mock_load_cfg.return_value = {'EABhandler': {'key_file': 'key_file'}} + self.eabhandler._config_load() + self.assertEqual('key_file', self.eabhandler.key_file) + + def test_007_mac_key_get(self): + """ test mac_key_get without file specified """ + self.assertFalse(self.eabhandler.mac_key_get(None)) + + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_008_mac_key_get(self): + """ test mac_key_get with file but no kid """ + self.eabhandler.key_file = 'file' + self.assertFalse(self.eabhandler.mac_key_get(None)) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_009_mac_key_get(self, mock_csv): + """ test mac_key_get csv reader return bogus values """ + self.eabhandler.key_file = 'file' + mock_csv.return_value = ['foo', 'bar'] + self.assertFalse(self.eabhandler.mac_key_get('kid')) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_010_mac_key_get(self, mock_csv): + """ test mac_key_get csv reader return match """ + self.eabhandler.key_file = 'file' + mock_csv.return_value = [{'eab_kid': 'kid', 'eab_mac': 'mac'}] + self.assertEqual('mac', self.eabhandler.mac_key_get('kid')) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_011_mac_key_get(self, mock_csv): + """ test mac_key_get csv reader no match """ + self.eabhandler.key_file = 'file' + mock_csv.return_value = [{'eab_kid': 'kid1', 'eab_mac': 'mac'}] + self.assertFalse(self.eabhandler.mac_key_get('kid')) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_012_mac_key_get(self, mock_csv): + """ test mac_key_get check break after first match """ + self.eabhandler.key_file = 'file' + mock_csv.return_value = [{'eab_kid': 'kid', 'eab_mac': 'mac'}, {'eab_kid': 'kid', 'eab_mac': 'mac2'}] + self.assertEqual('mac', self.eabhandler.mac_key_get('kid')) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_013_mac_key_get(self, mock_csv): + """ test mac_key_get match in the 2nd record """ + self.eabhandler.key_file = 'file' + mock_csv.return_value = [{'eab_kid': 'kid1', 'eab_mac': 'mac'}, {'eab_kid': 'kid', 'eab_mac': 'mac2'}] + self.assertEqual('mac2', self.eabhandler.mac_key_get('kid')) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_014_mac_key_get(self, mock_csv): + """ test mac_key_get csv reader no eab_kid """ + self.eabhandler.key_file = 'file' + mock_csv.return_value = [{'eab__kid': 'kid', 'eab_mac': 'mac'}] + self.assertFalse(self.eabhandler.mac_key_get('kid')) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_015_mac_key_get(self, mock_csv): + """ test mac_key_get csv reader no mac but match """ + self.eabhandler.key_file = 'file' + mock_csv.return_value = [{'eab_kid': 'kid', '_eab_mac': 'mac'}] + self.assertFalse(self.eabhandler.mac_key_get('kid')) + + @patch('csv.DictReader') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_016_mac_key_get(self, mock_csv): + """ test mac_key_get csv reader no mac but match """ + self.eabhandler.key_file = 'file' + mock_csv.side_effect = Exception('ex_mock_csv') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertFalse(self.eabhandler.mac_key_get('kid')) + self.assertIn('ERROR:test_a2c:EABhandler.mac_key_get() error: ex_mock_csv', lcm.output) + +if __name__ == '__main__': + + unittest.main() diff --git a/test/test_eabjson_handler.py b/test/test_eabjson_handler.py new file mode 100644 index 00000000..c9626af1 --- /dev/null +++ b/test/test_eabjson_handler.py @@ -0,0 +1,113 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +""" unittests for acme2certifier """ +# pylint: disable= C0415, W0212 +import unittest +import sys +import os +from OpenSSL import crypto +from unittest.mock import patch, Mock, MagicMock, mock_open +import requests + +sys.path.insert(0, '.') +sys.path.insert(1, '..') + + +class TestACMEHandler(unittest.TestCase): + """ test class for cgi_handler """ + + def setUp(self): + """ setup unittest """ + import logging + logging.basicConfig(level=logging.CRITICAL) + self.logger = logging.getLogger('test_a2c') + from examples.eab_handler.json_handler import EABhandler + self.eabhandler = EABhandler(self.logger) + self.dir_path = os.path.dirname(os.path.realpath(__file__)) + + def test_001_default(self): + """ default test which always passes """ + self.assertEqual('foo', 'foo') + + @patch('examples.eab_handler.json_handler.EABhandler._config_load') + def test_002__enter__(self, mock_cfg): + """ test enter called """ + mock_cfg.return_value = True + self.eabhandler.__enter__() + self.assertTrue(mock_cfg.called) + + @patch('examples.eab_handler.json_handler.load_config') + def test_003_config_load(self, mock_load_cfg): + """ test _config_load - empty dictionary """ + mock_load_cfg.return_value = {} + self.eabhandler._config_load() + self.assertFalse(self.eabhandler.key_file) + + @patch('examples.eab_handler.json_handler.load_config') + def test_004_config_load(self, mock_load_cfg): + """ test _config_load - bogus values """ + mock_load_cfg.return_value = {'foo': 'bar'} + self.eabhandler._config_load() + self.assertFalse(self.eabhandler.key_file) + + @patch('examples.eab_handler.json_handler.load_config') + def test_005_config_load(self, mock_load_cfg): + """ test _config_load - bogus values """ + mock_load_cfg.return_value = {'EABhandler': {'foo': 'bar'}} + self.eabhandler._config_load() + self.assertFalse(self.eabhandler.key_file) + + @patch('examples.eab_handler.json_handler.load_config') + def test_006_config_load(self, mock_load_cfg): + """ test _config_load - bogus values """ + mock_load_cfg.return_value = {'EABhandler': {'key_file': 'key_file'}} + self.eabhandler._config_load() + self.assertEqual('key_file', self.eabhandler.key_file) + + def test_007_mac_key_get(self): + """ test mac_key_get without file specified """ + self.assertFalse(self.eabhandler.mac_key_get(None)) + + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_008_mac_key_get(self): + """ test mac_key_get with file but no kid """ + self.eabhandler.key_file = 'file' + self.assertFalse(self.eabhandler.mac_key_get(None)) + + @patch('json.load') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_009_mac_key_get(self, mock_json): + """ test mac_key_get json reader return bogus values """ + self.eabhandler.key_file = 'file' + mock_json.return_value = {'foo', 'bar'} + self.assertFalse(self.eabhandler.mac_key_get('kid')) + + @patch('json.load') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_010_mac_key_get(self, mock_json): + """ test mac_key_get json match """ + self.eabhandler.key_file = 'file' + mock_json.return_value = {'kid': 'mac'} + self.assertEqual('mac', self.eabhandler.mac_key_get('kid')) + + @patch('json.load') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_011_mac_key_get(self, mock_json): + """ test mac_key_get json no match """ + self.eabhandler.key_file = 'file' + mock_json.return_value = {'kid1': 'mac'} + self.assertFalse(self.eabhandler.mac_key_get('kid')) + + @patch('json.load') + @patch("builtins.open", mock_open(read_data='foo'), create=True) + def test_012_mac_key_get(self, mock_json): + """ test mac_key_get json load exception """ + self.eabhandler.key_file = 'file' + mock_json.side_effect = Exception('ex_json_load') + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertFalse(self.eabhandler.mac_key_get('kid')) + self.assertIn('ERROR:test_a2c:EABhandler.mac_key_get() error: ex_json_load', lcm.output) + +if __name__ == '__main__': + + unittest.main() From 48ec966987dd17ba85a5ca8091ad4e66a6125ffc Mon Sep 17 00:00:00 2001 From: grindsa Date: Thu, 3 Jun 2021 19:34:37 +0200 Subject: [PATCH 32/51] [tst] unittests wsgi-handler --- examples/db_handler/wsgi_handler.py | 13 +- test/test_wsgi_handler.py | 194 +++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 8 deletions(-) diff --git a/examples/db_handler/wsgi_handler.py b/examples/db_handler/wsgi_handler.py index bb71181a..dfe90054 100644 --- a/examples/db_handler/wsgi_handler.py +++ b/examples/db_handler/wsgi_handler.py @@ -295,7 +295,11 @@ def account_update(self, data_dic): """ update existing account """ self.logger.debug('DBStore.account_update({0})'.format(data_dic)) - lookup = dict_from_row(self._account_search('name', data_dic['name'])) + try: + lookup = dict_from_row(self._account_search('name', data_dic['name'])) + except BaseException as _err: + lookup = None + if lookup: if 'alg' not in data_dic: data_dic['alg'] = lookup['alg'] @@ -303,7 +307,6 @@ def account_update(self, data_dic): data_dic['contact'] = lookup['contact'] if 'jwk' not in data_dic: data_dic['jwk'] = lookup['jwk'] - self._db_open() self.cursor.execute('''UPDATE account SET alg = :alg, contact = :contact, jwk = :jwk WHERE name = :name''', data_dic) self.cursor.execute('''SELECT id FROM account WHERE name=:name''', {'name': data_dic['name']}) @@ -381,7 +384,6 @@ def accountlist_get(self): account_list.append(result) self._db_close() - return(vlist, account_list) def authorization_add(self, data_dic): @@ -415,9 +417,8 @@ def authorization_lookup(self, column, string, vlist=('type', 'value')): def authorizations_expired_search(self, column, string, vlist=('id', 'name', 'expires', 'value', 'created_at', 'token', 'status__id', 'status__name', 'order__id', 'order__name'), operant='LIKE'): """ search order table for a certain key/value pair """ - self.logger.debug('DBStore.authorizations_invalid_search(column:{0}, pattern:{1})'.format(column, string)) + self.logger.debug('DBStore.authorizations_expired_search(column:{0}, pattern:{1})'.format(column, string)) self._db_open() - pre_statement = '''SELECT authorization.*, status.name as status__name, @@ -442,7 +443,7 @@ def authorizations_expired_search(self, column, string, vlist=('id', 'name', 'ex authorization_list.append(result) self._db_close() - self.logger.debug('DBStore.authorizations_invalid_search() ended') + self.logger.debug('DBStore.authorizations_expired_search-() ended') return authorization_list def authorization_update(self, data_dic): diff --git a/test/test_wsgi_handler.py b/test/test_wsgi_handler.py index 1e69809c..38153393 100644 --- a/test/test_wsgi_handler.py +++ b/test/test_wsgi_handler.py @@ -8,7 +8,9 @@ from mock import patch, MagicMock except ImportError: from unittest.mock import patch, MagicMock -sys.path.insert(0, '..') + +sys.path.insert(0, '.') +sys.path.insert(1, '..') def dict_from_row(row): """ small helper to convert a select list into a dictionary """ @@ -25,12 +27,15 @@ class TestACMEHandler(unittest.TestCase): def setUp(self): """ setup unittest """ # from acme.wsgi_handler import DBstore - from examples.db_handler.wsgi_handler import DBstore + from examples.db_handler.wsgi_handler import DBstore, initialize + from acme.version import __dbversion__ import logging logging.basicConfig(level=logging.CRITICAL) self.logger = logging.getLogger('test_acme2certifier') self.dir_path = os.path.dirname(os.path.realpath(__file__)) self.dbstore = DBstore(False, self.logger, self.dir_path + '/acme_test.db') + self.initialize = initialize + self.dbversion = __dbversion__ _cleanup(self.dir_path) self.dbstore._db_create() @@ -309,6 +314,53 @@ def test_039_authorization_update(self): data_dic = {'name' : 'name1', 'token' : 'token1', 'expires': '25'} self.assertEqual(1, self.dbstore.authorization_update(data_dic)) + def test_040_authorization_update(self): + """ test DBstore.authorization_update() method no expires """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'type' : 'type1', 'value': 'value1', 'order' : 1} + self.dbstore.authorization_add(data_dic) + data_dic = {'name' : 'name1', 'token' : 'token2'} + self.assertEqual(1, self.dbstore.authorization_update(data_dic)) + self.assertEqual('token2', dict_from_row(self.dbstore._authorization_search('name', 'name1')[0])['token']) + + def test_041_authorization_update(self): + """ test DBstore.authorization_update() method no expires """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'type' : 'type1', 'value': 'value1', 'order' : 1} + self.dbstore.authorization_add(data_dic) + data_dic = {'name' : 'name1', 'expires' : '35'} + self.assertEqual(1, self.dbstore.authorization_update(data_dic)) + self.assertEqual(35, dict_from_row(self.dbstore._authorization_search('name', 'name1')[0])['expires']) + + def test_042_authorization_update(self): + """ test DBstore.authorization_update() method no expires """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'expires' : '35'} + self.assertFalse(self.dbstore.authorization_update(data_dic)) + + def test_043_authorization_update(self): + """ test DBstore.authorization_update() method no expires """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'type' : 'type1', 'value': 'value1', 'order' : 1} + self.dbstore.authorization_add(data_dic) + data_dic = {'name' : 'name1', 'expires' : '35', 'status': 'valid'} + self.assertEqual(1, self.dbstore.authorization_update(data_dic)) + self.assertEqual(35, dict_from_row(self.dbstore._authorization_search('name', 'name1')[0])['expires']) + self.assertEqual(5, dict_from_row(self.dbstore._authorization_search('name', 'name1')[0])['status_id']) + self.assertEqual('valid', dict_from_row(self.dbstore._authorization_search('name', 'name1')[0])['status__name']) + def test_040_authorization_search(self): """ test DBstore.authorization_search() by name """ data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} @@ -578,6 +630,16 @@ def test_066_certificate_add(self): data_dic = {'name': 'certname2', 'error': 'error3', 'poll_identifier': None} self.assertEqual(2, self.dbstore.certificate_add(data_dic)) + def test_067_certificate_add(self): + """ test DBstore.certificate_add() method csr add """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name1', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name': 'certname1', 'order': 'name1'} + self.assertEqual(1, self.dbstore.certificate_add(data_dic)) + self.assertEqual({'cert': None, 'order': u'name1', 'order__name': u'name1', 'name': u'certname1', 'csr': u''}, self.dbstore.certificate_lookup('name', 'certname1')) + def test_067_certificate_lookup(self): """ test DBstore.certificate_lookup() by name (successful) """ data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} @@ -670,6 +732,134 @@ def test_077_certificate_account_check(self, mock_certlookup, mock_orderlookup): mock_orderlookup.return_value = {'account__name': 'name1'} self.assertEqual('foo1', self.dbstore.certificate_account_check(None, 'cert_failed')) + @patch('examples.db_handler.wsgi_handler.DBstore.order_lookup') + @patch('examples.db_handler.wsgi_handler.DBstore.certificate_lookup') + def test_078_certificate_account_check(self, mock_certlookup, mock_orderlookup): + """ test DBstore.certificate_account_check() order lookup retured no account__name """ + mock_certlookup.return_value = {'order__name': 'foo1'} + mock_orderlookup.return_value = {'foo': 'name1'} + self.assertFalse(self.dbstore.certificate_account_check(None, 'cert_failed')) + + def test_078_initialize(self): + """ test initialize function """ + self.assertEqual(None, self.initialize()) + + @patch('examples.db_handler.wsgi_handler.datestr_to_date') + def test_079_account_update(self, mock_datestr): + """ test account update all ok """ + mock_datestr.return_value = 'datestr' + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact2', 'name' : 'name2'} + self.assertEqual(('name2', True), self.dbstore.account_add(data_dic)) + update_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact20', 'name' : 'name2'} + self.assertEqual(2, self.dbstore.account_update(update_dic)) + result = {'id': 2, 'name': 'name2', 'alg': 'alg2', 'contact': 'contact20', 'created_at': 'datestr', 'eab_kid': '', 'jwk': 'jwk2'} + self.assertEqual(result, self.dbstore.account_lookup('name', 'name2')) + + @patch('examples.db_handler.wsgi_handler.datestr_to_date') + def test_080_account_update(self, mock_datestr): + """ test account update without alg """ + mock_datestr.return_value = 'datestr' + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact20', 'name' : 'name2'} + self.assertEqual(('name2', True), self.dbstore.account_add(data_dic)) + update_dic = {'jwk' : 'jwk2', 'contact' : 'contact20', 'name' : 'name2'} + self.assertEqual(2, self.dbstore.account_update(update_dic)) + result = {'id': 2, 'name': 'name2', 'alg': 'alg2', 'contact': 'contact20', 'created_at': 'datestr', 'eab_kid': '', 'jwk': 'jwk2'} + self.assertEqual(result, self.dbstore.account_lookup('name', 'name2')) + + @patch('examples.db_handler.wsgi_handler.datestr_to_date') + def test_081_account_update(self, mock_datestr): + """ test account update without jwk """ + mock_datestr.return_value = 'datestr' + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact21', 'name' : 'name2'} + self.assertEqual(('name2', True), self.dbstore.account_add(data_dic)) + update_dic = {'alg' : 'alg2', 'contact' : 'contact20', 'name' : 'name2'} + self.assertEqual(2, self.dbstore.account_update(update_dic)) + result = {'id': 2, 'name': 'name2', 'alg': 'alg2', 'contact': 'contact20', 'created_at': 'datestr', 'eab_kid': '', 'jwk': 'jwk2'} + self.assertEqual(result, self.dbstore.account_lookup('name', 'name2')) + + @patch('examples.db_handler.wsgi_handler.datestr_to_date') + def test_082_account_update(self, mock_datestr): + """ test account update without jwk """ + mock_datestr.return_value = 'datestr' + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact2', 'name' : 'name2'} + self.assertEqual(('name2', True), self.dbstore.account_add(data_dic)) + update_dic = {'alg' : 'alg2', 'jwk' : 'jwk20', 'name' : 'name2'} + self.assertEqual(2, self.dbstore.account_update(update_dic)) + result = {'id': 2, 'name': 'name2', 'alg': 'alg2', 'contact': 'contact2', 'created_at': 'datestr', 'eab_kid': '', 'jwk': 'jwk20'} + self.assertEqual(result, self.dbstore.account_lookup('name', 'name2')) + + @patch('examples.db_handler.wsgi_handler.datestr_to_date') + def test_083_account_update(self, mock_datestr): + """ test account update without eab_kid but eab_kid inserted in account_add() """ + mock_datestr.return_value = 'datestr' + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact2', 'name' : 'name2', 'eab_kid': 'eab_kid'} + self.assertEqual(('name2', True), self.dbstore.account_add(data_dic)) + update_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact20', 'name' : 'name2'} + self.assertEqual(2, self.dbstore.account_update(update_dic)) + result = {'id': 2, 'name': 'name2', 'alg': 'alg2', 'contact': 'contact20', 'created_at': 'datestr', 'eab_kid': 'eab_kid', 'jwk': 'jwk2'} + self.assertEqual(result, self.dbstore.account_lookup('name', 'name2')) + + def test_084_account_update(self): + """ test account update - account.search() did not return anything """ + update_dic = {'alg' : 'alg2', 'jwk' : 'jwk2', 'contact' : 'contact20', 'name' : 'name2'} + self.assertFalse(self.dbstore.account_update(update_dic)) + + def test_085_accountlist_get(self): + """ test DBstore.accountlist_get """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'type' : 'type1', 'value': 'value1', 'order' : 1} + self.dbstore.authorization_add(data_dic) + data_dic = {'name' : 'challenge1', 'token' : 'token1', 'authorization': 'name1', 'expires' : 25, 'type' : 'type1'} + self.dbstore.challenge_add(data_dic) + data_dic = {'name' : 'challenge2', 'token' : 'token2', 'authorization': 'name1', 'expires' : 25, 'type' : 'type2'} + self.dbstore.challenge_add(data_dic) + vlist = ['id', 'name', 'eab_kid', 'contact', 'created_at', 'jwk', 'alg', 'order__id', 'order__name', 'order__status__id', 'order__status__name', 'order__notbefore', 'order__notafter', 'order__expires', 'order__identifiers', 'order__authorization__id', 'order__authorization__name', 'order__authorization__type', 'order__authorization__value', 'order__authorization__expires', 'order__authorization__token', 'order__authorization__created_at', 'order__authorization__status__id', 'order__authorization__status__name', 'order__authorization__challenge__id', 'order__authorization__challenge__name', 'order__authorization__challenge__token', 'order__authorization__challenge__expires', 'order__authorization__challenge__type', 'order__authorization__challenge__keyauthorization', 'order__authorization__challenge__created_at', 'order__authorization__challenge__status__id', 'order__authorization__challenge__status__name'] + account_list = {'id': 1, 'name': 'name1', 'eab_kid': '', 'contact': 'contact1', 'jwk': '{"key11": "val11", "key12": "val12"}', 'alg': 'alg1', 'order__id': 1, 'order__name': 'name', 'order__status__id': 1, 'order__status__name': 'invalid', 'order__notbefore': '', 'order__notafter': '', 'order__expires': 25, 'order__identifiers': 'identifiers', 'order__authorization__id': 1, 'order__authorization__name': 'name1', 'order__authorization__type': 'type1', 'order__authorization__value': 'value1', 'order__authorization__expires': None, 'order__authorization__token': None, 'order__authorization__status__id': 2, 'order__authorization__status__name': 'pending', 'order__authorization__challenge__id': 1, 'order__authorization__challenge__name': 'challenge1', 'order__authorization__challenge__token': 'token1', 'order__authorization__challenge__expires': 25, 'order__authorization__challenge__type': 'type1', 'order__authorization__challenge__keyauthorization': None, 'order__authorization__challenge__status__id': 2, 'order__authorization__challenge__status__name': 'pending'} + (result_vlist, result_account_list) = self.dbstore.accountlist_get() + self.assertEqual(vlist, result_vlist) + self.assertTrue(set(account_list.items()).issubset( set(result_account_list[0].items()))) + + def test_086_authorizations_expired_search(self): + """ test DBstore.authorizations_expired_search() """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'type' : 'type1', 'value': 'value1', 'order' : 1} + self.dbstore.authorization_add(data_dic) + result = {'id': 1, 'name': 'name1', 'expires': None, 'value': 'value1', 'token': None, 'status__id': 2, 'status__name': 'pending', 'order__id': 1, 'order__name': 'name'} + result_list = self.dbstore.authorizations_expired_search('name', 'name1') + self.assertTrue(set(result.items()).issubset( set(result_list[0].items()))) + + def test_087_certificate_delete(self): + """ test DBstore.certificate_delete() method (succesful) """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name': 'certname1', 'csr': 'csr1', 'order': 'name'} + self.dbstore.certificate_add(data_dic) + result = {'name': 'certname1', 'csr': 'csr1', 'order': 'name', 'order__name': 'name', 'cert': None} + self.assertEqual(result, self.dbstore.certificate_lookup('name', 'certname1')) + self.dbstore.certificate_delete('name', 'certname1') + self.assertFalse(self.dbstore.certificate_lookup('name', 'certname1')) + + def test_088_dbversion(self): + """ test db_version """ + self.assertEqual((self.dbversion, 'tools/db_update.py'), self.dbstore.dbversion_get()) if __name__ == '__main__': From 0a4362a07aec67f8bb559166f640e419b0442df7 Mon Sep 17 00:00:00 2001 From: grindsa Date: Fri, 4 Jun 2021 17:51:18 +0200 Subject: [PATCH 33/51] [tst] unittests wsgi-handler --- examples/db_handler/wsgi_handler.py | 18 ++- test/test_wsgi_handler.py | 186 +++++++++++++++++++++++++++- 2 files changed, 190 insertions(+), 14 deletions(-) diff --git a/examples/db_handler/wsgi_handler.py b/examples/db_handler/wsgi_handler.py index dfe90054..0331b0e5 100644 --- a/examples/db_handler/wsgi_handler.py +++ b/examples/db_handler/wsgi_handler.py @@ -585,7 +585,6 @@ def certificatelist_get(self): self.cursor.execute(pre_statement) rows = self.cursor.fetchall() - # process results cert_list = [] for row in rows: @@ -658,7 +657,7 @@ def certificates_search(self, column, string, vlist=('name', 'csr', 'cert', 'ord self.logger.debug('DBStore.certificates_search() ended') return cert_list - def challenges_search(self, column, string, vlist=('name', 'type', 'cert', 'status__name', 'token')): + def challenges_search(self, column, string, vlist=('name', 'type', 'status__name', 'token')): """ search challenge table for a certain key/value pair """ self.logger.debug('DBStore._challenge_search(column:{0}, pattern:{1})'.format(column, string)) self._db_open() @@ -771,24 +770,23 @@ def db_update(self): certificate_column_list = [] for column in self.cursor.fetchall(): certificate_column_list.append(column[1]) - if 'poll_identifier' not in certificate_column_list: - self.logger.debug('alter certificate table - add poll_identifier') + self.logger.info('alter certificate table - add poll_identifier') self.cursor.execute('''ALTER TABLE certificate ADD COLUMN poll_identifier text''') if 'issue_uts' not in certificate_column_list: - self.logger.debug('alter certificate table - add issue_uts') + self.logger.info('alter certificate table - add issue_uts') self.cursor.execute('''ALTER TABLE certificate ADD COLUMN issue_uts integer DEFAULT 0''') if 'expire_uts' not in certificate_column_list: - self.logger.debug('alter certificate table - add expire_uts') + self.logger.info('alter certificate table - add expire_uts') self.cursor.execute('''ALTER TABLE certificate ADD COLUMN expire_uts integer DEFAULT 0''') # add additional values to status table pre_statement = 'SELECT * from status WHERE status.{0} LIKE ?'.format('name') self.cursor.execute(pre_statement, ['deactivated']) if not self.cursor.fetchone(): - self.logger.debug('adding additional status') + self.logger.info('adding additional status') self.cursor.execute('''INSERT INTO status(name) VALUES(:name)''', {'name': 'expired'}) self.cursor.execute('''INSERT INTO status(name) VALUES(:name)''', {'name': 'deactivated'}) self.cursor.execute('''INSERT INTO status(name) VALUES(:name)''', {'name': 'revoked'}) @@ -799,7 +797,7 @@ def db_update(self): challenges_column_list.append(column[1]) if 'validated' not in challenges_column_list: - self.logger.debug('alter challenge table - add validated') + self.logger.info('alter challenge table - add validated') self.cursor.execute('''ALTER TABLE challenge ADD COLUMN validated integer DEFAULT 0''') self.cursor.execute('''PRAGMA table_info(account)''') @@ -807,7 +805,7 @@ def db_update(self): for column in self.cursor.fetchall(): account_column_list.append(column[1]) if 'eab_kid' not in account_column_list: - self.logger.debug('alter account table - add eab_kid') + self.logger.info('alter account table - add eab_kid') self.cursor.execute('''ALTER TABLE account ADD COLUMN eab_kid varchar(255) DEFAULT \'\'''') # housekeeping table @@ -953,7 +951,7 @@ def order_update(self, data_dic): self._db_close() self.logger.debug('DBStore.order_update() ended') - def orders_invalid_search(self, column, string, vlist=('id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'acccount__contact'), operant='LIKE'): + def orders_invalid_search(self, column, string, vlist=('id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'), operant='LIKE'): """ search order table for a certain key/value pair """ self.logger.debug('DBStore.orders_search(column:{0}, pattern:{1})'.format(column, string)) self._db_open() diff --git a/test/test_wsgi_handler.py b/test/test_wsgi_handler.py index 38153393..329785d9 100644 --- a/test/test_wsgi_handler.py +++ b/test/test_wsgi_handler.py @@ -5,9 +5,9 @@ import sys import os try: - from mock import patch, MagicMock + from mock import patch, MagicMock, Mock except ImportError: - from unittest.mock import patch, MagicMock + from unittest.mock import patch, MagicMock, Mock sys.path.insert(0, '.') sys.path.insert(1, '..') @@ -31,7 +31,7 @@ def setUp(self): from acme.version import __dbversion__ import logging logging.basicConfig(level=logging.CRITICAL) - self.logger = logging.getLogger('test_acme2certifier') + self.logger = logging.getLogger('test_a2c') self.dir_path = os.path.dirname(os.path.realpath(__file__)) self.dbstore = DBstore(False, self.logger, self.dir_path + '/acme_test.db') self.initialize = initialize @@ -857,10 +857,188 @@ def test_087_certificate_delete(self): self.dbstore.certificate_delete('name', 'certname1') self.assertFalse(self.dbstore.certificate_lookup('name', 'certname1')) - def test_088_dbversion(self): + def test_088_certificatelist_get(self): + """ test DBstore.certificatelist_get() """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name': 'certname1', 'csr': 'csr1', 'order': 'name'} + self.dbstore.certificate_add(data_dic) + data_dic = {'name': 'certname1', 'cert': 'cert', 'cert_raw': 'cert_raw'} + self.assertEqual(1, self.dbstore.certificate_add(data_dic)) + vlist = ['id', 'name', 'cert_raw', 'csr', 'poll_identifier', 'created_at', 'issue_uts', 'expire_uts', 'order__id', 'order__name', 'order__status__name', 'order__notbefore', 'order__notafter', 'order__expires', 'order__identifiers', 'order__account__name', 'order__account__contact', 'order__account__created_at', 'order__account__jwk', 'order__account__alg', 'order__account__eab_kid'] + certlist = {'id': 1, 'name': 'certname1', 'cert_raw': 'cert_raw', 'csr': 'csr1', 'poll_identifier': None, 'issue_uts': 0, 'expire_uts': 0, 'order__id': 1, 'order__name': 'name', 'order__status__name': 1, 'order__notbefore': '', 'order__notafter': '', 'order__expires': 25, 'order__identifiers': 'identifiers', 'order__account__name': 'name1', 'order__account__contact': 'contact1', 'order__account__jwk': '{"key11": "val11", "key12": "val12"}', 'order__account__alg': 'alg1', 'order__account__eab_kid': ''} + (result_vlist, result_certifcate_list) = self.dbstore.certificatelist_get() + self.assertEqual(vlist, result_vlist) + self.assertTrue(set(certlist.items()).issubset( set(result_certifcate_list[0].items()))) + + def test_089_dbversion(self): """ test db_version """ self.assertEqual((self.dbversion, 'tools/db_update.py'), self.dbstore.dbversion_get()) + def test_090_certificates_search(self): + """ test DBstore.certificates_search() """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name': 'certname1', 'csr': 'csr1', 'order': 'name'} + self.dbstore.certificate_add(data_dic) + data_dic = {'name': 'certname1', 'cert': 'cert', 'cert_raw': 'cert_raw'} + self.dbstore.certificate_add(data_dic) + self.assertEqual([{'name': 'certname1', 'csr': 'csr1', 'cert': 'cert', 'order__name': 'name', 'order': 'name'}], self.dbstore.certificates_search('cert', 'cert')) + self.assertEqual([{'name': 'certname1', 'csr': 'csr1', 'cert': 'cert', 'order__name': 'name', 'order': 'name'}], self.dbstore.certificates_search('cert_raw', 'cert_raw')) + self.assertEqual([{'name': 'certname1', 'csr': 'csr1', 'cert': 'cert', 'order__name': 'name', 'order': 'name'}], self.dbstore.certificates_search('certificate.name', 'certname1')) + self.assertEqual([{'cert': 'cert', 'name': 'certname1'}], self.dbstore.certificates_search('certificate.name', 'certname1', vlist=['name', 'cert'])) + + def test_091_certificates_search(self): + """ test DBstore.certificates_search() no result""" + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name': 'certname1', 'csr': 'csr1', 'order': 'name'} + self.dbstore.certificate_add(data_dic) + data_dic = {'name': 'certname1', 'cert': 'cert', 'cert_raw': 'cert_raw'} + self.dbstore.certificate_add(data_dic) + self.assertFalse(self.dbstore.certificates_search('cert', 'cert1')) + + def test_092_challenge_search(self): + """ test DBstore.challenge_search method """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'type' : 'type1', 'value': 'value1', 'order' : 1} + self.dbstore.authorization_add(data_dic) + data_dic = {'name' : 'challenge1', 'token' : 'token1', 'authorization': 'name1', 'expires' : 25, 'type' : 'type1'} + self.dbstore.challenge_add(data_dic) + result = [{'name': 'challenge1', 'status': 'pending', 'status__name': 'pending', 'token': 'token1', 'type': 'type1'}] + self.assertEqual(result, self.dbstore.challenges_search('challenge.name', 'challenge1')) + self.assertEqual(result, self.dbstore.challenges_search('challenge.token', 'token1')) + self.assertEqual(result, self.dbstore.challenges_search('status__name', 'pending')) + self.assertEqual([{'name': 'challenge1', 'token': 'token1'}], self.dbstore.challenges_search('status__name', 'pending', vlist=['name', 'token'])) + + def test_093_challenge_search(self): + """ test DBstore.challenge_search failed """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name' : 'name', 'identifiers' : 'identifiers', 'account' : 'name1', 'status' : 1, 'expires' : '25'} + self.dbstore.order_add(data_dic) + data_dic = {'name' : 'name1', 'type' : 'type1', 'value': 'value1', 'order' : 1} + self.dbstore.authorization_add(data_dic) + data_dic = {'name' : 'challenge1', 'token' : 'token1', 'authorization': 'name1', 'expires' : 25, 'type' : 'type1'} + self.dbstore.challenge_add(data_dic) + self.assertFalse(self.dbstore.challenges_search('challenge.name', 'challenge')) + + @patch('examples.db_handler.wsgi_handler.DBstore._db_close') + @patch('examples.db_handler.wsgi_handler.DBstore._db_open') + def test_094_db_update(self, mock_open, mock_close): + """ test dbupdate - not alter certificates table """ + self.dbstore.cursor = Mock() + self.dbstore.cursor.fetchall = Mock(return_value=[[2, 'poll_identifier'], [2, 'issue_uts'], [2, 'expire_uts']]) + self.dbstore.cursor.fetchone = Mock(return_value=[1, 2, 3, 4, 5]) + mock_open.return_value = Mock() + mock_close.return_value = Mock() + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertTrue = self.dbstore.db_update() + self.assertIn('INFO:test_a2c:alter challenge table - add validated', lcm.output) + self.assertIn('INFO:test_a2c:alter account table - add eab_kid', lcm.output) + self.assertIn('INFO:test_a2c:alter account table - add eab_kid', lcm.output) + + @patch('examples.db_handler.wsgi_handler.DBstore._db_close') + @patch('examples.db_handler.wsgi_handler.DBstore._db_open') + def test_095_db_update(self, mock_open, mock_close): + """ test dbupdate - not alter challenge table """ + self.dbstore.cursor = Mock() + self.dbstore.cursor.fetchall = Mock(return_value=[[2, 'validated']]) + self.dbstore.cursor.fetchone = Mock(return_value=[1, 2, 3, 4, 5]) + mock_open.return_value = Mock() + mock_close.return_value = Mock() + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertTrue = self.dbstore.db_update() + self.assertIn('INFO:test_a2c:alter certificate table - add poll_identifier', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add issue_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add expire_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter account table - add eab_kid', lcm.output) + + @patch('examples.db_handler.wsgi_handler.DBstore._db_close') + @patch('examples.db_handler.wsgi_handler.DBstore._db_open') + def test_096_db_update(self, mock_open, mock_close): + """ test dbupdate - not alter account table """ + self.dbstore.cursor = Mock() + self.dbstore.cursor.fetchall = Mock(return_value=[[2, 'eab_kid']]) + self.dbstore.cursor.fetchone = Mock(return_value=[1, 2, 3, 4, 5]) + mock_open.return_value = Mock() + mock_close.return_value = Mock() + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertTrue = self.dbstore.db_update() + self.assertIn('INFO:test_a2c:alter certificate table - add poll_identifier', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add issue_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add expire_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter challenge table - add validated', lcm.output) + + @patch('examples.db_handler.wsgi_handler.DBstore._db_close') + @patch('examples.db_handler.wsgi_handler.DBstore._db_open') + def test_097_db_update(self, mock_open, mock_close): + """ test dbupdate - status update """ + self.dbstore.cursor = Mock() + self.dbstore.cursor.fetchall = Mock(return_value=[[2, 'foo']]) + self.dbstore.cursor.fetchone = Mock(side_effect=[None, [1, 2, 3, 4, 5]]) + mock_open.return_value = Mock() + mock_close.return_value = Mock() + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertTrue = self.dbstore.db_update() + self.assertIn('INFO:test_a2c:alter certificate table - add poll_identifier', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add issue_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add expire_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter challenge table - add validated', lcm.output) + self.assertIn('INFO:test_a2c:alter account table - add eab_kid', lcm.output) + self.assertIn('INFO:test_a2c:adding additional status', lcm.output) + + @patch('examples.db_handler.wsgi_handler.DBstore._db_close') + @patch('examples.db_handler.wsgi_handler.DBstore._db_open') + def test_098_db_update(self, mock_open, mock_close): + """ test dbupdate - housekeeping update """ + self.dbstore.cursor = Mock() + self.dbstore.cursor.fetchall = Mock(return_value=[[2, 'foo']]) + self.dbstore.cursor.fetchone = Mock(side_effect=[None, [2, 2, 3, 4, 5]]) + mock_open.return_value = Mock() + mock_close.return_value = Mock() + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertTrue = self.dbstore.db_update() + self.assertIn('INFO:test_a2c:alter certificate table - add poll_identifier', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add issue_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter certificate table - add expire_uts', lcm.output) + self.assertIn('INFO:test_a2c:alter challenge table - add validated', lcm.output) + self.assertIn('INFO:test_a2c:alter account table - add eab_kid', lcm.output) + self.assertIn('INFO:test_a2c:adding additional status', lcm.output) + self.assertIn('INFO:test_a2c:alter account table - add eab_kid', lcm.output) + + def test_099_order_update(self): + """ test DBstore.order_add() method for a new entry """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name': 'name', 'identifiers': 'identifiers', 'account': 'name1', 'status': 1, 'expires': '25'} + self.assertEqual(1, self.dbstore.order_add(data_dic)) + update_dic = {'name': 'name', 'status': 'valid'} + self.dbstore.order_update(update_dic) + result = {'expires': 25, 'notbefore': 0, 'notafter': 0, 'identifiers': 'identifiers', 'status': 'valid'} + self.assertEqual(result, self.dbstore.order_lookup('name', 'name')) + + def test_100_order_update(self): + """ test DBstore.order_add() method for a new entry """ + data_dic = {'alg' : 'alg1', 'jwk' : '{"key11": "val11", "key12": "val12"}', 'contact' : 'contact1', 'name' : 'name1'} + self.dbstore.account_add(data_dic) + data_dic = {'name': 'name1', 'identifiers': 'identifiers2', 'account': 'name1', 'status': 1, 'expires': '25'} + self.assertEqual(1, self.dbstore.order_add(data_dic)) + data_dic = {'name': 'name2', 'identifiers': 'identifiers2', 'account': 'name1', 'status': 2, 'expires': '25'} + self.assertEqual(2, self.dbstore.order_add(data_dic)) + expected_result = {'account__contact': 'contact1', 'account__id': 1, 'account__name': 'name1', 'expires': 25, 'id': 2, 'identifiers': 'identifiers2', 'name': 'name2', 'status__id': 2, 'status__name': 'pending'} + order_list = self.dbstore.orders_invalid_search('name', 'name2') + self.assertTrue(set(expected_result.items()).issubset( set(order_list[0].items()))) + if __name__ == '__main__': unittest.main() From a35bef7abef7bafcefb85dda0c948f9d17046d91 Mon Sep 17 00:00:00 2001 From: grindsa Date: Fri, 4 Jun 2021 19:20:05 +0200 Subject: [PATCH 34/51] [doc] codecov.io links in Readme.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3907420e..f3acce19 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,9 @@ ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/grindsa/acme2certifier/devel.svg?label=last%20commit%20into%20devel) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2581/badge)](https://bestpractices.coreinfrastructure.org/projects/2581) -![Codecov main](https://img.shields.io/codecov/c/gh/grindsa/acme2certifier/branch/master?label=test%20coverage%20master) -![Codecov devel](https://img.shields.io/codecov/c/gh/grindsa/acme2certifier/branch/devel?label=test%20coverage%20devel) +[![Codecov main](https://img.shields.io/codecov/c/gh/grindsa/acme2certifier/branch/master?label=test%20coverage%20master)](https://app.codecov.io/gh/grindsa/acme2certifier/branch/master) +[![Codecov devel](https://img.shields.io/codecov/c/gh/grindsa/acme2certifier/branch/devel?label=test%20coverage%20devel)](https://app.codecov.io/gh/grindsa/acme2certifier/branch/devel) + acme2certifier is development project to create an ACME protocol proxy. Main intention is to provide ACME services on CA servers which do not support this From c597b3d4e84e0b536c8760d43e7e2b2e05fcfaf7 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 5 Jun 2021 19:34:33 +0200 Subject: [PATCH 35/51] fix for #62 --- examples/ca_handler/xca_ca_handler.py | 98 +++++++++++++++++++-------- 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/examples/ca_handler/xca_ca_handler.py b/examples/ca_handler/xca_ca_handler.py index 2f31bdce..4b2247ff 100644 --- a/examples/ca_handler/xca_ca_handler.py +++ b/examples/ca_handler/xca_ca_handler.py @@ -354,23 +354,39 @@ def _item_insert(self, item_dic): self.logger.debug('CAhandler._item_insert() ended with row_id: {0}'.format(row_id)) return row_id - def _kue_generate(self, ku_val=23): + def _kue_generate(self, kuval=0, ku_csr=None): """ set genearte key usage extenstion """ - self.logger.debug('CAhandler._extension_list_generate()') - - # generate and reverse key_usage_list - key_usage_list = ['digitalSignature', 'nonRepudiation', 'keyEncipherment', 'dataEncipherment', 'keyAgreement', 'keyCertSign', 'cRLSign', 'encipherOnly', 'decipherOnly'] + self.logger.debug('CAhandler._kue_generate()') # convert keyusage value from template - try: - kuval = int(ku_val) - except BaseException: - self.logger.error('CAhandler._extension_list_generate(): convert to int failed defaulting ku_val to 23') - kuval = 23 + if kuval: + try: + kuval = int(kuval) + except BaseException: + self.logger.error('CAhandler._kue_generate(): convert to int failed defaulting ku_val to 0') + kuval = 0 + + if kuval: + # we have a key-usage value from template + self.logger.info('CAhandler._kue_generate() with data from template') + ku_string = self._ku_string_generate(kuval) + elif ku_csr: + # no data from template but data from csr + self.logger.info('CAhandler._kue_generate() with data from csr') + ku_string = ku_csr + else: + # no data from template no data from csr - default (23) + self.logger.info('CAhandler._kue_generate() with 23') + ku_string = self._ku_string_generate(23) + + self.logger.debug('CAhandler._kue_generate() ended with: {0}'.format(ku_string)) + return ku_string - if kuval == 0: - self.logger.error('CAhandler._extension_list_generate(): defaulting ku_val to 23') - kuval = 23 + def _ku_string_generate(self, kuval): + self.logger.debug('CAhandler._ku_string_generate({0})'.format(kuval)) + + # generate and reverse key_usage_list + key_usage_list = ['digitalSignature', 'nonRepudiation', 'keyEncipherment', 'dataEncipherment', 'keyAgreement', 'keyCertSign', 'cRLSign', 'encipherOnly', 'decipherOnly'] kubin = '{0:b}'.format(kuval)[::-1] ku_list = [] @@ -379,7 +395,7 @@ def _kue_generate(self, ku_val=23): ku_list.append(key_usage_list[idx]) ku_string = ','.join(ku_list) - self.logger.debug('CAhandler._extension_list_generate() ended with: {0}'.format(ku_string)) + self.logger.debug('CAhandler._ku_string_generate() endedt with: {0}'.format(ku_string)) return ku_string def _pemcertchain_generate(self, ee_cert, issuer_cert): @@ -662,10 +678,12 @@ def enroll(self, csr): cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(cert_validity * 86400) - # get extension list - extension_list = self._extension_list_generate(template_dic, cert, ca_cert) + # get extension list from CSR + csr_extensions_list = req.get_extensions() + extension_list = self._extension_list_generate(template_dic, cert, ca_cert, csr_extensions_list) + # add extensions (copy from CSR and take the ones we constructed) - cert.add_extensions(req.get_extensions()) + # cert.add_extensions(csr_extensions_list) cert.add_extensions(extension_list) if dn_dic: @@ -693,17 +711,14 @@ def enroll(self, csr): self.logger.debug('Certificate.enroll() ended') return(error, cert_bundle, cert_raw, None) - def _extension_list_generate(self, template_dic, cert, ca_cert): + def _extension_list_generate(self, template_dic, cert, ca_cert, csr_extensions_list): """ set extension list """ self.logger.debug('CAhandler._extension_list_generate()') - default_extension_list = [ - crypto.X509Extension(convert_string_to_byte('subjectKeyIdentifier'), False, convert_string_to_byte('hash'), subject=cert), - crypto.X509Extension(convert_string_to_byte('authorityKeyIdentifier'), False, convert_string_to_byte('keyid:always'), issuer=ca_cert), - crypto.X509Extension(convert_string_to_byte('keyUsage'), True, convert_string_to_byte('digitalSignature,keyEncipherment')), - crypto.X509Extension(convert_string_to_byte('basicConstraints'), True, convert_string_to_byte('CA:FALSE')), - crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), False, convert_string_to_byte('serverAuth')), - # crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), False, convert_string_to_byte('clientAuth,serverAuth')), - ] + + csr_extensions_dic = {} + for ext in csr_extensions_list: + csr_extensions_dic[convert_byte_to_string(ext.get_short_name())] = ext + print(csr_extensions_dic) if template_dic: extension_list = [ @@ -731,9 +746,20 @@ def _extension_list_generate(self, template_dic, cert, ca_cert): kuc = False else: kuc = False - # generate key-usage extension - ku_string = self._kue_generate(template_dic['keyUse']) - extension_list.append(crypto.X509Extension(convert_string_to_byte('keyUsage'), kuc, convert_string_to_byte(ku_string))) + kup = template_dic['keyUse'] + else: + kuc = False + kup = 0 + + if 'keyUsage' in csr_extensions_dic: + # get key usage field csr + ku_csr = csr_extensions_dic['keyUsage'].__str__() + else: + ku_csr = None + + # generate key-usage extension + ku_string = self._kue_generate(kup, ku_csr) + extension_list.append(crypto.X509Extension(convert_string_to_byte('keyUsage'), kuc, convert_string_to_byte(ku_string))) # add cdp if 'crlDist' in template_dic and template_dic['crlDist']: @@ -752,9 +778,23 @@ def _extension_list_generate(self, template_dic, cert, ca_cert): extension_list.append(crypto.X509Extension(convert_string_to_byte('basicConstraints'), bcc, convert_string_to_byte('CA:TRUE'))) elif template_dic['ca'] == '2': extension_list.append(crypto.X509Extension(convert_string_to_byte('basicConstraints'), bcc, convert_string_to_byte('CA:FALSE'))) + else: + default_extension_list = [ + crypto.X509Extension(convert_string_to_byte('subjectKeyIdentifier'), False, convert_string_to_byte('hash'), subject=cert), + crypto.X509Extension(convert_string_to_byte('authorityKeyIdentifier'), False, convert_string_to_byte('keyid:always'), issuer=ca_cert), + crypto.X509Extension(convert_string_to_byte('keyUsage'), True, convert_string_to_byte('digitalSignature,keyEncipherment')), + crypto.X509Extension(convert_string_to_byte('basicConstraints'), True, convert_string_to_byte('CA:FALSE')), + crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), False, convert_string_to_byte('serverAuth')), + # crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), False, convert_string_to_byte('clientAuth,serverAuth')), + ] extension_list = default_extension_list + # add subjectAltName(s) + if 'subjectAltName' in csr_extensions_dic: + self.logger.debug('CAhandler._extension_list_generate(): adding subAltNames: {0}'.format(csr_extensions_dic['subjectAltName'].__str__())) + extension_list.append(csr_extensions_dic['subjectAltName']) + self.logger.debug('CAhandler._extension_list_generate() ended') return extension_list From 025e2294c08da17e0ecba383dee7788736a6c506 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 6 Jun 2021 09:53:39 +0200 Subject: [PATCH 36/51] [fix] eku usage --- examples/ca_handler/xca_ca_handler.py | 103 ++++--- test/test_xca_ca_handler.py | 416 +++++++++++--------------- 2 files changed, 251 insertions(+), 268 deletions(-) diff --git a/examples/ca_handler/xca_ca_handler.py b/examples/ca_handler/xca_ca_handler.py index 4b2247ff..98bb72c8 100644 --- a/examples/ca_handler/xca_ca_handler.py +++ b/examples/ca_handler/xca_ca_handler.py @@ -329,6 +329,36 @@ def _db_close(self): self.dbs.close() # self.logger.debug('DBStore._db_close() ended') + def _extended_keyusage_generate(self, template_dic, csr_extensions_dic=None): + """ set generate extended key usage extenstion """ + self.logger.debug('CAhandler._extended_keyusage_generate()') + + if 'eKeyUse' in template_dic: + # eku included in tempalate + if 'ekuCritical' in template_dic: + try: + ekuc = bool(int(template_dic['ekuCritical'])) + except BaseException: + ekuc = False + else: + ekuc = False + eku_string = template_dic['eKeyUse'] + + elif 'extendedKeyUsage' in csr_extensions_dic: + # eku usage in extention + try: + ekuc = csr_extensions_dic['extendedKeyUsage'].get_critical() + except BaseException: + ekuc = False + eku_string = csr_extensions_dic['extendedKeyUsage'].__str__() + + else: + # neither extension nor template + eku_string = None + ekuc = False + + return(ekuc, eku_string) + def _item_insert(self, item_dic): """ insert new entry to item_table """ self.logger.debug('CAhandler._item_insert()') @@ -354,8 +384,36 @@ def _item_insert(self, item_dic): self.logger.debug('CAhandler._item_insert() ended with row_id: {0}'.format(row_id)) return row_id + def _keyusage_generate(self, template_dic, csr_extensions_dic=None): + """ set generate key usage extenstion """ + self.logger.debug('CAhandler._keyusage_generate()') + + if 'keyUse' in template_dic: + if 'kuCritical' in template_dic: + try: + kuc = bool(int(template_dic['kuCritical'])) + except BaseException: + kuc = False + else: + kuc = False + kup = template_dic['keyUse'] + else: + kuc = False + kup = 0 + + if 'keyUsage' in csr_extensions_dic: + # get key usage field csr + ku_csr = csr_extensions_dic['keyUsage'].__str__() + else: + ku_csr = None + + # generate key-usage extension + ku_string = self._kue_generate(kup, ku_csr) + + return(kuc, ku_string) + def _kue_generate(self, kuval=0, ku_csr=None): - """ set genearte key usage extenstion """ + """ set generate key usage extension """ self.logger.debug('CAhandler._kue_generate()') # convert keyusage value from template @@ -589,7 +647,10 @@ def _utf_stream_parse(self, utf_stream=None): if idx > 0: # strip the first character ele = ele[1:] - parameter_list.append(ele.decode('utf-8')) + if ele == b'eKeyUse\xff\xff\xff\xff': + self.logger.debug('_utf_stream_parse(): hack to skip template with empty eku - maybe a bug in xca...') + else: + parameter_list.append(ele.decode('utf-8')) if parameter_list: if len(parameter_list) % 2 != 0: @@ -726,41 +787,15 @@ def _extension_list_generate(self, template_dic, cert, ca_cert, csr_extensions_l crypto.X509Extension(convert_string_to_byte('authorityKeyIdentifier'), False, convert_string_to_byte('keyid:always'), issuer=ca_cert), ] - # extended key_usage - if 'eKeyUse' in template_dic: - if 'ekuCritical' in template_dic: - try: - ekuc = bool(int(template_dic['ekuCritical'])) - except BaseException: - ekuc = False - else: - ekuc = False - extension_list.append(crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), ekuc, convert_string_to_byte(template_dic['eKeyUse']))) - # key_usage - if 'keyUse' in template_dic: - if 'kuCritical' in template_dic: - try: - kuc = bool(int(template_dic['kuCritical'])) - except BaseException: - kuc = False - else: - kuc = False - kup = template_dic['keyUse'] - else: - kuc = False - kup = 0 - - if 'keyUsage' in csr_extensions_dic: - # get key usage field csr - ku_csr = csr_extensions_dic['keyUsage'].__str__() - else: - ku_csr = None - - # generate key-usage extension - ku_string = self._kue_generate(kup, ku_csr) + (kuc, ku_string) = self._keyusage_generate(template_dic, csr_extensions_dic) extension_list.append(crypto.X509Extension(convert_string_to_byte('keyUsage'), kuc, convert_string_to_byte(ku_string))) + # extended key_usage + (ekuc, eku_string) = self._extended_keyusage_generate(template_dic, csr_extensions_dic) + if eku_string: + extension_list.append(crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), ekuc, convert_string_to_byte(eku_string))) + # add cdp if 'crlDist' in template_dic and template_dic['crlDist']: extension_list.append(crypto.X509Extension(convert_string_to_byte('crlDistributionPoints'), False, convert_string_to_byte(template_dic['crlDist']))) diff --git a/test/test_xca_ca_handler.py b/test/test_xca_ca_handler.py index 4729fa55..1d9d0923 100644 --- a/test/test_xca_ca_handler.py +++ b/test/test_xca_ca_handler.py @@ -924,81 +924,175 @@ def test_124__validity_calculate(self): template_dic = {'novalidM': '2', 'validN': '2'} self.assertEqual(365, self.cahandler._validity_calculate(template_dic)) - def test_125__kue_generate(self): + def test_125__ku_string_generate(self): """ CAhandler._kue_generate() - digitalSignature """ kup = 1 - self.assertEqual('digitalSignature', self.cahandler._kue_generate(kup)) + self.assertEqual('digitalSignature', self.cahandler._ku_string_generate(kup)) - def test_126__kue_generate(self): + def test_126__ku_string_generate(self): """ CAhandler._kue_generate() - nonRepudiation """ kup = 2 - self.assertEqual('nonRepudiation', self.cahandler._kue_generate(kup)) + self.assertEqual('nonRepudiation', self.cahandler._ku_string_generate(kup)) - def test_127__kue_generate(self): + def test_127__ku_string_generate(self): """ CAhandler._kue_generate() - keyEncipherment """ kup = 4 - self.assertEqual('keyEncipherment', self.cahandler._kue_generate(kup)) + self.assertEqual('keyEncipherment', self.cahandler._ku_string_generate(kup)) - def test_128__kue_generate(self): + def test_128__ku_string_generate(self): """ CAhandler._kue_generate() - dataEncipherment """ kup = 8 - self.assertEqual('dataEncipherment', self.cahandler._kue_generate(kup)) + self.assertEqual('dataEncipherment', self.cahandler._ku_string_generate(kup)) - def test_129__kue_generate(self): + def test_129__ku_string_generate(self): """ CAhandler._kue_generate() - keyAgreement """ kup = 16 - self.assertEqual('keyAgreement', self.cahandler._kue_generate(kup)) + self.assertEqual('keyAgreement', self.cahandler._ku_string_generate(kup)) - def test_130__kue_generate(self): + def test_130__ku_string_generate(self): """ CAhandler._kue_generate() - keyCertSign """ kup = 32 - self.assertEqual('keyCertSign', self.cahandler._kue_generate(kup)) + self.assertEqual('keyCertSign', self.cahandler._ku_string_generate(kup)) - def test_131__kue_generate(self): + def test_131__ku_string_generate(self): """ CAhandler._kue_generate() - cRLSign """ kup = 64 - self.assertEqual('cRLSign', self.cahandler._kue_generate(kup)) + self.assertEqual('cRLSign', self.cahandler._ku_string_generate(kup)) - def test_132__kue_generate(self): + def test_132__ku_string_generate(self): """ CAhandler._kue_generate() - encipherOnly """ kup = 128 - self.assertEqual('encipherOnly', self.cahandler._kue_generate(kup)) + self.assertEqual('encipherOnly', self.cahandler._ku_string_generate(kup)) - def test_133__kue_generate(self): + def test_133__ku_string_generate(self): """ CAhandler._kue_generate() - encipherOnly """ kup = 256 - self.assertEqual('decipherOnly', self.cahandler._kue_generate(kup)) + self.assertEqual('decipherOnly', self.cahandler._ku_string_generate(kup)) - def test_134__kue_generate(self): + def test_134__ku_string_generate(self): """ CAhandler._kue_generate() - digitalSignature and nonRepudiation """ kup = 3 - self.assertEqual('digitalSignature,nonRepudiation', self.cahandler._kue_generate(kup)) + self.assertEqual('digitalSignature,nonRepudiation', self.cahandler._ku_string_generate(kup)) - def test_135__kue_generate(self): + def test_135__ku_string_generate(self): """ CAhandler._kue_generate() - all """ kup = 511 - self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign,encipherOnly,decipherOnly', self.cahandler._kue_generate(kup)) + self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign,encipherOnly,decipherOnly', self.cahandler._ku_string_generate(kup)) def test_136__kue_generate(self): - """ CAhandler._kue_generate() - all """ + """ CAhandler._kue_generate() - kup 0 defaulting to 23""" kup = 0 with self.assertLogs('test_a2c', level='INFO') as lcm: self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,keyAgreement', self.cahandler._kue_generate(kup)) - self.assertIn('ERROR:test_a2c:CAhandler._extension_list_generate(): defaulting ku_val to 23', lcm.output) + self.assertIn('INFO:test_a2c:CAhandler._kue_generate() with 23', lcm.output) def test_137__kue_generate(self): - """ CAhandler._kue_generate() - all """ + """ CAhandler._kue_generate() - kup '0' defaulting to 23 """ kup = '0' with self.assertLogs('test_a2c', level='INFO') as lcm: self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,keyAgreement', self.cahandler._kue_generate(kup)) - self.assertIn('ERROR:test_a2c:CAhandler._extension_list_generate(): defaulting ku_val to 23', lcm.output) + self.assertIn('INFO:test_a2c:CAhandler._kue_generate() with 23', lcm.output) def test_138__kue_generate(self): - """ CAhandler._kue_generate() - all """ + """ CAhandler._kue_generate() - kup cannot get converted to int """ kup = 'a' with self.assertLogs('test_a2c', level='INFO') as lcm: self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,keyAgreement', self.cahandler._kue_generate(kup)) - self.assertIn('ERROR:test_a2c:CAhandler._extension_list_generate(): convert to int failed defaulting ku_val to 23', lcm.output) + self.assertIn('INFO:test_a2c:CAhandler._kue_generate() with 23', lcm.output) + + def test_139__kue_generate(self): + """ CAhandler._kue_generate() - kup none """ + kup = None + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual('digitalSignature,nonRepudiation,keyEncipherment,keyAgreement', self.cahandler._kue_generate(kup)) + self.assertIn('INFO:test_a2c:CAhandler._kue_generate() with 23', lcm.output) + + def test_140__kue_generate(self): + """ CAhandler._kue_generate() - kup none but csr_extensions """ + kup = None + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual('ku_csr', self.cahandler._kue_generate(kup, 'ku_csr')) + self.assertIn('INFO:test_a2c:CAhandler._kue_generate() with data from csr', lcm.output) + + def test_141__kue_generate(self): + """ CAhandler._kue_generate() - kup csr_extensions """ + kup = 4 + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual('keyEncipherment', self.cahandler._kue_generate(kup, 'ku_csr')) + self.assertIn('INFO:test_a2c:CAhandler._kue_generate() with data from template', lcm.output) + + def test_142__kue_generate(self): + """ CAhandler._kue_generate() - kup 0 csr_extensions """ + kup = 0 + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.assertEqual('ku_csr', self.cahandler._kue_generate(kup, 'ku_csr')) + self.assertIn('INFO:test_a2c:CAhandler._kue_generate() with data from csr', lcm.output) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_143___keyusage_generate(self, mock_kuegen): + """ key usage generate - keyUse in template_dic but not kuCritical """ + template_dic = {'keyUse': {'foo': 'bar'}} + csr_extensions_dic = {} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_144___keyusage_generate(self, mock_kuegen): + """ key usage generate - keyUse in template_dic kuCritical string """ + template_dic = {'keyUse': 'foo', 'kuCritical': '1'} + csr_extensions_dic = {} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((True, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_145___keyusage_generate(self, mock_kuegen): + """ key usage generate - keyUse in template_dic kuCritical int """ + template_dic = {'keyUse': 'foo', 'kuCritical': 1} + csr_extensions_dic = {} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((True, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_146___keyusage_generate(self, mock_kuegen): + """ key usage generate - keyUse in template_dic kuCritical string 0 """ + template_dic = {'keyUse': 'foo', 'kuCritical': '0'} + csr_extensions_dic = {} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_147___keyusage_generate(self, mock_kuegen): + """ key usage generate - keyUse in template_dic kuCritical string 0 """ + template_dic = {'keyUse': 'foo', 'kuCritical': 0} + csr_extensions_dic = {} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_147___keyusage_generate(self, mock_kuegen): + """ key usage generate - keyUse in template_dic kuCritical triggers exception """ + template_dic = {'keyUse': 'foo', 'kuCritical': 'to fail'} + csr_extensions_dic = {} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_148___keyusage_generate(self, mock_kuegen): + """ key usage generate - keyUse extension dic """ + template_dic = {} + csr_keyusage = Mock() + csr_keyusage.__str__ = Mock(return_value='foo') + csr_extensions_dic = {'keyUsage': csr_keyusage} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') + def test_143___keyusage_generate(self, mock_kuegen): + """ key usage generate - empty emplate dic and empty CSR dic """ + template_dic = {} + csr_extensions_dic = {} + mock_kuegen.return_value = 'kue_string' + self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) def test_139__subject_modify(self): """ CAhandler._subject_modify() empty dn_dic """ @@ -1108,212 +1202,6 @@ def test_144__subject_modify(self): self.assertEqual('or', rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_145__subject_modify(self): - """ CAhandler._subject_modify() c, st, l, o included """ - dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st', 'localityName': 'lo', 'organizationName': 'or', 'organizationalUnitName': 'ou'} - subject = Mock() - subject.CN = 'cn' - subject.countryName = None - subject.stateOrProvinceName = None - subject.localityName = None - subject.organizationName = None - subject.organizationalUnitName = None - rc_obj = self.cahandler._subject_modify(subject, dn_dic) - self.assertEqual('cn', rc_obj.CN) - self.assertEqual('co', rc_obj.countryName) - self.assertEqual('st', rc_obj.stateOrProvinceName) - self.assertEqual('lo', rc_obj.localityName) - self.assertEqual('or', rc_obj.organizationName) - self.assertEqual('ou', rc_obj.organizationalUnitName) - - @patch('OpenSSL.crypto.X509Extension') - def test_146__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - empty template """ - template_dic = {} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'digitalSignature,keyEncipherment'), (b'basicConstraints', True, b'CA:FALSE'), (b'extendedKeyUsage', False, b'serverAuth')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_147__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - wrong template """ - template_dic = {'foo': 'bar'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_148__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - eKeyUse without ekuCritical """ - template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'extendedKeyUsage', False, b'eKeyUse')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_149__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - eKeyUse with ekuCritical 0 """ - template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse', 'ekuCritical': '0'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'extendedKeyUsage', False, b'eKeyUse')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_150__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - eKeyUse with ekuCritical 1 """ - template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse', 'ekuCritical': '1'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'extendedKeyUsage', True, b'eKeyUse')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_151__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - eKeyUse with ekuCritical string """ - template_dic = {'foo': 'bar', 'eKeyUse': 'eKeyUse', 'ekuCritical': 'string'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'extendedKeyUsage', False, b'eKeyUse')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') - @patch('OpenSSL.crypto.X509Extension') - def test_152__extension_list_generate(self, mock_crypto, mock_kue): - """ CAhandler._extension_list_generate() - KeyUse without kuCritical """ - template_dic = {'foo': 'bar', 'keyUse': 'keyUse'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - mock_kue.return_value = 'kue' - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', False, b'kue')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') - @patch('OpenSSL.crypto.X509Extension') - def test_153__extension_list_generate(self, mock_crypto, mock_kue): - """ CAhandler._extension_list_generate() - KeyUse with kuCritical 0 """ - template_dic = {'foo': 'bar', 'keyUse': 'keyUse', 'kuCritical': '0'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - mock_kue.return_value = 'kue' - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', False, b'kue')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') - @patch('OpenSSL.crypto.X509Extension') - def test_154__extension_list_generate(self, mock_crypto, mock_kue): - """ CAhandler._extension_list_generate() - KeyUse with kuCritical 1 """ - template_dic = {'foo': 'bar', 'keyUse': 'keyUse', 'kuCritical': '1'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - mock_kue.return_value = 'kue' - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'kue')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') - @patch('OpenSSL.crypto.X509Extension') - def test_155__extension_list_generate(self, mock_crypto, mock_kue): - """ CAhandler._extension_list_generate() - KeyUse with kuCritical string """ - template_dic = {'foo': 'bar', 'keyUse': 'keyUse', 'kuCritical': 'string'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - mock_kue.return_value = 'kue' - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', False, b'kue')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_156__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - eKeyUse with crlDist """ - template_dic = {'foo': 'bar', 'crlDist': 'crlDist'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'crlDistributionPoints', False, b'crlDist')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_157__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - eKeyUse with crlDist but no value """ - template_dic = {'foo': 'bar', 'crlDist': None} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_158__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - basicConstrains without bcCritical """ - template_dic = {'foo': 'bar', 'ca': '2'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'basicConstraints', False, b'CA:FALSE')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_159__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - basicConstrains with bcCritical 0 """ - template_dic = {'foo': 'bar', 'ca': '2', 'bcCritical': '0'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'basicConstraints', False, b'CA:FALSE')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_160__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - basicConstrains with bcCritical 1 """ - template_dic = {'foo': 'bar', 'ca': '2', 'bcCritical': '1'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'basicConstraints', True, b'CA:FALSE')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_161__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - basicConstrains with bcCritical string """ - template_dic = {'foo': 'bar', 'ca': '2', 'bcCritical': 'string'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'basicConstraints', False, b'CA:FALSE')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_162__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - basicConstrains with ca 1 """ - template_dic = {'foo': 'bar', 'ca': '1', 'bcCritical': '1'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'basicConstraints', True, b'CA:TRUE')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - - @patch('OpenSSL.crypto.X509Extension') - def test_163__extension_list_generate(self, mock_crypto): - """ CAhandler._extension_list_generate() - basicConstrains with ca 0 """ - template_dic = {'foo': 'bar', 'ca': '0', 'bcCritical': '1'} - cert = 'cert' - ca_cert = 'cacert' - mock_crypto.side_effect = return_input - result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always')] - self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert)) - @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_load') def test_164__enter__(self, mock_cfg): """ test enter """ @@ -1649,6 +1537,66 @@ def test_184_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo self.assertEqual((None, 'foofoo', 'foo', None), self.cahandler.enroll('csr')) self.assertIn('INFO:test_a2c:modify subject with template data', lcm.output) + def test_143___extended_keyusage_generate(self): + """ _extended_keyusage_generate template dic and csr_extensions_dic are empty """ + template_dic = {} + csr_extensions_dic = {} + self.assertEqual((False, None), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_144___extended_keyusage_generate(self): + """ _extended_keyusage_generate template dic eKeyUse in template not critical """ + template_dic = {'eKeyUse': 'eKeyUse'} + csr_extensions_dic = {} + self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_145___extended_keyusage_generate(self): + """ _extended_keyusage_generate template dic eKeyUse in template critical string """ + template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': '1'} + csr_extensions_dic = {} + self.assertEqual((True, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_146__extended_keyusage_generate(self): + """ _extended_keyusage_generate template dic eKeyUse in template critical in """ + template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': 1} + csr_extensions_dic = {} + self.assertEqual((True, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_147___extended_keyusage_generate(self): + """ _extended_keyusage_generate template dic eKeyUse in template critical zero """ + template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': '0'} + csr_extensions_dic = {} + self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_148___extended_keyusage_generate(self): + """ _extended_keyusage_generate template dic eKeyUse in template critical int zero """ + template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': 0} + csr_extensions_dic = {} + self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_149___extended_keyusage_generate(self): + """ _extended_keyusage_generate template dic eKeyUse in template convert to int fail """ + template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': 'convertfail'} + csr_extensions_dic = {} + self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_150___extended_keyusage_generate(self): + """ _extended_keyusage_generate extendedKeyUsage in csr_extensions_dic criticial true """ + template_dic = {} + eku_ext = Mock() + eku_ext.get_critical = Mock(return_value=True) + eku_ext.__str__ = Mock(return_value='eku') + csr_extensions_dic = {'extendedKeyUsage': eku_ext} + self.assertEqual((True, 'eku'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + + def test_151___extended_keyusage_generate(self): + """ _extended_keyusage_generate extendedKeyUsage in csr_extensions_dic criticial false """ + template_dic = {} + eku_ext = Mock() + eku_ext.get_critical = Mock(return_value=False) + eku_ext.__str__ = Mock(return_value='eku') + csr_extensions_dic = {'extendedKeyUsage': eku_ext} + self.assertEqual((False, 'eku'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + if __name__ == '__main__': unittest.main() From 8afc6d143d232eb48a79616a03acdaecb0e13115 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 6 Jun 2021 15:24:16 +0200 Subject: [PATCH 37/51] [tst] unittests xca_handler.py --- README.md | 1 - examples/ca_handler/xca_ca_handler.py | 3 +- test/test_xca_ca_handler.py | 373 +++++++++++++++++++++++--- 3 files changed, 335 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index f3acce19..55b17dca 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ [![Codecov main](https://img.shields.io/codecov/c/gh/grindsa/acme2certifier/branch/master?label=test%20coverage%20master)](https://app.codecov.io/gh/grindsa/acme2certifier/branch/master) [![Codecov devel](https://img.shields.io/codecov/c/gh/grindsa/acme2certifier/branch/devel?label=test%20coverage%20devel)](https://app.codecov.io/gh/grindsa/acme2certifier/branch/devel) - acme2certifier is development project to create an ACME protocol proxy. Main intention is to provide ACME services on CA servers which do not support this protocol yet. It consists of two libraries: diff --git a/examples/ca_handler/xca_ca_handler.py b/examples/ca_handler/xca_ca_handler.py index 98bb72c8..0bb27010 100644 --- a/examples/ca_handler/xca_ca_handler.py +++ b/examples/ca_handler/xca_ca_handler.py @@ -343,7 +343,7 @@ def _extended_keyusage_generate(self, template_dic, csr_extensions_dic=None): else: ekuc = False eku_string = template_dic['eKeyUse'] - + elif 'extendedKeyUsage' in csr_extensions_dic: # eku usage in extention try: @@ -779,7 +779,6 @@ def _extension_list_generate(self, template_dic, cert, ca_cert, csr_extensions_l csr_extensions_dic = {} for ext in csr_extensions_list: csr_extensions_dic[convert_byte_to_string(ext.get_short_name())] = ext - print(csr_extensions_dic) if template_dic: extension_list = [ diff --git a/test/test_xca_ca_handler.py b/test/test_xca_ca_handler.py index 1d9d0923..40a88ccf 100644 --- a/test/test_xca_ca_handler.py +++ b/test/test_xca_ca_handler.py @@ -1069,7 +1069,7 @@ def test_147___keyusage_generate(self, mock_kuegen): self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') - def test_147___keyusage_generate(self, mock_kuegen): + def test_148___keyusage_generate(self, mock_kuegen): """ key usage generate - keyUse in template_dic kuCritical triggers exception """ template_dic = {'keyUse': 'foo', 'kuCritical': 'to fail'} csr_extensions_dic = {} @@ -1077,7 +1077,7 @@ def test_147___keyusage_generate(self, mock_kuegen): self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') - def test_148___keyusage_generate(self, mock_kuegen): + def test_149___keyusage_generate(self, mock_kuegen): """ key usage generate - keyUse extension dic """ template_dic = {} csr_keyusage = Mock() @@ -1087,14 +1087,14 @@ def test_148___keyusage_generate(self, mock_kuegen): self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) @patch('examples.ca_handler.xca_ca_handler.CAhandler._kue_generate') - def test_143___keyusage_generate(self, mock_kuegen): + def test_150___keyusage_generate(self, mock_kuegen): """ key usage generate - empty emplate dic and empty CSR dic """ template_dic = {} csr_extensions_dic = {} mock_kuegen.return_value = 'kue_string' self.assertEqual((False, 'kue_string'), self.cahandler._keyusage_generate(template_dic, csr_extensions_dic)) - def test_139__subject_modify(self): + def test_151__subject_modify(self): """ CAhandler._subject_modify() empty dn_dic """ dn_dic = {} subject = Mock() @@ -1112,7 +1112,7 @@ def test_139__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_140__subject_modify(self): + def test_152__subject_modify(self): """ CAhandler._subject_modify() wrong dn_dic """ dn_dic = {'foo': 'bar'} subject = Mock() @@ -1130,7 +1130,7 @@ def test_140__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_141__subject_modify(self): + def test_153__subject_modify(self): """ CAhandler._subject_modify() c included """ dn_dic = {'foo': 'bar', 'countryName': 'co'} subject = Mock() @@ -1148,7 +1148,7 @@ def test_141__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_142__subject_modify(self): + def test_154__subject_modify(self): """ CAhandler._subject_modify() c, st included """ dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st'} subject = Mock() @@ -1166,7 +1166,7 @@ def test_142__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_143__subject_modify(self): + def test_155__subject_modify(self): """ CAhandler._subject_modify() c, st, l included """ dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st', 'localityName': 'lo'} subject = Mock() @@ -1184,7 +1184,7 @@ def test_143__subject_modify(self): self.assertFalse(rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) - def test_144__subject_modify(self): + def test_156__subject_modify(self): """ CAhandler._subject_modify() c, st, l, o included """ dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st', 'localityName': 'lo', 'organizationName': 'or'} subject = Mock() @@ -1202,36 +1202,54 @@ def test_144__subject_modify(self): self.assertEqual('or', rc_obj.organizationName) self.assertFalse(rc_obj.organizationalUnitName) + def test_157__subject_modify(self): + """ CAhandler._subject_modify() c, st, l, o included """ + dn_dic = {'foo': 'bar', 'countryName': 'co', 'stateOrProvinceName': 'st', 'localityName': 'lo', 'organizationName': 'or', 'organizationalUnitName': 'ou'} + subject = Mock() + subject.CN = 'cn' + subject.countryName = None + subject.stateOrProvinceName = None + subject.localityName = None + subject.organizationName = None + subject.organizationalUnitName = None + rc_obj = self.cahandler._subject_modify(subject, dn_dic) + self.assertEqual('cn', rc_obj.CN) + self.assertEqual('co', rc_obj.countryName) + self.assertEqual('st', rc_obj.stateOrProvinceName) + self.assertEqual('lo', rc_obj.localityName) + self.assertEqual('or', rc_obj.organizationName) + self.assertEqual('ou', rc_obj.organizationalUnitName) + @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_load') - def test_164__enter__(self, mock_cfg): + def test_158__enter__(self, mock_cfg): """ test enter """ mock_cfg.return_value = True self.cahandler.__enter__() self.assertTrue(mock_cfg.called) @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_load') - def test_165__enter__(self, mock_cfg): + def test_159__enter__(self, mock_cfg): """ test enter """ self.cahandler.xdb_file = self.dir_path + '/ca/est_proxy.xdb' mock_cfg.return_value = True self.cahandler.__enter__() self.assertFalse(mock_cfg.called) - def test_166_trigger(self): + def test_160_trigger(self): """ test trigger """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) - def test_167_poll(self): + def test_161_poll(self): """ test poll """ self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier','csr')) - def test_168_stub_func(self): + def test_162_stub_func(self): """ test stubfunc """ self.assertEqual('parameter', self.cahandler._stub_func('parameter')) @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_insert') @patch('examples.ca_handler.xca_ca_handler.CAhandler._item_insert') - def test_169__store_cert(self, mock_i_insert, mock_c_insert): + def test_163__store_cert(self, mock_i_insert, mock_c_insert): """ test insert """ mock_i_insert.return_value = 1 mock_c_insert.return_value = 2 @@ -1242,7 +1260,7 @@ def test_169__store_cert(self, mock_i_insert, mock_c_insert): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_170_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_164_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search """ mock_dicfrow.return_value = {'foo': 'bar'} mock_open.return_value = True @@ -1256,7 +1274,7 @@ def test_170_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_171_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_165_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search dicfromrow throws exception """ mock_dicfrow.side_effect = Exception('exc_dicfromrow') mock_open.return_value = True @@ -1270,7 +1288,7 @@ def test_171_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_172_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_166_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search """ mock_dicfrow.return_value = {'foo': 'bar'} mock_open.return_value = True @@ -1284,7 +1302,7 @@ def test_172_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.dict_from_row') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_close') @patch('examples.ca_handler.xca_ca_handler.CAhandler._db_open') - def test_173_revocation_search(self, mock_open, mock_close, mock_dicfrow): + def test_167_revocation_search(self, mock_open, mock_close, mock_dicfrow): """ revocation search dicfromrow throws exception """ mock_dicfrow.side_effect = Exception('exc_dicfromrow') mock_open.return_value = True @@ -1297,7 +1315,7 @@ def test_173_revocation_search(self, mock_open, mock_close, mock_dicfrow): @patch('examples.ca_handler.xca_ca_handler.CAhandler._cert_insert') @patch('examples.ca_handler.xca_ca_handler.CAhandler._item_insert') - def test_174__store_cert(self, mock_i_insert, mock_c_insert): + def test_168__store_cert(self, mock_i_insert, mock_c_insert): """ test insert """ mock_i_insert.return_value = 1 mock_c_insert.return_value = 2 @@ -1306,14 +1324,14 @@ def test_174__store_cert(self, mock_i_insert, mock_c_insert): self.assertTrue(mock_c_insert.called) @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_175_enroll(self, mock_chk): + def test_169_enroll(self, mock_chk): """ enroll test error returned from config_check""" mock_chk.return_value = 'error' self.assertEqual(('error', None, None, None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_176_enroll(self, mock_chk, mock_nameget): + def test_170_enroll(self, mock_chk, mock_nameget): """ enroll test error returned no request name returned """ mock_chk.return_value = None mock_nameget.return_value = None @@ -1323,7 +1341,7 @@ def test_176_enroll(self, mock_chk, mock_nameget): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_177_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + def test_171_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): """ enroll test error returned from ca_load failed """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1335,7 +1353,7 @@ def test_177_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_178_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + def test_172_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): """ enroll test error returned from ca_load failed """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1347,7 +1365,7 @@ def test_178_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_179_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): + def test_173_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): """ enroll test error returned from ca_load failed """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1366,7 +1384,7 @@ def test_179_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load): @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_180_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + def test_174_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): """ enroll test """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1399,7 +1417,7 @@ def test_180_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_181_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + def test_175_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): """ enroll test - default cert validity """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1433,7 +1451,7 @@ def test_181_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_182_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): + def test_176_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_cbs, mock_b64e): """ enroll test - rewrite CN """ mock_chk.return_value = None mock_nameget.return_value = 'reqname' @@ -1469,7 +1487,7 @@ def test_182_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_183_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): + def test_177_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): """ enroll test - template load validity """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1509,7 +1527,7 @@ def test_183_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo @patch('examples.ca_handler.xca_ca_handler.CAhandler._csr_import') @patch('examples.ca_handler.xca_ca_handler.CAhandler._requestname_get') @patch('examples.ca_handler.xca_ca_handler.CAhandler._config_check') - def test_184_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): + def test_178_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mock_csr_load, mock_509, mock_ext_get, mock_store, mock_dump, mock_tmp_load, mock_cbs, mock_b64e): """ enroll test - template load validity """ mock_chk.return_value = None mock_nameget.return_value = 'name' @@ -1537,49 +1555,49 @@ def test_184_enroll(self, mock_chk, mock_nameget, mock_csrinfo, mock_ca_load, mo self.assertEqual((None, 'foofoo', 'foo', None), self.cahandler.enroll('csr')) self.assertIn('INFO:test_a2c:modify subject with template data', lcm.output) - def test_143___extended_keyusage_generate(self): + def test_179___extended_keyusage_generate(self): """ _extended_keyusage_generate template dic and csr_extensions_dic are empty """ template_dic = {} csr_extensions_dic = {} self.assertEqual((False, None), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_144___extended_keyusage_generate(self): + def test_180___extended_keyusage_generate(self): """ _extended_keyusage_generate template dic eKeyUse in template not critical """ template_dic = {'eKeyUse': 'eKeyUse'} csr_extensions_dic = {} self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_145___extended_keyusage_generate(self): + def test_181___extended_keyusage_generate(self): """ _extended_keyusage_generate template dic eKeyUse in template critical string """ template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': '1'} csr_extensions_dic = {} self.assertEqual((True, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_146__extended_keyusage_generate(self): + def test_182__extended_keyusage_generate(self): """ _extended_keyusage_generate template dic eKeyUse in template critical in """ template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': 1} csr_extensions_dic = {} self.assertEqual((True, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_147___extended_keyusage_generate(self): + def test_183___extended_keyusage_generate(self): """ _extended_keyusage_generate template dic eKeyUse in template critical zero """ template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': '0'} csr_extensions_dic = {} self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_148___extended_keyusage_generate(self): + def test_184___extended_keyusage_generate(self): """ _extended_keyusage_generate template dic eKeyUse in template critical int zero """ template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': 0} csr_extensions_dic = {} self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_149___extended_keyusage_generate(self): + def test_185___extended_keyusage_generate(self): """ _extended_keyusage_generate template dic eKeyUse in template convert to int fail """ template_dic = {'eKeyUse': 'eKeyUse', 'ekuCritical': 'convertfail'} csr_extensions_dic = {} self.assertEqual((False, 'eKeyUse'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_150___extended_keyusage_generate(self): + def test_186___extended_keyusage_generate(self): """ _extended_keyusage_generate extendedKeyUsage in csr_extensions_dic criticial true """ template_dic = {} eku_ext = Mock() @@ -1588,7 +1606,7 @@ def test_150___extended_keyusage_generate(self): csr_extensions_dic = {'extendedKeyUsage': eku_ext} self.assertEqual((True, 'eku'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) - def test_151___extended_keyusage_generate(self): + def test_187___extended_keyusage_generate(self): """ _extended_keyusage_generate extendedKeyUsage in csr_extensions_dic criticial false """ template_dic = {} eku_ext = Mock() @@ -1597,6 +1615,283 @@ def test_151___extended_keyusage_generate(self): csr_extensions_dic = {'extendedKeyUsage': eku_ext} self.assertEqual((False, 'eku'), self.cahandler._extended_keyusage_generate(template_dic, csr_extensions_dic)) + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_188__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - empty template """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, 'mock_eku') + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'digitalSignature,keyEncipherment'), (b'basicConstraints', True, b'CA:FALSE'), (b'extendedKeyUsage', False, b'serverAuth')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertFalse(mock_ku.called) + self.assertFalse(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_189__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - template with bogus values """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, 'mock_eku') + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'foo': 'bar'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'extendedKeyUsage', True, b'mock_eku')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_190__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - template with bogus values no ekustring returned """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'foo': 'bar'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_191__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - template with bogus values no ekustring returned """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'crlDist': 'crlDist'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'crlDistributionPoints', False, b'crlDist')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_192__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - basic constrain CA: 1 """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': '1'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'basicConstraints', False, b'CA:TRUE')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_193__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - basic constrain CA: 2 """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': '2'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'basicConstraints', False, b'CA:FALSE')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_194__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - basic constrain CA: unknown """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': 'other'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_195__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - bccritial '1' """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': '2', 'bcCritical': '1'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'basicConstraints', True, b'CA:FALSE')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_196__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - bccritial 1 """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': '2', 'bcCritical': 1} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'basicConstraints', True, b'CA:FALSE')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_197__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - bccritial '0' """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': '2', 'bcCritical': '0'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'basicConstraints', False, b'CA:FALSE')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_198__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - bccritial 0 """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': '2', 'bcCritical': 0} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'basicConstraints', False, b'CA:FALSE')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + + @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') + @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') + @patch('OpenSSL.crypto.X509Extension') + def test_199__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): + """ CAhandler._extension_list_generate() - bccritial unknown """ + mock_ku.return_value = (True, 'mock_ku') + mock_eku.return_value = (True, None) + ext2 = Mock() + ext2.get_short_name = Mock(return_value='get_short_name1') + ext2.__str__ = Mock(return_value='short_name1') + ext3 = Mock() + ext3.get_short_name = Mock(return_value='get_short_name2') + ext3.__str__ = Mock(return_value='short_name3') + csr_extension_list = [ext2, ext3] + template_dic = {'ca': '2', 'bcCritical': 'unknown'} + cert = 'cert' + ca_cert = 'cacert' + mock_crypto.side_effect = return_input + result = [(b'subjectKeyIdentifier', False, b'hash'), (b'authorityKeyIdentifier', False, b'keyid:always'), (b'keyUsage', True, b'mock_ku'), (b'basicConstraints', False, b'CA:FALSE')] + self.assertEqual(result, self.cahandler._extension_list_generate(template_dic, cert, ca_cert, csr_extension_list)) + self.assertTrue(mock_ku.called) + self.assertTrue(mock_eku.called) + if __name__ == '__main__': unittest.main() From 66f733d128a0ffe0026d5bcd49d898ce24f44a5f Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 6 Jun 2021 19:14:44 +0200 Subject: [PATCH 38/51] [feat] environment variables in nclm_ca_handler.py --- docs/cmp.md | 4 +- docs/nclm.md | 2 + examples/ca_handler/nclm_ca_handler.py | 15 ++ test/test_msca_handler.py | 4 +- test/test_nclm_ca_handler.py | 200 ++++++++++++++++--------- test/test_xca_ca_handler.py | 1 - 6 files changed, 153 insertions(+), 73 deletions(-) diff --git a/docs/cmp.md b/docs/cmp.md index 50bb9a9b..48e24564 100644 --- a/docs/cmp.md +++ b/docs/cmp.md @@ -32,7 +32,9 @@ acme/cmp/WindowsCMPOpenSSL/openssl.exe cmp -cmd ir -server 192.168.14.137:8080 - |-server| 192.168.14.137:8080| address and port of CMPv2 server| |-path | pkix/ | path on CMPv2 server | |-ref | 1234 | reference number used for authentication towards CMPv2 server | -|-secret | pass:xxx | secred used for authentication towards CMPv2 server | +|-ref_variable | CMPV2_REF | name of the environment variable containing the reference number used for authentication (a configured `ref` parameter in acme_srv.cfg takes precedence) +|-secret | pass:xxx | secret used for authentication towards CMPv2 server | +|-secret_variable | CMPV2_SECRET | name of the environment variable containing the authentication secret (a configured `secret` parameter in acme_srv.cfg takes precedence) |-recipient | "/C=DE/CN=tst_sub_ca" | dn of issuing ca | |-newkey | pubkey.pem | public key extracted from CSR | |-cert | ra_cert.pem | public key of local registration authority | diff --git a/docs/nclm.md b/docs/nclm.md index c5a6e346..f8ed93a1 100644 --- a/docs/nclm.md +++ b/docs/nclm.md @@ -31,7 +31,9 @@ template_name: - api_host - URL of the Certifier-REST service - api_user - REST user +- api_user_variable - *optional* - name of the environment variable containing the REST username (a configured `api_user` parameter in acme_srv.cfg takes precedence) - api_password - password for REST user +- api_password_variable - *optional* - name of the environment variable containing the password for the REST user (a configured `api_password` parameter in acme_srv.cfg takes precedence) - ca_bundle - optional - certificate bundle needed to validate the server certificate - can be True/False or a filename (default: True) - ca_name - name of the CA used to enroll certificates - tsg_name - name of the target system group to store the certificates diff --git a/examples/ca_handler/nclm_ca_handler.py b/examples/ca_handler/nclm_ca_handler.py index 12ee2043..709413c1 100644 --- a/examples/ca_handler/nclm_ca_handler.py +++ b/examples/ca_handler/nclm_ca_handler.py @@ -3,6 +3,7 @@ """ ca handler for "NetGuard Certificate Lifecycle Manager" via REST-API class """ from __future__ import print_function # import json +import os import sys import time import requests @@ -192,9 +193,23 @@ def _config_load(self): if 'CAhandler' in config_dic: if 'api_host' in config_dic['CAhandler']: self.api_host = config_dic['CAhandler']['api_host'] + if 'api_user_variable' in config_dic['CAhandler']: + try: + self.credential_dic['api_user'] = os.environ[config_dic['CAhandler']['api_user_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load user_variable:{0}'.format(err)) if 'api_user' in config_dic['CAhandler']: + if self.credential_dic['api_user']: + self.logger.info('CAhandler._config_load() overwrite api_user') self.credential_dic['api_user'] = config_dic['CAhandler']['api_user'] + if 'api_password_variable' in config_dic['CAhandler']: + try: + self.credential_dic['api_password'] = os.environ[config_dic['CAhandler']['api_password_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load password_variable:{0}'.format(err)) if 'api_password' in config_dic['CAhandler']: + if self.credential_dic['api_password']: + self.logger.info('CAhandler._config_load() overwrite api_password') self.credential_dic['api_password'] = config_dic['CAhandler']['api_password'] if 'ca_name' in config_dic['CAhandler']: self.ca_name = config_dic['CAhandler']['ca_name'] diff --git a/test/test_msca_handler.py b/test/test_msca_handler.py index 4581f037..ae7aa1b9 100644 --- a/test/test_msca_handler.py +++ b/test/test_msca_handler.py @@ -253,11 +253,11 @@ def test_022_config_load(self, mock_load_cfg): @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') def test_023_config_load(self, mock_load_cfg): """ test _config_load - load with user variable which does not exist """ - mock_load_cfg.return_value = {'CAhandler': {'host_variable': 'doesnotexist'}} + mock_load_cfg.return_value = {'CAhandler': {'user_variable': 'doesnotexist'}} with self.assertLogs('test_a2c', level='INFO') as lcm: self.cahandler._config_load() self.assertFalse(self.cahandler.user) - self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load host_variable:'doesnotexist'", lcm.output) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load user_variable:'doesnotexist'", lcm.output) @patch.dict('os.environ', {'user_variable': 'user'}) @patch('examples.ca_handler.mscertsrv_ca_handler.load_config') diff --git a/test/test_nclm_ca_handler.py b/test/test_nclm_ca_handler.py index e3bd4f62..378f9eb0 100644 --- a/test/test_nclm_ca_handler.py +++ b/test/test_nclm_ca_handler.py @@ -579,10 +579,72 @@ def test_049_config_load(self, mock_load_cfg): self.assertFalse(self.cahandler.ca_name) self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) + @patch.dict('os.environ', {'api_user_var': 'user_var'}) + @patch('examples.ca_handler.nclm_ca_handler.load_config') + def test_050_config_load(self, mock_load_cfg): + """ CAhandler._config_load load username from variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_user_variable': 'api_user_var'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_host) + self.assertEqual({'api_user': 'user_var', 'api_password': None}, self.cahandler.credential_dic) + + @patch.dict('os.environ', {'api_user_var': 'user_var'}) + @patch('examples.ca_handler.nclm_ca_handler.load_config') + def test_051_config_load(self, mock_load_cfg): + """ CAhandler._config_load load username from non existing """ + mock_load_cfg.return_value = {'CAhandler': {'api_user_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_host) + self.assertEqual({'api_user': None, 'api_password': None}, self.cahandler.credential_dic) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load user_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'api_user_var': 'user_var'}) + @patch('examples.ca_handler.nclm_ca_handler.load_config') + def test_052_config_load(self, mock_load_cfg): + """ CAhandler._config_load load username from wich gets overwritten from cfg-file """ + mock_load_cfg.return_value = {'CAhandler': {'api_user_variable': 'api_user_var', 'api_user': 'api_user'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_host) + self.assertEqual({'api_user': 'api_user', 'api_password': None}, self.cahandler.credential_dic) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite api_user', lcm.output) + + @patch.dict('os.environ', {'api_password_var': 'password_var'}) + @patch('examples.ca_handler.nclm_ca_handler.load_config') + def test_053_config_load(self, mock_load_cfg): + """ CAhandler._config_load load password from variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_password_variable': 'api_password_var'}} + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_host) + self.assertEqual({'api_user': None, 'api_password': 'password_var'}, self.cahandler.credential_dic) + + @patch.dict('os.environ', {'api_password_var': 'password_var'}) + @patch('examples.ca_handler.nclm_ca_handler.load_config') + def test_054_config_load(self, mock_load_cfg): + """ CAhandler._config_load load password from non existing variable """ + mock_load_cfg.return_value = {'CAhandler': {'api_password_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_host) + self.assertEqual({'api_user': None, 'api_password': None}, self.cahandler.credential_dic) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load password_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'api_password_var': 'password_var'}) + @patch('examples.ca_handler.nclm_ca_handler.load_config') + def test_055_config_load(self, mock_load_cfg): + """ CAhandler._config_load load password from variable which gets overwritten """ + mock_load_cfg.return_value = {'CAhandler': {'api_password_variable': 'api_password_var', 'api_password': 'api_password'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.api_host) + self.assertEqual({'api_password': 'api_password', 'api_user': None}, self.cahandler.credential_dic) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite api_password', lcm.output) + @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_050__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_056__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - all ok """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -592,7 +654,7 @@ def test_050__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_051__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_057__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - no requestID in list """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -602,7 +664,7 @@ def test_051__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_052__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_058__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - cn in mock_unureq not correctly ordered """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -612,7 +674,7 @@ def test_052__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_053__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_059__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - empty subjectName """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -622,7 +684,7 @@ def test_053__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_054__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_060__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - no subjectName """ mock_utsnow.return_value = 1000 mock_uts.return_value = 900 @@ -632,7 +694,7 @@ def test_054__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_055__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): + def test_061__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): """ CAhandler._csr_id_lookup - requests to old """ mock_utsnow.return_value = 1000 mock_uts.return_value = 100 @@ -644,7 +706,7 @@ def test_055__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts): @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_056__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_062__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn one san """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -661,7 +723,7 @@ def test_056__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_057__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_063__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn two sans """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -678,7 +740,7 @@ def test_057__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_058__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_064__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn two sans to be reordered """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -695,7 +757,7 @@ def test_058__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_059__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_065__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn two sans to be reordered """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -712,7 +774,7 @@ def test_059__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_060__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_066__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn no requestID """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -729,7 +791,7 @@ def test_060__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_061__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_067__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn sans are not matching """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -746,7 +808,7 @@ def test_061__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_062__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_068__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn no pkcs10 """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -763,7 +825,7 @@ def test_062__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, @patch('examples.ca_handler.nclm_ca_handler.date_to_uts_utc') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._unusedrequests_get') @patch('examples.ca_handler.nclm_ca_handler.uts_now') - def test_063__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): + def test_069__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, mock_san): """ CAhandler._csr_id_lookup - no csr_cn request throws an exception """ self.cahandler.api_host = 'api_host' mock_utsnow.return_value = 1000 @@ -776,14 +838,14 @@ def test_063__csr_id_lookup(self, mock_utsnow, mock_unureq, mock_uts, mock_req, self.assertIn('ERROR:test_a2c:CAhandler._csr_id_lookup() returned error: exc_csr_id_lookup', lcm.output) @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') - def test_064__request_import(self, mock_req): + def test_070__request_import(self, mock_req): """ CAhandler._request_import """ self.cahandler.api_host = 'api_host' mock_req.return_value = 'foo' self.assertEqual('foo', self.cahandler._request_import('csr')) @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') - def test_065__request_import(self, mock_req): + def test_071__request_import(self, mock_req): """ CAhandler._request_import - req raises an exception """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('exc_req_import') @@ -792,7 +854,7 @@ def test_065__request_import(self, mock_req): self.assertIn('ERROR:test_a2c:CAhandler._request_import() returned error: exc_req_import', lcm.output) @patch('requests.get') - def test_066__unusedrequests_get(self, mock_req): + def test_072__unusedrequests_get(self, mock_req): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -801,7 +863,7 @@ def test_066__unusedrequests_get(self, mock_req): self.assertEqual({'foo': 'bar'}, self.cahandler._unusedrequests_get()) @patch('requests.get') - def test_067__unusedrequests_get(self, mock_req): + def test_073__unusedrequests_get(self, mock_req): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('exc_req_unused') @@ -810,7 +872,7 @@ def test_067__unusedrequests_get(self, mock_req): self.assertIn('ERROR:test_a2c:CAhandler._unusedrequests_get() returned error: exc_req_unused', lcm.output) @patch('requests.get') - def test_068__login(self, mock_get): + def test_074__login(self, mock_get): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -825,7 +887,7 @@ def test_068__login(self, mock_get): @patch('requests.post') @patch('requests.get') - def test_069__login(self, mock_get, mock_post): + def test_075__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get """ self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -839,7 +901,7 @@ def test_069__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_070__login(self, mock_get, mock_post): + def test_076__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without username""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -853,7 +915,7 @@ def test_070__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_071__login(self, mock_get, mock_post): + def test_077__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without username""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -870,7 +932,7 @@ def test_071__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_072__login(self, mock_get, mock_post): + def test_078__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without realms""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -884,7 +946,7 @@ def test_072__login(self, mock_get, mock_post): @patch('requests.post') @patch('requests.get') - def test_073__login(self, mock_get, mock_post): + def test_079__login(self, mock_get, mock_post): """ CAhandler._unusedrequests_get mock_post without access tooken""" self.cahandler.api_host = 'api_host' mockresponse1 = Mock() @@ -899,40 +961,40 @@ def test_073__login(self, mock_get, mock_post): self.assertFalse(self.cahandler.headers) self.assertIn('ERROR:test_a2c:CAhandler._login(): No token returned. Aborting...', lcm.output) - def test_074__san_compare(self): + def test_080__san_compare(self): """ CAhandler._san_compare all ok """ csr_san_list = ['foo:foo'] cert_san_list = {'foo': ['foo']} self.assertTrue(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_075__san_compare(self): + def test_081__san_compare(self): """ CAhandler._san_compare multiple """ csr_san_list = ['foo:foo', 'foo:bar'] cert_san_list = {'foo': ['foo', 'bar']} self.assertTrue(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_076__san_compare(self): + def test_082__san_compare(self): """ CAhandler._san_compare multiple """ csr_san_list = ['foo:foo,foo:bar'] cert_san_list = {'foo': ['foo', 'bar']} self.assertTrue(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_077__san_compare(self): + def test_083__san_compare(self): """ CAhandler._san_compare multiple """ csr_san_list = ['foo:foo,foo:bar1'] cert_san_list = {'foo': ['foo', 'bar']} self.assertFalse(self.cahandler._san_compare(csr_san_list, cert_san_list)) - def test_078_poll(self): + def test_084_poll(self): """ CAhandler.poll() """ self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) - def test_079_trigger(self): + def test_085_trigger(self): """ CAhandler.trigger() """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) @patch('requests.get') - def test_080___tsg_id_lookup(self, mock_get): + def test_086___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - all ok """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -943,7 +1005,7 @@ def test_080___tsg_id_lookup(self, mock_get): self.assertEqual({'name': 'name', 'id': 'id'}, self.cahandler.tsg_info_dic) @patch('requests.get') - def test_081___tsg_id_lookup(self, mock_get): + def test_087___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - multipe returned 1st matches """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -954,7 +1016,7 @@ def test_081___tsg_id_lookup(self, mock_get): self.assertEqual({'name': 'name', 'id': 'id'}, self.cahandler.tsg_info_dic) @patch('requests.get') - def test_082___tsg_id_lookup(self, mock_get): + def test_088___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - multipe returned 2nd matches """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -965,7 +1027,7 @@ def test_082___tsg_id_lookup(self, mock_get): self.assertEqual({'name': 'name', 'id': 'id'}, self.cahandler.tsg_info_dic) @patch('requests.get') - def test_083___tsg_id_lookup(self, mock_get): + def test_089___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - id is missing """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -978,7 +1040,7 @@ def test_083___tsg_id_lookup(self, mock_get): self.assertIn("ERROR:test_a2c:CAhandler._tsg_id_lookup() incomplete response: {'name': 'name'}", lcm.output) @patch('requests.get') - def test_084___tsg_id_lookup(self, mock_get): + def test_090___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - name is missing """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -991,7 +1053,7 @@ def test_084___tsg_id_lookup(self, mock_get): self.assertIn("ERROR:test_a2c:CAhandler._tsg_id_lookup() incomplete response: {'foo': 'bar', 'id': 'id'}", lcm.output) @patch('requests.get') - def test_085___tsg_id_lookup(self, mock_get): + def test_091___tsg_id_lookup(self, mock_get): """ CAhandler._tsg_id_lookup() - targetSystemGroups is missing """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1004,7 +1066,7 @@ def test_085___tsg_id_lookup(self, mock_get): self.assertIn('ERROR:test_a2c:CAhandler._tsg_id_lookup() no target-system-groups found for filter: name...', lcm.output) @patch('requests.get') - def test_086__tsg_id_lookup(self, mock_req): + def test_092__tsg_id_lookup(self, mock_req): """ CAhandler._request_import - req raises an exception """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('exc_tsg_id_lookup') @@ -1013,7 +1075,7 @@ def test_086__tsg_id_lookup(self, mock_req): self.assertIn('ERROR:test_a2c:CAhandler._tsg_id_lookup() returned error: exc_tsg_id_lookup', lcm.output) @patch('requests.get') - def test_087__template_id_lookup(self, mock_get): + def test_093__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - all ok """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1024,7 +1086,7 @@ def test_087__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': 10}, self.cahandler.template_info_dic) @patch('requests.get') - def test_088__template_id_lookup(self, mock_get): + def test_094__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - linkId None """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1035,7 +1097,7 @@ def test_088__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_089__template_id_lookup(self, mock_get): + def test_095__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - No linkId """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1046,7 +1108,7 @@ def test_089__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_090__template_id_lookup(self, mock_get): + def test_096__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no match in template names """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1057,7 +1119,7 @@ def test_090__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_091__template_id_lookup(self, mock_get): + def test_097__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - allowed false """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1068,7 +1130,7 @@ def test_091__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_092__template_id_lookup(self, mock_get): + def test_098__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - template in lower cases """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1079,7 +1141,7 @@ def test_092__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': 10}, self.cahandler.template_info_dic) @patch('requests.get') - def test_093__template_id_lookup(self, mock_get): + def test_099__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no template """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1090,7 +1152,7 @@ def test_093__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_094__template_id_lookup(self, mock_get): + def test_100__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no linktype """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1101,7 +1163,7 @@ def test_094__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_095__template_id_lookup(self, mock_get): + def test_101__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - empty list """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1112,7 +1174,7 @@ def test_095__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_096__template_id_lookup(self, mock_get): + def test_102__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - no items """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1123,7 +1185,7 @@ def test_096__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_097__template_id_lookup(self, mock_get): + def test_103__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - wrong dict """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1134,7 +1196,7 @@ def test_097__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_098__template_id_lookup(self, mock_get): + def test_104__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - wrong dict """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1145,7 +1207,7 @@ def test_098__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_099__template_id_lookup(self, mock_get): + def test_105__template_id_lookup(self, mock_get): """ CAhandler._template_id_lookup() - empty response """ self.cahandler.api_host = 'api_host' mockresponse = Mock() @@ -1156,7 +1218,7 @@ def test_099__template_id_lookup(self, mock_get): self.assertEqual({'name': 'template_name', 'id': None}, self.cahandler.template_info_dic) @patch('requests.get') - def test_100__template_id_lookup(self, mock_req): + def test_106__template_id_lookup(self, mock_req): """ CAhandler._cert_id_lookup() - request raises exception """ self.cahandler.api_host = 'api_host' mock_req.side_effect = Exception('req_exc') @@ -1170,7 +1232,7 @@ def test_100__template_id_lookup(self, mock_req): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_101__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_107__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter """ self.cahandler.__enter__() self.assertTrue(mock_load.called) @@ -1182,7 +1244,7 @@ def test_101__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_102__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_108__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with host already defined """ self.cahandler.api_host = 'api_host' self.cahandler.__enter__() @@ -1195,7 +1257,7 @@ def test_102__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_103__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_109__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with header defined """ self.cahandler.headers = 'header' self.cahandler.__enter__() @@ -1208,7 +1270,7 @@ def test_103__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_104__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_110__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with error defined """ self.cahandler.error = 'error' self.cahandler.__enter__() @@ -1221,7 +1283,7 @@ def test_104__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_105__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_111__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with tst_info_dic defined """ self.cahandler.tsg_info_dic = {'id': 'foo'} self.cahandler.__enter__() @@ -1234,7 +1296,7 @@ def test_105__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._config_check') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._login') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._tsg_id_lookup') - def test_106__enter__(self, mock_lookup, mock_login, mock_check, mock_load): + def test_112__enter__(self, mock_lookup, mock_login, mock_check, mock_load): """ test enter with error defined """ self.cahandler.tsg_info_dic = {'id': 'foo'} self.cahandler.error = 'error' @@ -1246,7 +1308,7 @@ def test_106__enter__(self, mock_lookup, mock_login, mock_check, mock_load): @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') @patch('requests.get') - def test_107_revoke(self, mock_get, mock_serial): + def test_113_revoke(self, mock_get, mock_serial): """ test revoke empty certificate list has been returned """ self.cahandler.api_host = 'api_host' mock_serial.return_value = 11 @@ -1257,7 +1319,7 @@ def test_107_revoke(self, mock_get, mock_serial): @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') @patch('requests.get') - def test_108_revoke(self, mock_get, mock_serial): + def test_114_revoke(self, mock_get, mock_serial): """ test revoke request get aborted with exception """ self.cahandler.api_host = 'api_host' mock_serial.return_value = 11 @@ -1268,7 +1330,7 @@ def test_108_revoke(self, mock_get, mock_serial): @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') @patch('requests.get') - def test_109_revoke(self, mock_get, mock_serial): + def test_115_revoke(self, mock_get, mock_serial): """ test revoke certificates in certificate_list but content is bogus """ self.cahandler.api_host = 'api_host' mock_serial.return_value = 11 @@ -1280,7 +1342,7 @@ def test_109_revoke(self, mock_get, mock_serial): @patch('requests.post') @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') @patch('requests.get') - def test_110_revoke(self, mock_get, mock_serial, mock_post): + def test_116_revoke(self, mock_get, mock_serial, mock_post): """ test revoke certificates in certificate_list all good """ self.cahandler.api_host = 'api_host' mock_serial.return_value = 11 @@ -1295,7 +1357,7 @@ def test_110_revoke(self, mock_get, mock_serial, mock_post): @patch('examples.ca_handler.nclm_ca_handler.CAhandler._api_post') @patch('examples.ca_handler.nclm_ca_handler.cert_serial_get') @patch('requests.get') - def test_111_revoke(self, mock_get, mock_serial, mock_post): + def test_117_revoke(self, mock_get, mock_serial, mock_post): """ test revoke certificates in certificate_list but request.post returns execption """ self.cahandler.api_host = 'api_host' mock_serial.return_value = 11 @@ -1305,14 +1367,14 @@ def test_111_revoke(self, mock_get, mock_serial, mock_post): mock_post.side_effect = Exception('ex_req_post') self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'Revocation operation failed'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) - def test_112_enroll(self): + def test_118_enroll(self): """ enroll() if there is an error """ self.cahandler.error = 'foo' with self.assertLogs('test_a2c', level='INFO') as lcm: self.assertEqual((None, None, None, None), self.cahandler.enroll('csr')) self.assertIn('ERROR:test_a2c:foo', lcm.output) - def test_113_enroll(self): + def test_119_enroll(self): """ enroll() no target-system-id """ self.cahandler.tsg_info_dic = {'id': None, 'name': 'name'} self.assertEqual(('CAhandler.eroll(): ID lookup for targetSystemGroup "name" failed.', None, None, None), self.cahandler.enroll('csr')) @@ -1325,7 +1387,7 @@ def test_113_enroll(self): @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') - def test_114_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup): + def test_120_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup): """ enroll() without certid """ self.cahandler.api_host = 'api_host' self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} @@ -1349,7 +1411,7 @@ def test_114_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, m @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') - def test_115_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + def test_121_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): """ enroll() with certid """ self.cahandler.api_host = 'api_host' self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} @@ -1374,7 +1436,7 @@ def test_115_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, m @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') - def test_116_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + def test_122_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): """ enroll() no tmpload """ self.cahandler.api_host = 'api_host' self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} @@ -1400,7 +1462,7 @@ def test_116_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, m @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') - def test_117_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + def test_123_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): """ enroll() tmpload """ self.cahandler.api_host = 'api_host' self.cahandler.tsg_info_dic = {'id': 10, 'name': 'name'} @@ -1426,7 +1488,7 @@ def test_117_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, m @patch('examples.ca_handler.nclm_ca_handler.csr_san_get') @patch('examples.ca_handler.nclm_ca_handler.csr_cn_get') @patch('examples.ca_handler.nclm_ca_handler.CAhandler._ca_id_lookup') - def test_118_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): + def test_124_enroll(self, mock_lookup, mock_cn_get, mock_san_get, mock_reqimp, mock_csr_lookup, mock_post, mock_cert_lookup, mock_tmpl_lookup, mock_bundle): """ enroll() tmpload """ self.cahandler.api_host = 'api_host' self.cahandler.tsg_info_dic = {'id': 'id', 'name': 'name'} diff --git a/test/test_xca_ca_handler.py b/test/test_xca_ca_handler.py index 40a88ccf..6dfaa032 100644 --- a/test/test_xca_ca_handler.py +++ b/test/test_xca_ca_handler.py @@ -1822,7 +1822,6 @@ def test_196__extension_list_generate(self, mock_crypto, mock_ku, mock_eku): self.assertTrue(mock_ku.called) self.assertTrue(mock_eku.called) - @patch('examples.ca_handler.xca_ca_handler.CAhandler._extended_keyusage_generate') @patch('examples.ca_handler.xca_ca_handler.CAhandler._keyusage_generate') @patch('OpenSSL.crypto.X509Extension') From c678b7dfe84ad5f788e6b534621f39c295945293 Mon Sep 17 00:00:00 2001 From: grindsa Date: Mon, 7 Jun 2021 08:51:43 +0200 Subject: [PATCH 39/51] [tst] unittests authorization.py --- acme/authorization.py | 7 +++++-- test/test_authorization.py | 32 +++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/acme/authorization.py b/acme/authorization.py index 46514989..190f3a87 100644 --- a/acme/authorization.py +++ b/acme/authorization.py @@ -51,7 +51,7 @@ def _authz_info(self, url): try: self.dbstore.authorization_update({'name' : authz_name, 'token' : token, 'expires' : expires}) except BaseException as err_: - self.logger.critical('acme2certifier database error in Authorization._authz_info(): {0}'.format(err_)) + self.logger.error('acme2certifier database error in Authorization._authz_info(): {0}'.format(err_)) authz_info_dic['expires'] = uts_to_date_utc(expires) # get authorization information from db to be inserted in message @@ -59,8 +59,9 @@ def _authz_info(self, url): try: auth_info = self.dbstore.authorization_lookup('name', authz_name, ['status__name', 'type', 'value']) except BaseException as err_: - self.logger.critical('acme2certifier database error in Authorization._authz_info(): {0}'.format(err_)) + self.logger.error('acme2certifier database error in Authorization._authz_info(): {0}'.format(err_)) auth_info = {} + if auth_info: if 'status__name' in auth_info[0]: authz_info_dic['status'] = auth_info[0]['status__name'] @@ -71,6 +72,8 @@ def _authz_info(self, url): authz_info_dic['identifier'] = {'type' : auth_info[0]['type'], 'value' : auth_info[0]['value']} if auth_info[0]['type'] == 'TNAuthList': tnauth = True + else: + authz_info_dic['status'] = 'pending' with Challenge(self.debug, self.server_name, self.logger, expires) as challenge: # get challenge data (either existing or new ones) diff --git a/test/test_authorization.py b/test/test_authorization.py index 4c601172..8f65b4dd 100644 --- a/test/test_authorization.py +++ b/test/test_authorization.py @@ -152,7 +152,7 @@ def test_014_authorization__authz_info(self, mock_name, mock_uts, mock_challenge self.authorization.dbstore.authorization_lookup.return_value = [{'name': 'foo'}] with self.assertLogs('test_a2c', level='INFO') as lcm: self.authorization._authz_info('http://tester.local/acme/authz/foo') - self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_authz_update', lcm.output) + self.assertIn('ERROR:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_authz_update', lcm.output) @patch('acme.challenge.Challenge.new_set') @patch('acme.authorization.uts_now') @@ -182,15 +182,29 @@ def test_016_authorization__authz_info(self, mock_name, mock_uts, mock_challenge self.authorization._authz_info('http://tester.local/acme/authz/foo') self.assertIn('CRITICAL:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_authz_update', lcm.output) + @patch('acme.challenge.Challenge.new_set') + @patch('acme.authorization.uts_now') + @patch('acme.authorization.generate_random_string') + def test_017_authorization__authz_info(self, mock_name, mock_uts, mock_challengeset): + """ test Authorization.auth_info() - dbstore.authorization lookup raises an exception """ + mock_name.return_value = 'randowm_string' + mock_uts.return_value = 1543640400 + mock_challengeset.return_value = [{'key1' : 'value1', 'key2' : 'value2'}] + self.authorization.dbstore.authorization_update.return_value = 'foo' + self.authorization.dbstore.authorization_lookup.side_effect = [[{'type' : 'identifier_type', 'value1' : 'identifier_value', 'status__name' : 'foo'}], Exception('exc_authz_lookup')] + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.authorization._authz_info('http://tester.local/acme/authz/foo') + self.assertIn('ERROR:test_a2c:acme2certifier database error in Authorization._authz_info(): exc_authz_lookup', lcm.output) + @patch('acme.authorization.Authorization._config_load') - def test_017__enter__(self, mock_cfg): + def test_018__enter__(self, mock_cfg): """ test enter """ mock_cfg.return_value = True self.authorization.__enter__() self.assertTrue(mock_cfg.called) @patch('acme.authorization.load_config') - def test_018_config_load(self, mock_load_cfg): + def test_019_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() mock_load_cfg.return_value = parser @@ -199,7 +213,7 @@ def test_018_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_019_config_load(self, mock_load_cfg): + def test_020_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'foo': 'bar'} @@ -209,7 +223,7 @@ def test_019_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_020_config_load(self, mock_load_cfg): + def test_021_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'expiry_check_disable': False} @@ -219,7 +233,7 @@ def test_020_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_021_config_load(self, mock_load_cfg): + def test_022_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'expiry_check_disable': True} @@ -229,7 +243,7 @@ def test_021_config_load(self, mock_load_cfg): self.assertEqual(86400, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_022_config_load(self, mock_load_cfg): + def test_023_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'validity': 60} @@ -239,7 +253,7 @@ def test_022_config_load(self, mock_load_cfg): self.assertEqual(60, self.authorization.validity ) @patch('acme.authorization.load_config') - def test_023_config_load(self, mock_load_cfg): + def test_024_config_load(self, mock_load_cfg): """ test _config_load """ parser = configparser.ConfigParser() parser['Authorization'] = {'validity': 'foo'} @@ -251,7 +265,7 @@ def test_023_config_load(self, mock_load_cfg): self.assertIn('WARNING:test_a2c:Authorization._config_load(): failed to parse validity: foo', lcm.output) @patch('acme.authorization.Authorization._authz_info') - def test_024_new_get(self, mock_info): + def test_025_new_get(self, mock_info): """ new get """ mock_info.return_value = 'foo' result = {'code': 200, 'data': 'foo', 'header': {}} From 5eb4371eff55e14a3b4323b9417350fa0c221161 Mon Sep 17 00:00:00 2001 From: grindsa Date: Mon, 7 Jun 2021 19:41:02 +0200 Subject: [PATCH 40/51] [feat] environment variables in est_ca_handler.py --- docs/est.md | 5 +- examples/ca_handler/est_ca_handler.py | 31 ++++- test/test_est_ca_handler.py | 168 +++++++++++++++++++------- 3 files changed, 157 insertions(+), 47 deletions(-) diff --git a/docs/est.md b/docs/est.md index 7919efa7..95256551 100644 --- a/docs/est.md +++ b/docs/est.md @@ -42,11 +42,14 @@ ca_bundle: ``` - est_host - URL of the est server service +- est_host_variable - *optional* - name of the environment variable storing the est server url (a configured `est_host` parameter in acme_srv.cfg takes precedence) - est_client_key - Private key of the certificate used for TLS client-auth (acme/est/est.key.pem) - est_client_cert - Certificate used for TLS client-auth (acme/est/est.crt.pem) - est_user - username for HTTP basic Authentication +- est_user_variable - *optional* - name of the environment variable specifying the username for HTTP basic authentication (a configured `est_user` parameter in acme_srv.cfg takes precedence) - est_password - password for HTTP basic Authentication -- ca_bundle - CA certificate bundle needed to valiate the EST server certificate (acme/est/ca_bundle.pem). Setting to False disables the certificate check +- est_password_variable - *optional* - name of the environment variable specifying the user password for HTTP basic authentication (a configured `est_password` parameter in acme_srv.cfg takes precedence) +- ca_bundle - CA certificate bundle needed to validate the EST server certificate (acme/est/ca_bundle.pem). Setting to False disables the certificate check Important: TLSClientAuth and HTTP basic authentication cannot be combined with each other diff --git a/examples/ca_handler/est_ca_handler.py b/examples/ca_handler/est_ca_handler.py index 0f6fb070..1ee6981a 100644 --- a/examples/ca_handler/est_ca_handler.py +++ b/examples/ca_handler/est_ca_handler.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- """ ca handler for generic EST server """ from __future__ import print_function +import os import textwrap import requests from requests.auth import HTTPBasicAuth @@ -91,10 +92,17 @@ def _config_load(self): self.logger.debug('CAhandler._config_load()') config_dic = load_config(self.logger, 'CAhandler') + if 'est_host_variable' in config_dic['CAhandler']: + try: + self.est_host = os.environ[config_dic['CAhandler']['est_host_variable']] + '/.well-known/est' + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load est_host_variable:{0}'.format(err)) if 'est_host' in config_dic['CAhandler']: + if self.est_host: + self.logger.info('CAhandler._config_load() overwrite est_host') self.est_host = config_dic['CAhandler']['est_host'] + '/.well-known/est' - else: - self.logger.error('CAhandler._config_load(): missing "est_host" parameter in config file') + if not self.est_host: + self.logger.error('CAhandler._config_load(): missing "est_host" parameter') # check if we need to use clientauth if 'est_client_cert' in config_dic['CAhandler'] and 'est_client_key' in config_dic['CAhandler']: @@ -105,10 +113,25 @@ def _config_load(self): self.logger.error('CAhandler._config_load() configuration incomplete: either "est_client_cert or "est_client_key" parameter is missing in config file') # check if we need to use user-auth - if 'est_user' in config_dic['CAhandler'] and 'est_password' in config_dic['CAhandler']: + if 'est_user_variable' in config_dic['CAhandler']: + try: + self.est_user = os.environ[config_dic['CAhandler']['est_user_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load est_user_variable:{0}'.format(err)) + if 'est_user' in config_dic['CAhandler']: + if self.est_user: + self.logger.info('CAhandler._config_load() overwrite est_user') self.est_user = config_dic['CAhandler']['est_user'] + if 'est_password_variable' in config_dic['CAhandler']: + try: + self.est_password = os.environ[config_dic['CAhandler']['est_password_variable']] + except BaseException as err: + self.logger.error('CAhandler._config_load() could not load est_password:{0}'.format(err)) + if 'est_password' in config_dic['CAhandler']: + if self.est_password: + self.logger.info('CAhandler._config_load() overwrite est_password') self.est_password = config_dic['CAhandler']['est_password'] - elif 'est_user' in config_dic['CAhandler'] or 'est_password' in config_dic['CAhandler']: + if (self.est_user and not self.est_password) or (self.est_password and not self.est_user): self.logger.error('CAhandler._config_load() configuration incomplete: either "est_user" or "est_password" parameter is missing in config file') # check if we have one authentication scheme diff --git a/test/test_est_ca_handler.py b/test/test_est_ca_handler.py index ad164b1f..10128fd4 100644 --- a/test/test_est_ca_handler.py +++ b/test/test_est_ca_handler.py @@ -48,16 +48,44 @@ def test_003_config_load(self, mock_load_cfg): self.cahandler._config_load() self.assertEqual('foo_host/.well-known/est', self.cahandler.est_host) + @patch.dict('os.environ', {'est_host_var': 'foo_host'}) @patch('examples.ca_handler.est_ca_handler.load_config') def test_004_config_load(self, mock_load_cfg): + """ test _config_load - est host configured via environment variable """ + mock_load_cfg.return_value = {'CAhandler': {'est_host_variable': 'est_host_var'}} + self.cahandler._config_load() + self.assertEqual('foo_host/.well-known/est', self.cahandler.est_host) + + @patch.dict('os.environ', {'est_host_var': 'foo_host'}) + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_005_config_load(self, mock_load_cfg): + """ test _config_load - est host configured via not existing environment variable """ + mock_load_cfg.return_value = {'CAhandler': {'est_host_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.est_host) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load est_host_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'est_host_var': 'foo_host'}) + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_006_config_load(self, mock_load_cfg): + """ test _config_load - est host configured as variable and in cfg """ + mock_load_cfg.return_value = {'CAhandler': {'est_host_variable': 'est_host_var', 'est_host': 'foo_host_loc'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('foo_host_loc/.well-known/est', self.cahandler.est_host) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite est_host', lcm.output) + + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_007_config_load(self, mock_load_cfg): """ test _config_load - no est host configured """ mock_load_cfg.return_value = {'CAhandler': {'foo': 'bar'}} with self.assertLogs('test_a2c', level='INFO') as lcm: self.cahandler._config_load() - self.assertIn('ERROR:test_a2c:CAhandler._config_load(): missing "est_host" parameter in config file', lcm.output) + self.assertIn('ERROR:test_a2c:CAhandler._config_load(): missing "est_host" parameter', lcm.output) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_005_config_load(self, mock_load_cfg): + def test_008_config_load(self, mock_load_cfg): """ test _config_load - client certificate configured but no key """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_client_cert': 'est_client_cert'}} with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -66,7 +94,7 @@ def test_005_config_load(self, mock_load_cfg): self.assertIn('ERROR:test_a2c:CAhandler._config_load() configuration incomplete: either "est_client_cert or "est_client_key" parameter is missing in config file', lcm.output) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_006_config_load(self, mock_load_cfg): + def test_009_config_load(self, mock_load_cfg): """ test _config_load - client certificate configured but no key """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_client_key': 'est_client_key'}} with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -75,35 +103,91 @@ def test_006_config_load(self, mock_load_cfg): self.assertIn('ERROR:test_a2c:CAhandler._config_load() configuration incomplete: either "est_client_cert or "est_client_key" parameter is missing in config file', lcm.output) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_007_config_load(self, mock_load_cfg): + def test_010_config_load(self, mock_load_cfg): """ test _config_load - user is configured but no password """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_user': 'est_user'}} with self.assertLogs('test_a2c', level='INFO') as lcm: self.cahandler._config_load() - self.assertFalse(self.cahandler.est_user) + self.assertTrue(self.cahandler.est_user) self.assertFalse(self.cahandler.est_password) self.assertIn('ERROR:test_a2c:CAhandler._config_load() configuration incomplete: either "est_user" or "est_password" parameter is missing in config file', lcm.output) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_008_config_load(self, mock_load_cfg): + def test_011_config_load(self, mock_load_cfg): """ test _config_load - password is configured but no user_name """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_password': 'est_password'}} with self.assertLogs('test_a2c', level='INFO') as lcm: self.cahandler._config_load() self.assertFalse(self.cahandler.est_user) - self.assertFalse(self.cahandler.est_password) + self.assertTrue(self.cahandler.est_password) self.assertIn('ERROR:test_a2c:CAhandler._config_load() configuration incomplete: either "est_user" or "est_password" parameter is missing in config file', lcm.output) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_009_config_load(self, mock_load_cfg): + def test_012_config_load(self, mock_load_cfg): """ test _config_load - username and password are configured """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_user': 'est_user', 'est_password': 'est_password'}} self.cahandler._config_load() self.assertEqual('est_user', self.cahandler.est_user) self.assertEqual('est_password', self.cahandler.est_password) + @patch.dict('os.environ', {'est_user_var': 'estuser'}) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_010_config_load(self, mock_load_cfg): + def test_013_config_load(self, mock_load_cfg): + """ test _config_load - load username from variable """ + mock_load_cfg.return_value = {'CAhandler': {'est_user_variable': 'est_user_var'}} + self.cahandler._config_load() + self.assertEqual('estuser', self.cahandler.est_user) + + @patch.dict('os.environ', {'est_pass_var': 'estpass'}) + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_014_config_load(self, mock_load_cfg): + """ test _config_load - load password from variable """ + mock_load_cfg.return_value = {'CAhandler': {'est_password_variable': 'est_pass_var'}} + self.cahandler._config_load() + self.assertEqual('estpass', self.cahandler.est_password) + + @patch.dict('os.environ', {'est_user_var': 'estuser'}) + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_015_config_load(self, mock_load_cfg): + """ test _config_load - load username from not existing variable """ + mock_load_cfg.return_value = {'CAhandler': {'est_user_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.est_user) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load est_user_variable:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'est_pass_var': 'estpass'}) + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_016_config_load(self, mock_load_cfg): + """ test _config_load - load password from not existing variable """ + mock_load_cfg.return_value = {'CAhandler': {'est_password_variable': 'does_not_exist'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertFalse(self.cahandler.est_password) + self.assertIn("ERROR:test_a2c:CAhandler._config_load() could not load est_password:'does_not_exist'", lcm.output) + + @patch.dict('os.environ', {'est_user_var': 'estuser'}) + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_017_config_load(self, mock_load_cfg): + """ test _config_load - load username from variable and cfg """ + mock_load_cfg.return_value = {'CAhandler': {'est_user_variable': 'est_user_var', 'est_user': 'estuser_loc'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('estuser_loc', self.cahandler.est_user) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite est_user', lcm.output) + + @patch.dict('os.environ', {'est_pass_var': 'estpass'}) + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_018_config_load(self, mock_load_cfg): + """ test _config_load - load password from variable """ + mock_load_cfg.return_value = {'CAhandler': {'est_password_variable': 'est_pass_var', 'est_password': 'estpassword_loc'}} + with self.assertLogs('test_a2c', level='INFO') as lcm: + self.cahandler._config_load() + self.assertEqual('estpassword_loc', self.cahandler.est_password) + self.assertIn('INFO:test_a2c:CAhandler._config_load() overwrite est_password', lcm.output) + + @patch('examples.ca_handler.est_ca_handler.load_config') + def test_019_config_load(self, mock_load_cfg): """ test _config_load - neither client nor user_auth are configured """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo'}} with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -114,7 +198,7 @@ def test_010_config_load(self, mock_load_cfg): self.assertIn('ERROR:test_a2c:CAhandler._config_load() configuration incomplete: either user or client authentication must be configured', lcm.output) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_011_config_load(self, mock_load_cfg): + def test_020_config_load(self, mock_load_cfg): """ test _config_load - neither client nor user_auth are configured """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_user': 'est_user', 'est_password': 'est_password', 'est_client_cert': 'est_client_cert', 'est_client_key': 'est_client_key'}} with self.assertLogs('test_a2c', level='INFO') as lcm: @@ -125,49 +209,49 @@ def test_011_config_load(self, mock_load_cfg): self.assertIn('ERROR:test_a2c:CAhandler._config_load() configuration wrong: user and client authentication cannot be configured together', lcm.output) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_012_config_load(self, mock_load_cfg): + def test_021_config_load(self, mock_load_cfg): """ test _config_load - ca bundle not configured """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_user': 'est_user', 'est_password': 'est_password'}} self.cahandler._config_load() self.assertTrue(self.cahandler.ca_bundle) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_013_config_load(self, mock_load_cfg): + def test_022_config_load(self, mock_load_cfg): """ test _config_load - ca bundle True """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_user': 'est_user', 'est_password': 'est_password', 'ca_bundle': True}} self.cahandler._config_load() self.assertTrue(self.cahandler.ca_bundle) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_014_config_load(self, mock_load_cfg): + def test_023_config_load(self, mock_load_cfg): """ test _config_load - ca bundle False """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_user': 'est_user', 'est_password': 'est_password', 'ca_bundle': False}} self.cahandler._config_load() self.assertFalse(self.cahandler.ca_bundle) @patch('examples.ca_handler.est_ca_handler.load_config') - def test_015_config_load(self, mock_load_cfg): + def test_024_config_load(self, mock_load_cfg): """ test _config_load - ca bundle string """ mock_load_cfg.return_value = {'CAhandler': {'est_host': 'foo', 'est_user': 'est_user', 'est_password': 'est_password', 'ca_bundle': 'bar'}} self.cahandler._config_load() self.assertEqual('bar', self.cahandler.ca_bundle) - def test_016_revoke(self): + def test_025_revoke(self): """ test revocation """ self.assertEqual((500, 'urn:ietf:params:acme:error:serverInternal', 'Revocation is not supported.'), self.cahandler.revoke('cert', 'rev_reason', 'rev_date')) - def test_017_poll(self): + def test_026_poll(self): """ test polling """ self.assertEqual(('Method not implemented.', None, None, 'poll_identifier', False), self.cahandler.poll('cert_name', 'poll_identifier', 'csr')) - def test_018_trigger(self): + def test_027_trigger(self): """ test polling """ self.assertEqual(('Method not implemented.', None, None), self.cahandler.trigger('payload')) @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch.object(requests, 'get') - def test_019__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): + def test_028__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() successful run by using client certs """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -181,7 +265,7 @@ def test_019__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch.object(requests, 'get') - def test_020__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): + def test_029__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() successful run by using client certs """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -196,7 +280,7 @@ def test_020__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch.object(requests, 'get') - def test_021__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): + def test_030__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() no est_host parameter """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -211,7 +295,7 @@ def test_021__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch('requests.get') - def test_022__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): + def test_031__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() request.get triggers exception """ mock_req.side_effect = Exception('exc_cacerts_get') mock_to_pem.return_value = 'pem' @@ -225,7 +309,7 @@ def test_022__cacerts_get(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch.object(requests, 'post') - def test_023__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): + def test_032__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() successful run """ mockresponse = Mock() mock_req.return_value = mockresponse @@ -239,7 +323,7 @@ def test_023__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch('requests.post') - def test_024__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): + def test_033__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() successful run """ mock_req.side_effect = Exception('exc_simple_enroll') mock_to_pem.return_value = 'pem' @@ -253,7 +337,7 @@ def test_024__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): @patch('examples.ca_handler.est_ca_handler.b64_decode') @patch('examples.ca_handler.est_ca_handler.CAhandler._pkcs7_to_pem') @patch('requests.post') - def test_025__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): + def test_034__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): """ test _cacerts_get() successful run """ mock_req.side_effect = Exception('exc_simple_enroll') mock_to_pem.return_value = 'pem' @@ -266,7 +350,7 @@ def test_025__simpleenroll(self, mock_req, mock_to_pem, _mock_b64): self.assertIn('ERROR:test_a2c:CAhandler._simpleenroll() returned an error: exc_simple_enroll', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_026_enroll(self, mock_ca): + def test_035_enroll(self, mock_ca): """ test certificate enrollment _cacert_get returns error """ mock_ca.return_value = ('Error', None) self.cahandler.est_host = 'foo' @@ -275,7 +359,7 @@ def test_026_enroll(self, mock_ca): self.assertIn('ERROR:test_a2c:CAhandler.enroll(): Error', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_027_enroll(self, mock_ca): + def test_036_enroll(self, mock_ca): """ test certificate enrollment no error but now ca_certs """ mock_ca.return_value = (None, None) self.cahandler.est_host = 'foo' @@ -284,7 +368,7 @@ def test_027_enroll(self, mock_ca): self.assertIn('ERROR:test_a2c:CAhandler.enroll(): no CA certificates found', lcm.output) @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_028_enroll(self, mock_ca): + def test_037_enroll(self, mock_ca): """ test certificate enrollment authentication information are missing """ mock_ca.return_value = (None, 'ca_pem') self.cahandler.est_host = 'foo' @@ -294,7 +378,7 @@ def test_028_enroll(self, mock_ca): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_029_enroll(self, mock_ca, mock_enroll): + def test_038_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment _simpleenroll returns error """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = ('Error', None) @@ -306,7 +390,7 @@ def test_029_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_030_enroll(self, mock_ca, mock_enroll): + def test_039_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment _simpleenroll returns certificate """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, 'cert') @@ -316,7 +400,7 @@ def test_030_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_031_enroll(self, mock_ca, mock_enroll): + def test_040_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert') @@ -326,7 +410,7 @@ def test_031_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_032_enroll(self, mock_ca, mock_enroll): + def test_041_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT END """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, 'cert-----END CERTIFICATE-----\n') @@ -336,7 +420,7 @@ def test_032_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_033_enroll(self, mock_ca, mock_enroll): + def test_042_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN AND END """ mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert-----END CERTIFICATE-----\n') @@ -346,7 +430,7 @@ def test_033_enroll(self, mock_ca, mock_enroll): @patch('examples.ca_handler.est_ca_handler.CAhandler._simpleenroll') @patch('examples.ca_handler.est_ca_handler.CAhandler._cacerts_get') - def test_034_enroll(self, mock_ca, mock_enroll): + def test_043_enroll(self, mock_ca, mock_enroll): """ test certificate enrollment replace CERT BEGIN AND END and \n""" mock_ca.return_value = (None, 'ca_pem') mock_enroll.return_value = (None, '-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n\n') @@ -355,21 +439,21 @@ def test_034_enroll(self, mock_ca, mock_enroll): self.assertEqual((None, '-----BEGIN CERTIFICATE-----\ncert\n-----END CERTIFICATE-----\n\nca_pem', 'cert', None), self.cahandler.enroll('csr')) @patch('examples.ca_handler.est_ca_handler.CAhandler._config_load') - def test_035__enter__(self, mock_cfg): + def test_044__enter__(self, mock_cfg): """ test enter called """ mock_cfg.return_value = True self.cahandler.__enter__() self.assertTrue(mock_cfg.called) @patch('examples.ca_handler.est_ca_handler.CAhandler._config_load') - def test_036__enter__(self, mock_cfg): + def test_045__enter__(self, mock_cfg): """ test enter api hosts defined """ mock_cfg.return_value = True self.cahandler.est_host = 'api_host' self.cahandler.__enter__() self.assertFalse(mock_cfg.called) - def test_037_get_certificates(self): + def test_046_get_certificates(self): """ test pkcs7 convrt to pem """ cert_pem_list = [] with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: @@ -381,7 +465,7 @@ def test_037_get_certificates(self): result = [b'-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', b'-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] self.assertEqual(result, cert_pem_list) - def test_038__pkcs7_to_pem(self): + def test_047__pkcs7_to_pem(self): """ test pkcs7 to pem default output """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() @@ -389,7 +473,7 @@ def test_038__pkcs7_to_pem(self): result = fso.read() self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content)) - def test_039__pkcs7_to_pem(self): + def test_048__pkcs7_to_pem(self): """ test pkcs7 to pem output string """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() @@ -397,14 +481,14 @@ def test_039__pkcs7_to_pem(self): result = fso.read() self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'string')) - def test_040__pkcs7_to_pem(self): + def test_049__pkcs7_to_pem(self): """ test pkcs7 to pem output list """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() result = ['-----BEGIN CERTIFICATE-----\nMIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1\nNDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP\nMA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\nxXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8\njqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/\nqkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/\n/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV\nXcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9\nhcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB\nZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1\n5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM\nGueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8\nhH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm\nKxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T\nAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD\nVR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP\neGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc\n31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W\nvDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9\n6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH\nJh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa\n7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC\nzM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3\n2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/\nM7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5\nZ3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF\nzfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t\njX1vlY35Ofonc4+6dRVamBiF9A==\n-----END CERTIFICATE-----\n', '-----BEGIN CERTIFICATE-----\nMIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\nCxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw\nMDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ\nMA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nAJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF\nrqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ\n1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW\nqWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR\n1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir\n+KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ\n2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS\nri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB\nCrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK\n16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9\nBYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD\nVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD\nVR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG\nCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl\nMA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN\nNdt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX\nEzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu\nDRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3\nFc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs\n475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge\n2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO\n7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW\nG8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6\neVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp\n0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF\nfvkG2Q==\n-----END CERTIFICATE-----\n'] self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'list')) - def test_041__pkcs7_to_pem(self): + def test_050__pkcs7_to_pem(self): """ test pkcs7 to pem output list """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() @@ -412,7 +496,7 @@ def test_041__pkcs7_to_pem(self): self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) @patch('OpenSSL.crypto.load_pkcs7_data') - def test_042__pkcs7_to_pem(self, mock_load): + def test_051__pkcs7_to_pem(self, mock_load): """ test pkcs7 to pem output list """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() @@ -422,7 +506,7 @@ def test_042__pkcs7_to_pem(self, mock_load): self.assertEqual(result, self.cahandler._pkcs7_to_pem(file_content, 'unknown')) @patch('OpenSSL.crypto') - def test_043__pkcs7_to_pem(self, mock_load): + def test_052__pkcs7_to_pem(self, mock_load): """ test pkcs7 to pem output list """ with open(self.dir_path + '/ca/certs.p7b', 'r') as fso: file_content = fso.read() From 3adadfbde9278d943edcec0a703b5bba113c809a Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 8 Jun 2021 08:47:21 +0200 Subject: [PATCH 41/51] [fix] est_ca_handler.py --- .github/workflows/ca_handler_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ca_handler_tests.yml b/.github/workflows/ca_handler_tests.yml index 87b75975..f84341cd 100644 --- a/.github/workflows/ca_handler_tests.yml +++ b/.github/workflows/ca_handler_tests.yml @@ -135,7 +135,7 @@ jobs: run: | sudo apt-get install curl openssl patch sudo cp examples/ca_handler/est_ca_handler.py examples/Docker/data/ca_handler.py - sudo patch examples/Docker/data/ca_handler.py .github/est_handler.patch + # sudo patch examples/Docker/data/ca_handler.py .github/est_handler.patch - name: "[ PREPARE ] setup using http-basic-auth" run: | sudo mkdir -p examples/Docker/data/est @@ -184,7 +184,7 @@ jobs: if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload - # sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ cd examples/Docker docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log From 906c1edeab66b09b6e4444245c92b81a48978d13 Mon Sep 17 00:00:00 2001 From: grindsa Date: Tue, 8 Jun 2021 13:14:54 +0200 Subject: [PATCH 42/51] [doc] updated CHANGES.md --- CHANGES.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 3723a425..b7903aea 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,32 @@ This is a high-level summary of the most important changes. For a full list of changes, see the [git commit log](https://github.com/grindsa/acme2certifier/commits) and pick the appropriate release branch. +## Changes in 0.16 + +**Features**: + +- CA-Handler configuration via environment variables: + - cmp_ca_handler: ref-num and passphrase + - certifier_ca_handler: api_user, api_password + - est_ca_handler: est_host, est_user, est_password + - mscertsrv_ca_handler: host, user, password + - nclm_ca_handler: api_user, api_password + - openssl_ca_handler: passphrase + - xca_ca_handler: passphrase + +**Bugfixes**: + +- avoidance of KU/EKU duplicates when using templates in xca_ca_handler +- alpn challenge handling in django deployments +- fix for handling of empty challenges +- more robust DNS challenge validation + +**Other improvements**: + +- [CodeCoverage measurement](https://app.codecov.io/gh/grindsa/acme2certifier/) via codecov.io +- Switch to [acme.sh:latest](https://hub.docker.com/r/neilpang/acme.sh) in CI pipeline +- Regression test-cases for django deployments using either mariadb or postgres backends + ## Changes in 0.15.3 **Upgrade notes**: From 1dce0a5eaff06a4f35e9b78c28251fc3bcc52b8d Mon Sep 17 00:00:00 2001 From: grindsa Date: Wed, 9 Jun 2021 19:02:28 +0200 Subject: [PATCH 43/51] [doc] fix typos --- CHANGES.md | 4 ++-- README.md | 6 +++--- docs/acme_srv.md | 6 +++--- docs/cert-mgr.md | 2 +- docs/cmp.md | 6 +++--- docs/mscertsrv.md | 6 +++--- docs/openssl.md | 4 ++-- docs/poll.md | 2 +- docs/trigger.md | 8 ++++---- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b7903aea..ef99c824 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -138,13 +138,13 @@ and pick the appropriate release branch. **Bugfixes/Improvements**: - several fixes in unit-tests -- unit-tests are splitted into separate files +- unit-tests are split into separate files - unittests for `certifier_ca_handler.py` - documentation updates - Github actions to test - certificate enrollment for all four containerized deployment options - tnauth functionality - - image creation and dockerhup upload + - image creation and dockerhub upload ## Changes in 0.11.1 diff --git a/README.md b/README.md index 55b17dca..32568691 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ project's home page at: [https://github.com/grindsa/acme2certifier](https://gith ## ChangeLog -Releasenotes and ChangLog can be found at [https://github.com/grindsa/acme2certifier/releases](https://github.com/grindsa/acme2certifier/releases) +Release notes and ChangLog can be found at [https://github.com/grindsa/acme2certifier/releases](https://github.com/grindsa/acme2certifier/releases) ## Disclaimer @@ -97,9 +97,9 @@ to let me know. ## Installation -The proxy can run either as plain wsgi-script on either apache or ngix or as +The proxy can run either as plain wsgi-script on either apache or nginx or as django project. Running acme2certifier as django project allows to use other -database backendes than SQLite. +database backends than SQLite. The fastest and most convenient way to install acme2certifier is to use docker containers. There are ready made images available at [dockerhub](https://hub.docker.com/r/grindsa/acme2certifier) and [ghcr.io](https://github.com/users/grindsa/packages/container/acme2certifier/) diff --git a/docs/acme_srv.md b/docs/acme_srv.md index cb721a39..47885d3e 100644 --- a/docs/acme_srv.md +++ b/docs/acme_srv.md @@ -7,7 +7,7 @@ | Section | Option | Description | Values | default| | :-------| :------| :-----------| :------| :------| | `DEFAULT` | `debug` | Debug mode| True/False| False| -| `Account` | `ecc_only` | mandantes the usage of ECC for account key generation | True/False | False| +| `Account` | `ecc_only` | mandates the usage of ECC for account key generation | True/False | False| | `Account` | `inner_header_nonce_allow` | allow nonce header on inner JWS during key-rollover | True/False | False| | `Account` | `tos_check_disable` | turn off "Terms of Service" acceptance check | True/False | False| | `Authorization` | `expiry_check_disable` | Disable authorization expiration | True/False | False| @@ -16,13 +16,13 @@ | `Certificate` | `revocation_reason_check_disable` | disable the check of revocation reason | True/False | False| | `Challenge` | `challenge_validation_disable` | disable challenge validation via http or dns. THIS IS A SEVERE SECURITY ISSUE! Please enable for testing/debugging purposes only. | True/False | False| | `Challenge` | `dns_server_list` | Use own dns servers for name resolution during challenge verification| ["ip1", "ip2"] | []| -| `Directory` | `supress_version` | Do not show version information when fetching the directory ressource | True/False | False| +| `Directory` | `supress_version` | Do not show version information when fetching the directory resource | True/False | False| | `Directory` | `tos_url` | Terms of Service URL | URL | None| | `Helper` | `log_format` | Format of logging information | check the 'LogRecord attributes' Section of the [python logging module](https://docs.python.org/3/library/logging.html)| `%(message)s`| | `Message`| `signature_check_disable` | disable signature check of incoming JWS messages. THIS IS A SEVERE SECURTIY ISSUE bypassing security checks and allowing message manipulations during transit. Please enable for testing/debugging purposes only. | True/False | False| | `Nonce`| `nonce_check_disable` | disable nonce check. THIS IS A SECURTIY ISSUE as it exposes the API for replay attacks! Should be enabled for testing/debugging purposes only. | True/False | False| | `Order` | `expiry_check_disable` | Disable order expiration | True/False | False| -| `Order` | `retry_after_timeout` | Retry-After value to be send to client in case a certifcate enrollment request gets pending on CA server | Integer |120| +| `Order` | `retry_after_timeout` | Retry-After value to be send to client in case a certificate enrollment request gets pending on CA server | Integer |120| | `Order` | [`tnauthlist_support`](tnauthlist.md) | accept [TNAuthList identifiers](https://tools.ietf.org/html/draft-ietf-acme-authority-token-tnauthlist-03) and challenges containing [tkauth-01 type](https://tools.ietf.org/html/draft-ietf-acme-authority-token-03) | True/False | False| | `Order` | `validity` | Order validity in seconds | Integer |86400| diff --git a/docs/cert-mgr.md b/docs/cert-mgr.md index 2c45abc8..8f631ea6 100644 --- a/docs/cert-mgr.md +++ b/docs/cert-mgr.md @@ -57,7 +57,7 @@ spec: name: acme2certifier ``` -- apply the configuration. Certificate enrollment shoud start immedeately +- apply the configuration. Certificate enrollment should start immediately ```bash grindsa@ub-20:~$ microk8s.kubectl apply -f acme2certifier.yaml diff --git a/docs/cmp.md b/docs/cmp.md index 48e24564..8a2b89d9 100644 --- a/docs/cmp.md +++ b/docs/cmp.md @@ -3,7 +3,7 @@ # Generic CMPv2 protocol handler The CMPv2 protocol handler is not bound to a specific ca server. Certificate enrollment is done by calling an [openssl binary with cmpossl support](https://github.com/mpeylo/cmpossl/wiki). -That means that this handler just a wrapper calling openssl with special parameters by using the subprocess module. +That means that this handler just a wrapper calling openssl with special parameters by using the `subprocess` module. As of today, revocation operations are not supported. The handler has been tested against [Insta Certifier](https://www.insta.fi/en/services/cyber-security/insta-certifier) @@ -20,7 +20,7 @@ either Refnum/PSK or certificate authentication. Please consult your server conf The configuration could be a bid tricky and may require finetuning depending on type and configuration of your CMPv2 server. I strongly suggest to try enrollment via command line first and adapt the ca_handler accordingly. -In my setup acme2certifier is authenticating via refnum/secred towards CMPv2 server. The later described ca-handler configuration maps to the below command line. +In my setup acme2certifier is authenticating via refnum/secret towards CMPv2 server. The later described ca-handler configuration maps to the below command line. ```shell acme/cmp/WindowsCMPOpenSSL/openssl.exe cmp -cmd ir -server 192.168.14.137:8080 -path pkix/ -ref 1234 -secret pass:xxx -recipient "/C=DE/CN=tst_sub_ca" -newkey pubkey.pem -cert ra_cert.pem -trusted capubs.pem -popo 0 -subject /CN=test-cert -extracertsout ca_certs.pem -certout test-cert.pem -ignore_keyusage @@ -62,7 +62,7 @@ handler_file: examples/ca_handler/cmp_ca_handler.py ``` - modify the server configuration (/acme/acme_srv.cfg) according to your needs. every parameter used in the openssl CLI command requires a corresponding entry in the CAhandler -section. The entry is the name of the openssl parameter with the prefix "cmp_", value is the parameter value used in the openssl CLI command. In addtion you need to specify the +section. The entry is the name of the openssl parameter with the prefix "cmp_", value is the parameter value used in the openssl CLI command. In addition you need to specify the path to the openssl binary supporting CMPv2 (`cmp_openssl_bin`) and a temporary directory to store files (`cmp_tmp_dir`). The above mentioned CLI commend will result in the below configuration to be inserted in acme_srv.cfg diff --git a/docs/mscertsrv.md b/docs/mscertsrv.md index 00e2bf38..4323ddf8 100644 --- a/docs/mscertsrv.md +++ b/docs/mscertsrv.md @@ -13,7 +13,7 @@ When using the handler please be aware of the following limitations: ## Preparation 1. Microsoft Certification Authority Web Enrollment Service must be enabled and configured - of course :-) -2. You need to have a set of credentails with permissions to access the service and enrollment templates +2. You need to have a set of credentials with permissions to access the service and enrollment templates 3. Authentication method (basic or ntlm) to the service must be defined. It is helpful to verify the service access before starting the configuration of acme2certifier @@ -30,7 +30,7 @@ root@rlh:~# curl -I --ntlm --user : -k https:///certsrv/ root@rlh:~# curl -I --user : -k https:///certsrv/ ``` -Access to the service is possible if you see the status code 200 returned as part of the reponse +Access to the service is possible if you see the status code 200 returned as part of the response ```bash HTTP/1.1 200 OK @@ -74,6 +74,6 @@ template: - user_variable - *optional* - name of the environment variable containing the username used for service access (a configured `user` parameter in acme_srv.cfg takes precedence) - password - password - password_variable - *optional* - name of the environment variable containing the password used for service access (a configured `password` parameter in acme_srv.cfg takes precedence) -- ca_bundle - CA certificate bundle in pem format needed to valiate the server certificate +- ca_bundle - CA certificate bundle in pem format needed to validate the server certificate - auth_method - authentication method (either "basic" or "ntlm") - template - certificate template used for enrollment diff --git a/docs/openssl.md b/docs/openssl.md index 4c3dfd37..7ca323c0 100644 --- a/docs/openssl.md +++ b/docs/openssl.md @@ -66,7 +66,7 @@ save_cert_as_hex: True - `blacklist` - *optional* - list of prohibited common names and sans. Format per entry must follow the [regular expression syntax](https://docs.python.org/3/library/re.html). To be stored in json format - `save_cert_as_hex` - *optional* - serialnumber in hex format will be used as filename to save enrolled certificates -`whitelist` and `blecklist` options can be used independently from each other. When used together please note that that a positive result of a blacklist check takes presendence over the posivite result of a whitelist check. +`whitelist` and `blacklist` options can be used independently from each other. When used together please note that that a positive result of a blacklist check takes precedence over the positive result of a whitelist check. The openssl_conf file allows customization of the certificate profile and must contain a section `[extensions]` containing the certificate extensions to be inserted. If not specified the following extensions will be applied. @@ -84,6 +84,6 @@ Enjoy enrolling and revoking certificates some remarks: -- certificates and CRls will be signed with sha256 +- certificates and CRLs will be signed with sha256 - during enrollment all extensions included in the csr will be copied to the certificate. Don’t tell me that this is a bad idea. Read the first two sentences of this page instead. - the CRL "next update interval" is 7days diff --git a/docs/poll.md b/docs/poll.md index 606721c0..e82ae602 100644 --- a/docs/poll.md +++ b/docs/poll.md @@ -27,6 +27,6 @@ In parallel the ```order-status``` will be set to "valid" and a URL to ```certif polls the ```order```-resource. In case a CSR got rejected the order status will be changed to “invalid”. -The handler for [NeCM/Insta certifier](certifier.md) contains an example implementation. +The handler for [NCLM/Insta certifier](certifier.md) contains an example implementation. Further, an [example acme_srv.db](../examples/acme_srv.db.example) is available to give a better insight on the expected values especially in the certificate table. diff --git a/docs/trigger.md b/docs/trigger.md index 5bca2252..344a5242 100644 --- a/docs/trigger.md +++ b/docs/trigger.md @@ -19,14 +19,14 @@ ACME2CERTIFIER_URL="http://10.97.149.146" curl -X POST -H "Content-Type: application/json" -d "{\"payload\":\"$BASE64_PAYLOAD\"}" "$ACME2CERTIFIER_URL/trigger" ``` -The payload will be forwarded extracted from the post-request and forwarded to the ```ca_handler.trigger()``` method for furhter processing. +The payload will be forwarded extracted from the post-request and forwarded to the ```ca_handler.trigger()``` method for further processing. -It is expected that ```ca_handler.trigger()``` returns the follwoing values: +It is expected that ```ca_handler.trigger()``` returns the following values: - An error-message (if there is any) - The Certificate chain in pem-format - The certificate in asn1 (binary) format - base64 encoded - (needed for later revocation) -In case a valid certificate will be returned, acme2certifier will update the local database set the status of the order ressource to "valid". -The correlation between certifcate and certificate ressource will be done by comparing the public keys of certificate and CSR (which should +In case a valid certificate will be returned, acme2certifier will update the local database set the status of the order resource to "valid". +The correlation between certificate and certificate resource will be done by comparing the public keys of certificate and CSR (which should already exist in the database) From ebe888286c46653d0028e6446e9ee284ee45effb Mon Sep 17 00:00:00 2001 From: Florian Schilling Date: Fri, 11 Jun 2021 16:20:31 +0200 Subject: [PATCH 44/51] docker-container: do not change group owner-ship --- examples/Docker/apache2/django/docker-entrypoint.sh | 2 +- examples/Docker/apache2/wsgi/docker-entrypoint.sh | 2 +- examples/Docker/nginx/django/docker-entrypoint.sh | 2 +- examples/Docker/nginx/wsgi/docker-entrypoint.sh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/Docker/apache2/django/docker-entrypoint.sh b/examples/Docker/apache2/django/docker-entrypoint.sh index 383b0ba0..78c6157b 100644 --- a/examples/Docker/apache2/django/docker-entrypoint.sh +++ b/examples/Docker/apache2/django/docker-entrypoint.sh @@ -66,7 +66,7 @@ else ln -s /var/www/acme2certifier/volume/settings.py /var/www/acme2certifier/acme2certifier/settings.py fi -chown -R www-data.www-data /var/www/acme2certifier/volume +chown -R www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" diff --git a/examples/Docker/apache2/wsgi/docker-entrypoint.sh b/examples/Docker/apache2/wsgi/docker-entrypoint.sh index 70c3d122..11ca53dd 100644 --- a/examples/Docker/apache2/wsgi/docker-entrypoint.sh +++ b/examples/Docker/apache2/wsgi/docker-entrypoint.sh @@ -40,7 +40,7 @@ then ln -s /var/www/acme2certifier/volume/ca_handler.py /var/www/acme2certifier/acme/ca_handler.py fi -chown -R www-data.www-data /var/www/acme2certifier/volume +chown -R www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" diff --git a/examples/Docker/nginx/django/docker-entrypoint.sh b/examples/Docker/nginx/django/docker-entrypoint.sh index afc4606c..85334a15 100644 --- a/examples/Docker/nginx/django/docker-entrypoint.sh +++ b/examples/Docker/nginx/django/docker-entrypoint.sh @@ -69,7 +69,7 @@ else ln -s /var/www/acme2certifier/volume/settings.py /var/www/acme2certifier/acme2certifier/settings.py fi -chown -R www-data.www-data /var/www/acme2certifier/volume +chown -R www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" diff --git a/examples/Docker/nginx/wsgi/docker-entrypoint.sh b/examples/Docker/nginx/wsgi/docker-entrypoint.sh index cb904d27..62bc58d3 100644 --- a/examples/Docker/nginx/wsgi/docker-entrypoint.sh +++ b/examples/Docker/nginx/wsgi/docker-entrypoint.sh @@ -44,6 +44,6 @@ then ln -s /var/www/acme2certifier/volume/ca_handler.py /var/www/acme2certifier/acme/ca_handler.py fi -chown -R www-data.www-data /var/www/acme2certifier/volume +chown -R www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" From 43ff1b154ab6db1fcb238d62f9a31f6a809dbcac Mon Sep 17 00:00:00 2001 From: Florian Schilling Date: Fri, 11 Jun 2021 17:09:31 +0200 Subject: [PATCH 45/51] docker-entrypoint: don't copy ca_handler when defined handler_file in acme_srv.cfg --- .../apache2/django/docker-entrypoint.sh | 10 ++++++-- .../Docker/apache2/wsgi/docker-entrypoint.sh | 13 ++++++++--- .../Docker/nginx/django/docker-entrypoint.sh | 21 ++++++++++------- .../Docker/nginx/wsgi/docker-entrypoint.sh | 23 ++++++++++++------- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/examples/Docker/apache2/django/docker-entrypoint.sh b/examples/Docker/apache2/django/docker-entrypoint.sh index 78c6157b..7d5f9b96 100644 --- a/examples/Docker/apache2/django/docker-entrypoint.sh +++ b/examples/Docker/apache2/django/docker-entrypoint.sh @@ -14,8 +14,14 @@ then cp /var/www/acme2certifier/examples/apache_django_ssl.conf /etc/apache2/sites-enabled/acme2certifier_ssl.conf fi -# create ca_handler if not existing -if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] +# create ca_handler if: +# - ca_handler.py does not exists in volume AND +# - no entry hanlder_file: exists in acme_srv.cfg +# - define ca_handler defined under handler_file does not exists +if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ + ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ + [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ + )) then echo "no ca_handler.py found! creating from skeleton_ca_handler.py" cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py diff --git a/examples/Docker/apache2/wsgi/docker-entrypoint.sh b/examples/Docker/apache2/wsgi/docker-entrypoint.sh index 11ca53dd..905a7072 100644 --- a/examples/Docker/apache2/wsgi/docker-entrypoint.sh +++ b/examples/Docker/apache2/wsgi/docker-entrypoint.sh @@ -12,9 +12,16 @@ then cp /var/www/acme2certifier/examples/apache_wsgi_ssl.conf /etc/apache2/sites-enabled/acme2certifier_ssl.conf fi -# create ca_handler if not existing -if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] -then +# create ca_handler if: +# - ca_handler.py does not exists in volume AND +# - no entry hanlder_file: exists in acme_srv.cfg +# - define ca_handler defined under handler_file does not exists +if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ + ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ + [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ + )) +then + echo "no ca_handler.py found! creating from skeleton_ca_handler.py" cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py fi diff --git a/examples/Docker/nginx/django/docker-entrypoint.sh b/examples/Docker/nginx/django/docker-entrypoint.sh index 85334a15..d7841f9c 100644 --- a/examples/Docker/nginx/django/docker-entrypoint.sh +++ b/examples/Docker/nginx/django/docker-entrypoint.sh @@ -8,17 +8,22 @@ then fi # enable ssl if acme2certifier_cert.pem and acme2certifier_key.pem exist on volume -if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] +if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && \ + [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] && \ + [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] then - if [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] - then - cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf - ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf - fi + cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf + ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf fi -# create ca_handler if not existing -if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] +# create ca_handler if: +# - ca_handler.py does not exists in volume AND +# - no entry hanlder_file: exists in acme_srv.cfg +# - define ca_handler defined under handler_file does not exists +if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ + ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ + [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ + )) then echo "no ca_handler.py found! creating from skeleton_ca_handler.py" cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py diff --git a/examples/Docker/nginx/wsgi/docker-entrypoint.sh b/examples/Docker/nginx/wsgi/docker-entrypoint.sh index 62bc58d3..994d4a4d 100644 --- a/examples/Docker/nginx/wsgi/docker-entrypoint.sh +++ b/examples/Docker/nginx/wsgi/docker-entrypoint.sh @@ -3,22 +3,29 @@ # create acme-srv.cfg if not existing if [ ! -f /var/www/acme2certifier/volume/acme_srv.cfg ] then + echo "no acme_srv.cfg found! creating acme_srv.cfg" cp /var/www/acme2certifier/examples/acme_srv.cfg /var/www/acme2certifier/volume/ fi # enable ssl if acme2certifier_cert.pem and acme2certifier_key.pem exist on volume -if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] +if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && \ + [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] && \ + [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] then - if [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] - then - cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf - ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf - fi + cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf + ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf fi -# create ca_handler if not existing -if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] +# create ca_handler if: +# - ca_handler.py does not exists in volume AND +# - no entry hanlder_file: exists in acme_srv.cfg +# - define ca_handler defined under handler_file does not exists +if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ + ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ + [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ + )) then + echo "no ca_handler.py found! creating from skeleton_ca_handler.py" cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py fi From 3f0c94c593531ba61c5f5c6145e02543b8d39858 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 12 Jun 2021 08:32:43 +0200 Subject: [PATCH 46/51] [fix] unitests - openssl_ca_handler.py --- test/ca/root-ca-client.txt | 29 ++++++++++++++++++++++++++++- test/ca/sub-ca-client.txt | 25 ++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/test/ca/root-ca-client.txt b/test/ca/root-ca-client.txt index 317ca6a9..6507a5bc 100644 --- a/test/ca/root-ca-client.txt +++ b/test/ca/root-ca-client.txt @@ -1 +1,28 @@ -MIIEVDCCAjygAwIBAgIIDdwnBptoyOEwDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAxMHcm9vdC1j YTAeFw0yMDA2MDkxODAwMDBaFw0yMTA2MDkxODAwMDBaMBkxFzAVBgNVBAMTDnJvb3QtY2EtY2xp ZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm/ZNn21jP/VlBZGznfA5ZJ1Tqbew XOeea4OQAzhPkydPx9gStPi5rY+sXgt0W9XU6UAXZ6KVbM7rRjBhb5qya9Kb6pL1bjT4CbNCeePF CIp4EzKT336n4hc/JFJ1BvbWRnKyOrp2rl6YZCUt/kd9SCKLHNJIg5TA/F+AeHb5gVuixi5kbmFq xoqgzJT69XlyKZgZ565dT7MeehqSCUvhfY0t4oVMVNZ52OxwqQG9PiYHQdLRKQ/qZIHIYZq/yfJb +VLvDKv4NwoCncAZhS1tFMlmvVrA0UIScWtSxscYDV1QguaWUhSCJ7mm6S0rl78hHJjPl0Nqb4Zd RDrQmwOI0wIDAQABo4GmMIGjMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDPtim/8zhBX2jKiaUlL Nkt//tObMA4GA1UdDwEB/wQEAwID6DAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATAZBgNVHREEEjAQ gg5yb290LWNhLWNsaWVudDARBglghkgBhvhCAQEEBAMCBkAwHgYJYIZIAYb4QgENBBEWD3hjYSBj ZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEA28lUKlJv6PNOedFUnoxqxXkmIU2T/p0bBPOX ObcoonJpukViB586cMhILPSTa9Jh8GMDHwcIa85NIPginWVFRM1lnjIY4RWWM6k4HmaA2DW4D8Qi DpvAuwXN1RN5pjTZq0ixCagCfbGCzNNYJpsQO00s2ONtsLzMyXqWttzDCIC6DJ07PWmqnv6GM1FL SqXKXJoDKTxxt1LMe4xERJFG5ZOKffaHx0Aotz3l4P6D0J+9akP5g4IZB4B88ANBhDfyHMujNqvc bitOM9pqKuEngFZkQilLESkl19KtghKQ5gLP8HbqOXLYBhNu8hojadZ+fe1HvPAcgTduQOdBiHQw 1O4ISavOMmFncAVrbwVUmMdK4m+9BlPCw5umhI8MRIZQ5fECXO0Yu8JKdkeXVrOuxrV/eON3fJio i4NCuKLC77D09+ZNU7MwwykmEHyWS81UnFDbvuWNjvHsUgtDad7npGFOZvR5LD9PTenG0NmHp6hr 74DMkEHBEg3tReAsTuCS8yE5WFD1/Ic3yNIIPy/4W/6Lfb4eoKF2H0Rt4DieI910kJE0tLxXGC4V Wh/Vl8H7rSky4qtmoD1ZpjQhWoZcmdsTG4oKqcsGMMsKDOwV8BrSrG/RSvdNU6lRziaUEGowNvGY FVIxgukwkvsgbki36eda/JeAhdebEgfaxzozRnc= \ No newline at end of file +MIIFHjCCAwagAwIBAgIIcFUYZLICUHowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UE +AxMHcm9vdC1jYTAeFw0yMDA2MDkxNzE4MDBaFw0zMDA2MDkxNzE3MDBaMBExDzAN +BgNVBAMTBnN1Yi1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO2x +CXITgVcFJuqh5ibdBUwaNJgI3lBmG2aLjvIaBXbH3ocH6WsXO1d5i37PepArmTpG +fd+Ew3FvUmyiPzFO3WJSwgk096yoLVQHwAcxyuy1dBXemGFBm3v5ofTK+MyINxJP +PkRWbJLhSETofzCo/vbFkBqIkFoarh8uEwfxzhpDq3cWjROaJhHhT+6GsbDMGouL +za9J1HVs4Fn5fkmFxB9g7st5Z19TVIKCisPP4VQNmbhaWuHJMkaXDkaVAUcw6QQy +quwfdl78jndh14D8tFuoLZcRxT/cfQPmqhcjjkkTelMk/5OfYlk+1wjoAEToXDzG +HTkXS/zkGMdZeZFstXAFhy0THlSMO5RTuKwSXxIObvKKM2WdNVpnYOD5XaZnvFJx +5fQu13HiNrprQKQAssihKqz9iCeJ0xuwuIydkrmjXSU0KtyzSZXBgaaMSeRYx+dG +hVfv1f6U+MQjBq+QEbkuafcFs3TnuRcbbWA4H+T4cJK3krg9m9s1P2tTAFYuNDAR +Df6IgPPyeSglcMpKPqg7uZWR5e/0wQj29XLUgrkFoIPsLEML6aKTMOdiCUcdAdne +mkwcB7JIth+HAeSjNpW1lRb14QNxbf52qxN0X8HsDNYmg++rxxOOwEMzYuo7Ch1C +lzI0RGaRHHbkWymj+doyXvVwnV4ZZwRXXpeJmhmTAgMBAAGjeTB3MBIGA1UdEwEB +/wQIMAYBAf8CAQEwHQYDVR0OBBYEFIMnznmJq0PWTssJTOYznKF7gjN4MB8GA1Ud +IwQYMBaAFL/OiI9h7taWfyqsHzQwwiq3NBvOMA4GA1UdDwEB/wQEAwIBBjARBglg +hkgBhvhCAQEEBAMCAAcwDQYJKoZIhvcNAQELBQADggIBAJMwQ33+tL2yO+tePbDZ +b5ZiASeAI6FmHWLtTpx3YeDBXR1NFtMGR1jYiWO5Mc6BAmLC2KPevXt+VM7RWeQU +PlMKfcbxX5XdrhMWyC0HSvGQtg0/Ftc6do8Mj3wOIrmlskJPDX9s4VT0ersabRdZ +2Djkcyub5PipMcJcPR7IpnfLJLcK1/QxrAHZtdseUuOyvXelAoPWTPLk4uMxEzGk +lTDhqjCzVc3+sRJOwV9QQopOX3tB5vijAzC96jrRj90UNDZBt9IJu0sBIYro/a9O +AqxFbQXcsr6rUZgvktWgghqJOai/iidTCA0TM4SqJUuaok4guJmMTGc8mJZ+EfmV +8JPJ/8OaP2KU2VcMDzqN4/KeZt7+tfG7GB3h6l3D7M/q8qkSYYo2nzQ405EB/KVY +ohhw85RcJw3zqnziFuTmTTSqu4zOLlGFwSri7VgH3JfmgGWmjQ6B8wP3V0jKydFb +JaIM4PLPRZeCHfexJ3Iu2a174saShxBwBsfCVah+9j6PJ8Pvx8LzPW+WeyW56NpF +FamwsJJKqafvBMuZPjCR+burDPJh9Y7IrPZNDsgmBcUzB9BCxB1Qlj4fdkieuHJM +5m6jaOeUlnECprkyutyh5lEY0BVw5RO+v9SqtI/6cbFrclMcb1SpF5W0slEX3xTG +02BvBlCOKrZlqnp/jSdmAZ9s diff --git a/test/ca/sub-ca-client.txt b/test/ca/sub-ca-client.txt index 02a29e3e..a56c22e5 100644 --- a/test/ca/sub-ca-client.txt +++ b/test/ca/sub-ca-client.txt @@ -1 +1,24 @@ -MIIEQTCCAimgAwIBAgIIC8wwxUTvJqQwDQYJKoZIhvcNAQELBQAwETEPMA0GA1UEAxMGc3ViLWNhMB4XDTIwMDYwOTE3MTkwMFoXDTIxMDYwOTE3MTkwMFowGzEZMBcGA1UEAxMQY2xpZW50LmJhci5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJps2tk/d5pqv1gSeLnDBFQSzznY/iSBtzRNLlRWm6J7yOAERgGsbMBW7s5AhYRbuHuberlBtsyFyKenWvijo6r7DTOGiv2oBf7iCoCXYbNAqlvnP5inzp6ZmmgmxigLFbdlTfPQBkaytDzLAav1KLCmCof4DpQunsxdDjW0kBm8jRC7HY5bauxeFKQb2NcGmjlB3kQjZNHF52xG/GgkMIH7E0NJUhmsVfItSezkmFUQFhP2VqYYsiPRtvXlZqpzPISxn2InGcUaaBzJFO7RWif0IIsgzcyzqXvt8KEqeoI15gmd1G4lXPeyadXG8kzE8L+8f4J+gGgQSA1eR4VMkOMCAwEAAaOBkjCBjzAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRjovc4aaN6LCIE5E/ZgsLBH+3/WDAOBgNVHQ8BAf8EBAMCA+gwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBsGA1UdEQQUMBKCEGNsaWVudC5iYXIubG9jYWwwEQYJYIZIAYb4QgEBBAQDAgZAMA0GCSqGSIb3DQEBCwUAA4ICAQCZm5d3jc9oopD193bGwJFo8NNo1wzYvvqbK/lONy/JsisX1pERxN+EZyTB2CLxQ4yKZU9Xnx0fmcJExqoPLEva6hAMdOiSEsEs52yyL6gjMLHxJJfdXBiqMZetp+BCPf23rc96ONzyjURDCfsN4VMg7090e9yKpuyHKIOHStqMT+ZLvPcd+YiU4jMazoagauEW2mdpqyA8mN92qiphwo8QMCv3XZJWJ1PEwaCTGhBxlzMoaknWKzCD2YQ/yyGE4Ha8vBaymk1eh7txo5B53C0OpO0UT4WGUOZDP1GPySymqQfDO6R9BhBjyggsG5G9FA84tUqZJAKlGhPesQyIQBM4SZlQTJt/hP/cCoZ6BiibBdaZnLzOyH+NTJ9ou0hpmMp2LZiB8G2Igam7wdXySvQe9sxXXDDTKhxwqk7V+by2gS6asfcQjstQQeMN/iMrg3AtZt/Kl5WcHcwSjZAypHugPiwjr48WHvDS2lUKnbbDuiCxvc1TsPGG6Z+b/0aTwrps6yMeTRuDk3A8DYceHftrWZSOgg+5A2ISd58vPOHiamATVLXGJ1vnCP0Sm/Z4QCnIGfOvxltdAnrcA75MnefaOmQv9CrhwyBembugd9fPC/uFi/ESKGPuo6zLYwjFwLqwNe99UgU98iYz9rfdKNqJ6fWRolzz4AXqUHQ4Dc8eZA== \ No newline at end of file +MIIETjCCAjagAwIBAgIRAIG11e4S8ErJuwCYAKsoU3UwDQYJKoZIhvcNAQELBQAw +ETEPMA0GA1UEAxMGc3ViLWNhMB4XDTIxMDYxMjA2MjMzOFoXDTIzMDYwMjA2MjMz +OFowGTEXMBUGA1UEAwwOZm9vMS5iYXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQC0lk4lyEIa0VL/u5ic01Zo/o+gyYqFpU7xe+nbFgiKA+R1 +rqrzP/sR6xjHqS0Rkv/BcBXf81sp/+iDmwIQLVlBTkKdimqVHCJMAbTL8ZNpcLDa +RUce4liyX1cmczPTSqI/kcyEr8tKpYN+KzvKZZsNx2Pbgu7y7/70P2uSywiW+sqY +Z+X28KGFxq6wwENzJtweDVsbWql9LLtw6daF41UQg10auNlRL1nhW0SlWZh1zPPW +/0sa6C3xX28jjVh843b4ekkRNLXSEYQMTi0qYR2LomQ5aTlQ/hellf17UknfN2aA +2RH5D7Ek+mndj/rH21bxQg26KRmHlaJld9K1IfvJAgMBAAGjgZgwgZUwCwYDVR0P +BAQDAgXgMBkGA1UdEQQSMBCCDmZvbzEuYmFyLmxvY2FsMB0GA1UdDgQWBBReDKlE +Wwro02ljWMCi10HMqhDmbzAfBgNVHSMEGDAWgBSDJ855iatD1k7LCUzmM5yhe4Iz +eDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAN +BgkqhkiG9w0BAQsFAAOCAgEAhv7Jco6VjT25FuyOz/C0N5+q2M8sqjcDDYMwUTKX +VkIc7/lSsubL8z64eS4I5iBecNOlPXASMoMe0KbdrvzqItYgeisC08rnWQayuDr/ +dj2Y/v4WptZdTPc0pWZQ7LUSxcZaydMFsIKxtfO2HR84DqrUbpvDfVSP7/UiN2O0 +TbSBiEC6Xayu6IudGZ9naHTAXzTau6SejcbH+0jWZsDXd1SbDPd3a+ZcHbDLIZAz +sjcurleDPS54PIXjblOgMrsheDq/wzxKtvLOZEe8Gr6THwtX6uS0oQ72BFNGfZVV +PFiL/q0Dvj2FveBtv7k14QcBqHutE4pEpYb/kcU7cxCVgGlUw8Q8trYQhBB37X9d +OHjC2G8cyCeyVr+xfUE12wTKZDRIXjG3FMpKgeB4oNYPWA5m/1GBOGddhmogIB8G +XeenDcAjBdVOFuuOrMInHLnLD9w7iEiopfx+six3Nxpo3thDV4xdiTZsWp9ojZhQ +zW8haEQleJ3Xyl65UuZKHyrRJ0OWR4LRkNwJitG5F0MYg8bjgik/cHTwzIB0HXgn +aVeMBJY3sOkvCpAlTGZe1GL9foWIeFkprPG4cePrjtC3Mn8rHH0pIi1mdkcAIdex +Ydg/qlroKk2ROLXnX5LHmrM1CDZQphgyzLETdwXQdTBOJvc8FsDPhp5p+iqgT2e1 +6QI= From 66afa7b20bf227317b579f4f463d4dcfd219aec3 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 12 Jun 2021 09:17:00 +0200 Subject: [PATCH 47/51] [wf] disable pr-event in ca-handler workflow --- .github/workflows/ca_handler_tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ca_handler_tests.yml b/.github/workflows/ca_handler_tests.yml index f84341cd..310ba09b 100644 --- a/.github/workflows/ca_handler_tests.yml +++ b/.github/workflows/ca_handler_tests.yml @@ -2,8 +2,6 @@ name: CA handler Tests on: push: - pull_request: - branches: [ devel ] schedule: - cron: '0 2 * * 6' From 62463508da940bc675324b643858bfdd93b208b9 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sat, 12 Jun 2021 20:54:56 +0200 Subject: [PATCH 48/51] [fix] docker-entrypoint.sh for django-apache2 --- .../apache2/django/docker-entrypoint.sh | 48 +++++++++++++------ .../Docker/apache2/wsgi/docker-entrypoint.sh | 11 +++-- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/examples/Docker/apache2/django/docker-entrypoint.sh b/examples/Docker/apache2/django/docker-entrypoint.sh index 7d5f9b96..f74589d7 100644 --- a/examples/Docker/apache2/django/docker-entrypoint.sh +++ b/examples/Docker/apache2/django/docker-entrypoint.sh @@ -3,27 +3,21 @@ # create acme-srv.cfg if not existing if [ ! -f /var/www/acme2certifier/volume/acme_srv.cfg ] then - echo "no acme_srv.cfg found! creating acme_srv.cfg" + echo "no acme_srv.cfg found! creating acme_srv.cfg" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/acme_srv.cfg /var/www/acme2certifier/volume/ fi # enable tls if acme2certifier.pem exists on volume if [ -f /var/www/acme2certifier/volume/acme2certifier.pem ] then - echo "found acme2certifier.pem! enalbe TLS" + echo "found acme2certifier.pem! enalbe TLS" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/apache_django_ssl.conf /etc/apache2/sites-enabled/acme2certifier_ssl.conf fi -# create ca_handler if: -# - ca_handler.py does not exists in volume AND -# - no entry hanlder_file: exists in acme_srv.cfg -# - define ca_handler defined under handler_file does not exists -if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ - ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ - [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ - )) +# create ca_handler if not existing +if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] then - echo "no ca_handler.py found! creating from skeleton_ca_handler.py" + echo "no ca_handler.py found! creating from skeleton_ca_handler.py" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py fi @@ -49,7 +43,7 @@ fi # create settings.py if not existing if [ ! -f /var/www/acme2certifier/volume/settings.py ] then - echo "no settings.py found! copy settings.py" + echo "no settings.py found! copy settings.py" >> /proc/1/fd/1 egrep -v '(# SECURITY WARNING: keep the secret key used in production secret!|^SECRET_KEY)' /var/www/acme2certifier/examples/django/acme2certifier/settings.py > /var/www/acme2certifier/volume/settings.py ## generate SECRET_KEY echo "generating SECRET_KEY" @@ -58,21 +52,45 @@ then # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '${DJANGO_SECRET_KEY}' EOF - echo "adding '*' wildcard hosts in settings.py" + echo "adding '*' wildcard hosts in settings.py" >> /proc/1/fd/1 sed -i "s/ALLOWED_HOSTS = \['127.0.0.1'\]/ALLOWED_HOSTS = \['127.0.0.1','*'\]/g" /var/www/acme2certifier/volume/settings.py fi -# apply migration or create a symlink for settings.py +# create migrations if not existing +if [ ! -d /var/www/acme2certifier/volume/migrations ] +then + echo "no acme_srv.cfg found! creating acme_srv.cfg" >> /proc/1/fd/1 + cp -R /var/www/acme2certifier/examples/django/acme/migrations /var/www/acme2certifier/volume/ + # mkdir -p /var/www/acme2certifier/volume/migrations +fi + +# create a symlink for migrations +if [ ! -L /var/www/acme2certifier/acme/migrations ] +then + if [ -d /var/www/acme2certifier/volume/migrations ] + then + echo "delete migration directory" >> /proc/1/fd/1 + rm -rf /var/www/acme2certifier/acme/migrations + fi + + echo "create symlink for migration directory" >> /proc/1/fd/1 + ln -s /var/www/acme2certifier/volume/migrations /var/www/acme2certifier/acme/ +fi + +# apply migrations or create a symlink for settings.py if [ -L /var/www/acme2certifier/acme2certifier/settings.py ] then # apply migrations + echo "apply migrations" >> /proc/1/fd/1 python3 /var/www/acme2certifier/tools/django_update.py python3 manage.py loaddata acme/fixture/status.yaml else ln -s /var/www/acme2certifier/volume/settings.py /var/www/acme2certifier/acme2certifier/settings.py + python3 /var/www/acme2certifier/tools/django_update.py + python3 manage.py loaddata acme/fixture/status.yaml fi -chown -R www-data /var/www/acme2certifier/volume +chown -R www-data.www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" diff --git a/examples/Docker/apache2/wsgi/docker-entrypoint.sh b/examples/Docker/apache2/wsgi/docker-entrypoint.sh index 905a7072..d1370991 100644 --- a/examples/Docker/apache2/wsgi/docker-entrypoint.sh +++ b/examples/Docker/apache2/wsgi/docker-entrypoint.sh @@ -1,16 +1,18 @@ #!/bin/bash # create acme-srv.cfg if not existing -if [ ! -f /var/www/acme2certifier/volume/acme_srv.cfg ] -then +if [ ! -f /var/www/acme2certifier/volume/acme_srv.cfg ] +then + echo "no acme_srv.cfg found! creating acme_srv.cfg" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/acme_srv.cfg /var/www/acme2certifier/volume/ fi # enable ssl if acme2certifier.pm exists on volume if [ -f /var/www/acme2certifier/volume/acme2certifier.pem ] then + echo "found acme2certifier.pem! enalbe TLS" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/apache_wsgi_ssl.conf /etc/apache2/sites-enabled/acme2certifier_ssl.conf -fi +fi # create ca_handler if: # - ca_handler.py does not exists in volume AND @@ -21,7 +23,7 @@ if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ )) then - echo "no ca_handler.py found! creating from skeleton_ca_handler.py" + echo "no ca_handler.py found! creating from skeleton_ca_handler.py" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py fi @@ -50,4 +52,3 @@ fi chown -R www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" - From 4af6d3adf21a8cc56120f357bf0eb4940ae95be0 Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 13 Jun 2021 08:03:36 +0200 Subject: [PATCH 49/51] [fix] docker-entrypoint.sh for django-nginx --- CHANGES.md | 1 + .../Docker/nginx/django/docker-entrypoint.sh | 53 +++++++++++++------ .../Docker/nginx/wsgi/docker-entrypoint.sh | 4 +- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ef99c824..dea46442 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,7 @@ and pick the appropriate release branch. **Bugfixes**: +- django migrations files will get stored on volume - avoidance of KU/EKU duplicates when using templates in xca_ca_handler - alpn challenge handling in django deployments - fix for handling of empty challenges diff --git a/examples/Docker/nginx/django/docker-entrypoint.sh b/examples/Docker/nginx/django/docker-entrypoint.sh index d7841f9c..af01a793 100644 --- a/examples/Docker/nginx/django/docker-entrypoint.sh +++ b/examples/Docker/nginx/django/docker-entrypoint.sh @@ -3,29 +3,24 @@ # create acme-srv.cfg if not existing if [ ! -f /var/www/acme2certifier/volume/acme_srv.cfg ] then - echo "no acme_srv.cfg found! creating acme_srv.cfg" + echo "no acme_srv.cfg found! creating acme_srv.cfg" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/acme_srv.cfg /var/www/acme2certifier/volume/ fi # enable ssl if acme2certifier_cert.pem and acme2certifier_key.pem exist on volume -if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && \ - [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] && \ - [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] +if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] then - cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf - ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf + if [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] + then + cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf + ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf + fi fi -# create ca_handler if: -# - ca_handler.py does not exists in volume AND -# - no entry hanlder_file: exists in acme_srv.cfg -# - define ca_handler defined under handler_file does not exists -if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ - ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ - [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ - )) +# create ca_handler if not existing +if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] then - echo "no ca_handler.py found! creating from skeleton_ca_handler.py" + echo "no ca_handler.py found! creating from skeleton_ca_handler.py" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py fi @@ -60,10 +55,32 @@ then # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '${DJANGO_SECRET_KEY}' EOF - echo "adding '*' wildcard hosts in settings.py" + echo "adding '*' wildcard hosts in settings.py" >> /proc/1/fd/1 sed -i "s/ALLOWED_HOSTS = \['127.0.0.1'\]/ALLOWED_HOSTS = \['127.0.0.1','*'\]/g" /var/www/acme2certifier/volume/settings.py fi +# create migrations if not existing +if [ ! -d /var/www/acme2certifier/volume/migrations ] +then + echo "no acme_srv.cfg found! creating acme_srv.cfg" >> /proc/1/fd/1 + cp -R /var/www/acme2certifier/examples/django/acme/migrations /var/www/acme2certifier/volume/ + # mkdir -p /var/www/acme2certifier/volume/migrations +fi + +# create a symlink for migrations +if [ ! -L /var/www/acme2certifier/acme/migrations ] +then + if [ -d /var/www/acme2certifier/volume/migrations ] + then + echo "delete migration directory" >> /proc/1/fd/1 + rm -rf /var/www/acme2certifier/acme/migrations + fi + + echo "create symlink for migration directory" >> /proc/1/fd/1 + ln -s /var/www/acme2certifier/volume/migrations /var/www/acme2certifier/acme/ +fi + + # apply migration or create a symlink for settings.py if [ -L /var/www/acme2certifier/acme2certifier/settings.py ] then @@ -72,9 +89,11 @@ then python3 manage.py loaddata acme/fixture/status.yaml else ln -s /var/www/acme2certifier/volume/settings.py /var/www/acme2certifier/acme2certifier/settings.py + python3 /var/www/acme2certifier/tools/django_update.py + python3 manage.py loaddata acme/fixture/status.yaml fi -chown -R www-data /var/www/acme2certifier/volume +chown -R www-data.www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" diff --git a/examples/Docker/nginx/wsgi/docker-entrypoint.sh b/examples/Docker/nginx/wsgi/docker-entrypoint.sh index 994d4a4d..0c85da88 100644 --- a/examples/Docker/nginx/wsgi/docker-entrypoint.sh +++ b/examples/Docker/nginx/wsgi/docker-entrypoint.sh @@ -3,7 +3,7 @@ # create acme-srv.cfg if not existing if [ ! -f /var/www/acme2certifier/volume/acme_srv.cfg ] then - echo "no acme_srv.cfg found! creating acme_srv.cfg" + echo "no acme_srv.cfg found! creating acme_srv.cfg" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/acme_srv.cfg /var/www/acme2certifier/volume/ fi @@ -25,7 +25,7 @@ if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ )) then - echo "no ca_handler.py found! creating from skeleton_ca_handler.py" + echo "no ca_handler.py found! creating from skeleton_ca_handler.py" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py fi From 53a3587340aab8343de751093038a842fc54f60c Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 13 Jun 2021 08:33:14 +0200 Subject: [PATCH 50/51] [fix] dont overwrite ownership on volume --- CHANGES.md | 2 ++ .../apache2/django/docker-entrypoint.sh | 20 ++++++++++------ .../Docker/apache2/wsgi/docker-entrypoint.sh | 6 ++--- .../Docker/nginx/django/docker-entrypoint.sh | 23 +++++++++++-------- .../Docker/nginx/wsgi/docker-entrypoint.sh | 2 +- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dea46442..afae415c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,8 @@ and pick the appropriate release branch. **Bugfixes**: +- don't overwrite group ownership for volume folder +- don't copy ca_handler file if a valid ca_handler was defined under `CAhandler` section in acme_srv.cfg - django migrations files will get stored on volume - avoidance of KU/EKU duplicates when using templates in xca_ca_handler - alpn challenge handling in django deployments diff --git a/examples/Docker/apache2/django/docker-entrypoint.sh b/examples/Docker/apache2/django/docker-entrypoint.sh index f74589d7..e47c4d34 100644 --- a/examples/Docker/apache2/django/docker-entrypoint.sh +++ b/examples/Docker/apache2/django/docker-entrypoint.sh @@ -10,12 +10,18 @@ fi # enable tls if acme2certifier.pem exists on volume if [ -f /var/www/acme2certifier/volume/acme2certifier.pem ] then - echo "found acme2certifier.pem! enalbe TLS" >> /proc/1/fd/1 + echo "found acme2certifier.pem! enable TLS" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/apache_django_ssl.conf /etc/apache2/sites-enabled/acme2certifier_ssl.conf fi -# create ca_handler if not existing -if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] +# create ca_handler if: +# - ca_handler.py does not exists in volume AND +# - no entry handler_file: exists in acme_srv.cfg +# - define ca_handler defined under handler_file does not exists +if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ + ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ + [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ + )) then echo "no ca_handler.py found! creating from skeleton_ca_handler.py" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py @@ -69,9 +75,9 @@ if [ ! -L /var/www/acme2certifier/acme/migrations ] then if [ -d /var/www/acme2certifier/volume/migrations ] then - echo "delete migration directory" >> /proc/1/fd/1 + echo "delete migration directory" >> /proc/1/fd/1 rm -rf /var/www/acme2certifier/acme/migrations - fi + fi echo "create symlink for migration directory" >> /proc/1/fd/1 ln -s /var/www/acme2certifier/volume/migrations /var/www/acme2certifier/acme/ @@ -87,10 +93,10 @@ then else ln -s /var/www/acme2certifier/volume/settings.py /var/www/acme2certifier/acme2certifier/settings.py python3 /var/www/acme2certifier/tools/django_update.py - python3 manage.py loaddata acme/fixture/status.yaml + python3 manage.py loaddata acme/fixture/status.yaml fi -chown -R www-data.www-data /var/www/acme2certifier/volume +chown -R www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" diff --git a/examples/Docker/apache2/wsgi/docker-entrypoint.sh b/examples/Docker/apache2/wsgi/docker-entrypoint.sh index d1370991..cb062cb3 100644 --- a/examples/Docker/apache2/wsgi/docker-entrypoint.sh +++ b/examples/Docker/apache2/wsgi/docker-entrypoint.sh @@ -7,16 +7,16 @@ then cp /var/www/acme2certifier/examples/acme_srv.cfg /var/www/acme2certifier/volume/ fi -# enable ssl if acme2certifier.pm exists on volume +# enable tls if acme2certifier.pm exists on volume if [ -f /var/www/acme2certifier/volume/acme2certifier.pem ] then - echo "found acme2certifier.pem! enalbe TLS" >> /proc/1/fd/1 + echo "found acme2certifier.pem! enable TLS" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/apache_wsgi_ssl.conf /etc/apache2/sites-enabled/acme2certifier_ssl.conf fi # create ca_handler if: # - ca_handler.py does not exists in volume AND -# - no entry hanlder_file: exists in acme_srv.cfg +# - no entry handler_file: exists in acme_srv.cfg # - define ca_handler defined under handler_file does not exists if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ diff --git a/examples/Docker/nginx/django/docker-entrypoint.sh b/examples/Docker/nginx/django/docker-entrypoint.sh index af01a793..19f9fa06 100644 --- a/examples/Docker/nginx/django/docker-entrypoint.sh +++ b/examples/Docker/nginx/django/docker-entrypoint.sh @@ -8,17 +8,22 @@ then fi # enable ssl if acme2certifier_cert.pem and acme2certifier_key.pem exist on volume -if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] +if [ -f /var/www/acme2certifier/volume/acme2certifier_cert.pem ] && \ + [ -f /var/www/acme2certifier/volume/acme2certifier_key.pem ] && \ + [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] then - if [ ! -f /etc/nginx/sites-available/acme_ssl.conf ] - then - cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf - ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf - fi + cp /var/www/acme2certifier/examples/nginx/nginx_acme_ssl.conf /etc/nginx/sites-available/acme_ssl.conf + ln -s /etc/nginx/sites-available/acme_ssl.conf /etc/nginx/sites-enabled/acme_ssl.conf fi -# create ca_handler if not existing -if [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] +# create ca_handler if: +# - ca_handler.py does not exists in volume AND +# - no entry handler_file: exists in acme_srv.cfg +# - define ca_handler defined under handler_file does not exists +if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ + ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ + [ -f $(grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg | awk -F":" '{print $2}') ] \ + )) then echo "no ca_handler.py found! creating from skeleton_ca_handler.py" >> /proc/1/fd/1 cp /var/www/acme2certifier/examples/ca_handler/skeleton_ca_handler.py /var/www/acme2certifier/volume/ca_handler.py @@ -93,7 +98,7 @@ else python3 manage.py loaddata acme/fixture/status.yaml fi -chown -R www-data.www-data /var/www/acme2certifier/volume +chown -R www-data /var/www/acme2certifier/volume chmod u+s /var/www/acme2certifier/volume/ exec "$@" diff --git a/examples/Docker/nginx/wsgi/docker-entrypoint.sh b/examples/Docker/nginx/wsgi/docker-entrypoint.sh index 0c85da88..676da3dd 100644 --- a/examples/Docker/nginx/wsgi/docker-entrypoint.sh +++ b/examples/Docker/nginx/wsgi/docker-entrypoint.sh @@ -18,7 +18,7 @@ fi # create ca_handler if: # - ca_handler.py does not exists in volume AND -# - no entry hanlder_file: exists in acme_srv.cfg +# - no entry handler_file: exists in acme_srv.cfg # - define ca_handler defined under handler_file does not exists if ( [ ! -f /var/www/acme2certifier/volume/ca_handler.py ] && \ ! ( grep -E '^handler_file:' /var/www/acme2certifier/volume/acme_srv.cfg &> /dev/null && \ From a9b90dc8f6bbda6e4f6520dd460b07e84a6452fa Mon Sep 17 00:00:00 2001 From: grindsa Date: Sun, 13 Jun 2021 15:07:21 +0200 Subject: [PATCH 51/51] [rel] bump to v0.16 --- SECURITY.md | 6 +++--- acme/version.py | 2 +- examples/django/acme/fixture/status.yaml | 2 +- tools/django_update.py | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 1d307fe4..05cf0621 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,9 +6,9 @@ | Version | Supported | | ------- | ------------------ | -| 0.15.x | :white_check_mark: | -| 0.14.x | :white_check_mark: | -| < 0.14 | :x: | +| 0.16.x | :white_check_mark: | +| 0.15.x | :white_check_mark: | +| < 0.15 | :x: | ## Reporting a Vulnerability diff --git a/acme/version.py b/acme/version.py index 6a287c89..55abcf09 100644 --- a/acme/version.py +++ b/acme/version.py @@ -3,5 +3,5 @@ # 1) we don't load dependencies by storing it in __init__.py # 2) we can import it in setup.py for the same reason # 3) we can import it into your module module -__version__ = '0.15.3' +__version__ = '0.16' __dbversion__ = '0.15.3' diff --git a/examples/django/acme/fixture/status.yaml b/examples/django/acme/fixture/status.yaml index 374502ec..f5335e0d 100644 --- a/examples/django/acme/fixture/status.yaml +++ b/examples/django/acme/fixture/status.yaml @@ -34,4 +34,4 @@ pk: 1 fields: name: dbversion - value: 0.15 + value: 0.15.3 diff --git a/tools/django_update.py b/tools/django_update.py index 5dc0e77f..d63ebe7b 100644 --- a/tools/django_update.py +++ b/tools/django_update.py @@ -10,7 +10,7 @@ from django.conf import settings from acme.models import Status, Housekeeping from django.core.management import call_command -from acme.version import __version__ +from acme.version import __dbversion__ if __name__ == '__main__': @@ -24,5 +24,5 @@ OBJ, _CREATED = Status.objects.update_or_create(name=status, defaults={'name': status}) # update dbversion - print('update dbversion to {0}...'.format(__version__)) - OBJ, _CREATED = Housekeeping.objects.update_or_create(name='dbversion', defaults={'name': 'dbversion', 'value': __version__}) + print('update dbversion to {0}...'.format(__dbversion__)) + OBJ, _CREATED = Housekeeping.objects.update_or_create(name='dbversion', defaults={'name': 'dbversion', 'value': __dbversion__})