mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-24 03:11:24 -07:00
java_keystore: fix keystore type (#2516)
* fix keystore type; update unit tests * add changelog fragment * document new param 'keystore_type' * add keystore_type support (backward compatible) * check JKS format with magic bytes * update integration tests * revert first changes in unit tests * update changelog fragment * fix magic bytes for python2/python3 * fix integration tests (irrelevant check_mode) * fix unit test (keystore removed before failure => changed=true) * fix typo * fix spelling * shorten a branch * mock is_jks_or_pkcs12 * fix function path in unit tests * Apply suggestions from code review (spelling) Co-authored-by: Ajpantuso <ajpantuso@gmail.com> * rename a method (module + unit tests) * move ArgumentSpec class content to main() * refactor create() to not loose existing keystore in case of error * update unit tests * add integration test (error handling) * fix keystore backup cleanup Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
This commit is contained in:
parent
2fb0877577
commit
199ead85d0
4 changed files with 308 additions and 69 deletions
|
@ -14,7 +14,25 @@ from ansible_collections.community.general.tests.unit.plugins.modules.utils impo
|
|||
from ansible_collections.community.general.tests.unit.compat.mock import patch
|
||||
from ansible_collections.community.general.tests.unit.compat.mock import Mock
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.general.plugins.modules.system.java_keystore import JavaKeystore, ArgumentSpec
|
||||
from ansible_collections.community.general.plugins.modules.system.java_keystore import JavaKeystore
|
||||
|
||||
|
||||
module_argument_spec = dict(
|
||||
name=dict(type='str', required=True),
|
||||
dest=dict(type='path', required=True),
|
||||
certificate=dict(type='str', no_log=True),
|
||||
certificate_path=dict(type='path'),
|
||||
private_key=dict(type='str', no_log=True),
|
||||
private_key_path=dict(type='path', no_log=False),
|
||||
private_key_passphrase=dict(type='str', no_log=True),
|
||||
password=dict(type='str', required=True, no_log=True),
|
||||
ssl_backend=dict(type='str', default='openssl', choices=['openssl', 'cryptography']),
|
||||
keystore_type=dict(type='str', choices=['jks', 'pkcs12']),
|
||||
force=dict(type='bool', default=False),
|
||||
)
|
||||
module_supports_check_mode = True
|
||||
module_choose_between = (['certificate', 'certificate_path'],
|
||||
['private_key', 'private_key_path'])
|
||||
|
||||
|
||||
class TestCreateJavaKeystore(ModuleTestCase):
|
||||
|
@ -25,11 +43,13 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
super(TestCreateJavaKeystore, self).setUp()
|
||||
|
||||
orig_exists = os.path.exists
|
||||
self.spec = ArgumentSpec()
|
||||
self.mock_create_file = patch('ansible_collections.community.general.plugins.modules.system.java_keystore.create_file')
|
||||
self.mock_create_path = patch('ansible_collections.community.general.plugins.modules.system.java_keystore.create_path')
|
||||
self.mock_current_type = patch('ansible_collections.community.general.plugins.modules.system.java_keystore.JavaKeystore.current_type')
|
||||
self.mock_run_command = patch('ansible.module_utils.basic.AnsibleModule.run_command')
|
||||
self.mock_get_bin_path = patch('ansible.module_utils.basic.AnsibleModule.get_bin_path')
|
||||
self.mock_preserved_copy = patch('ansible.module_utils.basic.AnsibleModule.preserved_copy')
|
||||
self.mock_atomic_move = patch('ansible.module_utils.basic.AnsibleModule.atomic_move')
|
||||
self.mock_os_path_exists = patch('os.path.exists',
|
||||
side_effect=lambda path: True if path == '/path/to/keystore.jks' else orig_exists(path))
|
||||
self.mock_selinux_context = patch('ansible.module_utils.basic.AnsibleModule.selinux_context',
|
||||
|
@ -38,8 +58,11 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
side_effect=lambda path: (False, None))
|
||||
self.run_command = self.mock_run_command.start()
|
||||
self.get_bin_path = self.mock_get_bin_path.start()
|
||||
self.preserved_copy = self.mock_preserved_copy.start()
|
||||
self.atomic_move = self.mock_atomic_move.start()
|
||||
self.create_file = self.mock_create_file.start()
|
||||
self.create_path = self.mock_create_path.start()
|
||||
self.current_type = self.mock_current_type.start()
|
||||
self.selinux_context = self.mock_selinux_context.start()
|
||||
self.is_special_selinux_path = self.mock_is_special_selinux_path.start()
|
||||
self.os_path_exists = self.mock_os_path_exists.start()
|
||||
|
@ -49,8 +72,11 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
super(TestCreateJavaKeystore, self).tearDown()
|
||||
self.mock_create_file.stop()
|
||||
self.mock_create_path.stop()
|
||||
self.mock_current_type.stop()
|
||||
self.mock_run_command.stop()
|
||||
self.mock_get_bin_path.stop()
|
||||
self.mock_preserved_copy.stop()
|
||||
self.mock_atomic_move.stop()
|
||||
self.mock_selinux_context.stop()
|
||||
self.mock_is_special_selinux_path.stop()
|
||||
self.mock_os_path_exists.stop()
|
||||
|
@ -65,8 +91,10 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
with patch('os.remove', return_value=True):
|
||||
|
@ -96,8 +124,10 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
module.exit_json = Mock()
|
||||
|
@ -106,7 +136,7 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
with patch('os.remove', return_value=True):
|
||||
self.create_path.side_effect = ['/tmp/tmp1cyp12xa']
|
||||
self.create_file.side_effect = ['/tmp/tmpvalcrt32', '/tmp/tmpwh4key0c', '']
|
||||
self.run_command.side_effect = [(1, '', ''), (0, '', '')]
|
||||
self.run_command.side_effect = [(1, '', 'Oops'), (0, '', '')]
|
||||
self.get_bin_path.side_effect = ['keytool', 'openssl', '']
|
||||
jks = JavaKeystore(module)
|
||||
jks.create()
|
||||
|
@ -118,6 +148,7 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
"-passout", "stdin",
|
||||
"-passin", "stdin"],
|
||||
msg='',
|
||||
err='Oops',
|
||||
rc=1
|
||||
)
|
||||
|
||||
|
@ -131,8 +162,10 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
module.exit_json = Mock()
|
||||
|
@ -141,7 +174,7 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
with patch('os.remove', return_value=True):
|
||||
self.create_path.side_effect = ['/tmp/tmp1cyp12xa']
|
||||
self.create_file.side_effect = ['/tmp/tmpvalcrt32', '/tmp/tmpwh4key0c', '']
|
||||
self.run_command.side_effect = [(1, '', ''), (0, '', '')]
|
||||
self.run_command.side_effect = [(1, '', 'Oops'), (0, '', '')]
|
||||
self.get_bin_path.side_effect = ['keytool', 'openssl', '']
|
||||
jks = JavaKeystore(module)
|
||||
jks.create()
|
||||
|
@ -152,6 +185,7 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
"-out", "/tmp/tmp1cyp12xa",
|
||||
"-passout", "stdin"],
|
||||
msg='',
|
||||
err='Oops',
|
||||
rc=1
|
||||
)
|
||||
|
||||
|
@ -165,8 +199,10 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
module.exit_json = Mock()
|
||||
|
@ -175,7 +211,7 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
with patch('os.remove', return_value=True):
|
||||
self.create_path.side_effect = ['/tmp/tmpgrzm2ah7']
|
||||
self.create_file.side_effect = ['/tmp/etacifitrec', '/tmp/yek_etavirp', '']
|
||||
self.run_command.side_effect = [(0, '', ''), (1, '', '')]
|
||||
self.run_command.side_effect = [(0, '', ''), (1, '', 'Oops')]
|
||||
self.get_bin_path.side_effect = ['keytool', 'openssl', '']
|
||||
jks = JavaKeystore(module)
|
||||
jks.create()
|
||||
|
@ -185,6 +221,7 @@ class TestCreateJavaKeystore(ModuleTestCase):
|
|||
"-srckeystore", "/tmp/tmpgrzm2ah7", "-srcstoretype", "pkcs12", "-alias", "test",
|
||||
"-noprompt"],
|
||||
msg='',
|
||||
err='Oops',
|
||||
rc=1
|
||||
)
|
||||
|
||||
|
@ -195,20 +232,28 @@ class TestCertChanged(ModuleTestCase):
|
|||
def setUp(self):
|
||||
"""Setup."""
|
||||
super(TestCertChanged, self).setUp()
|
||||
self.spec = ArgumentSpec()
|
||||
self.mock_create_file = patch('ansible_collections.community.general.plugins.modules.system.java_keystore.create_file')
|
||||
self.mock_current_type = patch('ansible_collections.community.general.plugins.modules.system.java_keystore.JavaKeystore.current_type')
|
||||
self.mock_run_command = patch('ansible.module_utils.basic.AnsibleModule.run_command')
|
||||
self.mock_get_bin_path = patch('ansible.module_utils.basic.AnsibleModule.get_bin_path')
|
||||
self.mock_preserved_copy = patch('ansible.module_utils.basic.AnsibleModule.preserved_copy')
|
||||
self.mock_atomic_move = patch('ansible.module_utils.basic.AnsibleModule.atomic_move')
|
||||
self.run_command = self.mock_run_command.start()
|
||||
self.create_file = self.mock_create_file.start()
|
||||
self.get_bin_path = self.mock_get_bin_path.start()
|
||||
self.current_type = self.mock_current_type.start()
|
||||
self.preserved_copy = self.mock_preserved_copy.start()
|
||||
self.atomic_move = self.mock_atomic_move.start()
|
||||
|
||||
def tearDown(self):
|
||||
"""Teardown."""
|
||||
super(TestCertChanged, self).tearDown()
|
||||
self.mock_create_file.stop()
|
||||
self.mock_current_type.stop()
|
||||
self.mock_run_command.stop()
|
||||
self.mock_get_bin_path.stop()
|
||||
self.mock_preserved_copy.stop()
|
||||
self.mock_atomic_move.stop()
|
||||
|
||||
def test_cert_unchanged_same_fingerprint(self):
|
||||
set_module_args(dict(
|
||||
|
@ -220,14 +265,17 @@ class TestCertChanged(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
with patch('os.remove', return_value=True):
|
||||
self.create_file.side_effect = ['/tmp/placeholder', '']
|
||||
self.run_command.side_effect = [(0, 'foo=abcd:1234:efgh', ''), (0, 'SHA256: abcd:1234:efgh', '')]
|
||||
self.get_bin_path.side_effect = ['keytool', 'openssl', '']
|
||||
self.current_type.side_effect = ['jks']
|
||||
jks = JavaKeystore(module)
|
||||
result = jks.cert_changed()
|
||||
self.assertFalse(result, 'Fingerprint is identical')
|
||||
|
@ -242,19 +290,22 @@ class TestCertChanged(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
with patch('os.remove', return_value=True):
|
||||
self.create_file.side_effect = ['/tmp/placeholder', '']
|
||||
self.run_command.side_effect = [(0, 'foo=abcd:1234:efgh', ''), (0, 'SHA256: wxyz:9876:stuv', '')]
|
||||
self.get_bin_path.side_effect = ['keytool', 'openssl', '']
|
||||
self.current_type.side_effect = ['jks']
|
||||
jks = JavaKeystore(module)
|
||||
result = jks.cert_changed()
|
||||
self.assertTrue(result, 'Fingerprint mismatch')
|
||||
|
||||
def test_cert_changed_fail_alias_does_not_exist(self):
|
||||
def test_cert_changed_alias_does_not_exist(self):
|
||||
set_module_args(dict(
|
||||
certificate='cert-foo',
|
||||
private_key='private-foo',
|
||||
|
@ -264,8 +315,10 @@ class TestCertChanged(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
with patch('os.remove', return_value=True):
|
||||
|
@ -287,8 +340,10 @@ class TestCertChanged(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
with patch('os.remove', return_value=True):
|
||||
|
@ -310,8 +365,10 @@ class TestCertChanged(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
module.exit_json = Mock()
|
||||
|
@ -321,6 +378,7 @@ class TestCertChanged(ModuleTestCase):
|
|||
self.create_file.side_effect = ['/tmp/tmpdj6bvvme', '']
|
||||
self.run_command.side_effect = [(1, '', 'Oops'), (0, 'SHA256: wxyz:9876:stuv', '')]
|
||||
self.get_bin_path.side_effect = ['keytool', 'openssl', '']
|
||||
self.current_type.side_effect = ['jks']
|
||||
jks = JavaKeystore(module)
|
||||
jks.cert_changed()
|
||||
module.fail_json.assert_called_once_with(
|
||||
|
@ -340,8 +398,10 @@ class TestCertChanged(ModuleTestCase):
|
|||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
argument_spec=module_argument_spec,
|
||||
supports_check_mode=module_supports_check_mode,
|
||||
mutually_exclusive=module_choose_between,
|
||||
required_one_of=module_choose_between
|
||||
)
|
||||
|
||||
module.exit_json = Mock()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue