1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02: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:
quidame 2021-06-27 14:56:43 +02:00 committed by GitHub
parent 2fb0877577
commit 199ead85d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 308 additions and 69 deletions

View file

@ -0,0 +1,4 @@
---
bugfixes:
- "java_keystore - add parameter ``keystore_type`` to control output file format and override ``keytool``'s
default, which depends on Java version (https://github.com/ansible-collections/community.general/issues/2515)."

View file

@ -1,8 +1,8 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2016, Guillaume Grossetie <ggrossetie@yuzutech.fr>
# Copyright: (c) 2021, quidame <quidame@poivron.org>
# Copyright: (c) 2016, Guillaume Grossetie <ggrossetie@yuzutech.fr>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
@ -97,6 +97,24 @@ options:
- openssl
- cryptography
version_added: 3.1.0
keystore_type:
description:
- Type of the Java keystore.
- When this option is omitted and the keystore doesn't already exist, the
behavior follows C(keytool)'s default store type which depends on
Java version; C(pkcs12) since Java 9 and C(jks) prior (may also
be C(pkcs12) if new default has been backported to this version).
- When this option is omitted and the keystore already exists, the current
type is left untouched, unless another option leads to overwrite the
keystore (in that case, this option behaves like for keystore creation).
- When I(keystore_type) is set, the keystore is created with this type if
it doesn't already exist, or is overwritten to match the given type in
case of mismatch.
type: str
choices:
- jks
- pkcs12
version_added: 3.3.0
requirements:
- openssl in PATH (when I(ssl_backend=openssl))
- keytool in PATH
@ -107,12 +125,16 @@ author:
extends_documentation_fragment:
- files
seealso:
- module: community.crypto.openssl_pkcs12
- module: community.general.java_cert
notes:
- I(certificate) and I(private_key) require that their contents are available
on the controller (either inline in a playbook, or with the C(file) lookup),
while I(certificate_path) and I(private_key_path) require that the files are
available on the target host.
- By design, any change of a value of options I(keystore_type), I(name) or
I(password), as well as changes of key or certificate materials will cause
the existing I(dest) to be overwritten.
'''
EXAMPLES = '''
@ -156,6 +178,12 @@ msg:
type: str
sample: "Unable to find the current certificate fingerprint in ..."
err:
description: Output from stderr of keytool/openssl command after error of given command.
returned: failure
type: str
sample: "Keystore password is too short - must be at least 6 characters\n"
rc:
description: keytool/openssl command execution return value
returned: changed and failure
@ -176,7 +204,7 @@ import tempfile
from ansible.module_utils.six import PY2
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.common.text.converters import to_bytes, to_native
try:
from cryptography.hazmat.primitives.serialization.pkcs12 import serialize_key_and_certificates
@ -201,6 +229,7 @@ except ImportError:
class JavaKeystore:
def __init__(self, module):
self.module = module
self.result = dict()
self.keytool_bin = module.get_bin_path('keytool', True)
@ -211,6 +240,7 @@ class JavaKeystore:
self.password = module.params['password']
self.private_key = module.params['private_key']
self.ssl_backend = module.params['ssl_backend']
self.keystore_type = module.params['keystore_type']
if self.ssl_backend == 'openssl':
self.openssl_bin = module.get_bin_path('openssl', True)
@ -312,6 +342,9 @@ class JavaKeystore:
rc=rc
)
if self.keystore_type not in (None, self.current_type()):
return "keystore type mismatch"
stored_certificate_match = re.search(r"SHA256: ([\w:]+)", stored_certificate_fingerprint_out)
if not stored_certificate_match:
return self.module.fail_json(
@ -322,6 +355,14 @@ class JavaKeystore:
return stored_certificate_match.group(1)
def current_type(self):
magic_bytes = b'\xfe\xed\xfe\xed'
with open(self.keystore_path, 'rb') as fd:
header = fd.read(4)
if header == magic_bytes:
return 'jks'
return 'pkcs12'
def cert_changed(self):
current_certificate_fingerprint = self.read_certificate_fingerprint()
stored_certificate_fingerprint = self.read_stored_certificate_fingerprint()
@ -389,6 +430,8 @@ class JavaKeystore:
with open(keystore_p12_path, 'wb') as p12_file:
p12_file.write(pkcs12_bundle)
self.result.update(msg="PKCS#12 bundle created by cryptography backend")
def openssl_create_pkcs12_bundle(self, keystore_p12_path):
export_p12_cmd = [self.openssl_bin, "pkcs12", "-export", "-name", self.name, "-in", self.certificate_path,
"-inkey", self.private_key_path, "-out", keystore_p12_path, "-passout", "stdin"]
@ -401,19 +444,22 @@ class JavaKeystore:
cmd_stdin = "%s\n" % self.keypass
cmd_stdin += "%s\n%s" % (self.password, self.password)
(rc, export_p12_out, dummy) = self.module.run_command(
(rc, export_p12_out, export_p12_err) = self.module.run_command(
export_p12_cmd, data=cmd_stdin, environ_update=None, check_rc=False
)
self.result = dict(msg=export_p12_out, cmd=export_p12_cmd, rc=rc)
if rc != 0:
self.module.fail_json(msg=export_p12_out, cmd=export_p12_cmd, rc=rc)
self.result['err'] = export_p12_err
self.module.fail_json(**self.result)
def create(self):
"""Create the keystore, or replace it with a rollback in case of
keytool failure.
"""
if self.module.check_mode:
return {'changed': True}
if os.path.exists(self.keystore_path):
os.remove(self.keystore_path)
self.result['changed'] = True
return self.result
keystore_p12_path = create_path()
self.module.add_cleanup_file(keystore_p12_path)
@ -423,6 +469,13 @@ class JavaKeystore:
else:
self.openssl_create_pkcs12_bundle(keystore_p12_path)
if self.keystore_type == 'pkcs12':
# Preserve properties of the destination file, if any.
self.module.atomic_move(keystore_p12_path, self.keystore_path)
self.update_permissions()
self.result['changed'] = True
return self.result
import_keystore_cmd = [self.keytool_bin, "-importkeystore",
"-destkeystore", self.keystore_path,
"-srckeystore", keystore_p12_path,
@ -430,19 +483,38 @@ class JavaKeystore:
"-alias", self.name,
"-noprompt"]
(rc, import_keystore_out, dummy) = self.module.run_command(
if self.keystore_type == 'jks':
keytool_help = self.module.run_command([self.keytool_bin, '-importkeystore', '-help'])
if '-deststoretype' in keytool_help[1] + keytool_help[2]:
import_keystore_cmd.insert(4, "-deststoretype")
import_keystore_cmd.insert(5, self.keystore_type)
keystore_backup = None
if self.exists():
keystore_backup = self.keystore_path + '.tmpbak'
# Preserve properties of the source file
self.module.preserved_copy(self.keystore_path, keystore_backup)
os.remove(self.keystore_path)
(rc, import_keystore_out, import_keystore_err) = self.module.run_command(
import_keystore_cmd, data='%s\n%s\n%s' % (self.password, self.password, self.password), check_rc=False
)
if rc != 0:
return self.module.fail_json(msg=import_keystore_out, cmd=import_keystore_cmd, rc=rc)
self.result = dict(msg=import_keystore_out, cmd=import_keystore_cmd, rc=rc)
# keytool may return 0 whereas the keystore has not been created.
if rc != 0 or not self.exists():
if keystore_backup is not None:
self.module.preserved_copy(keystore_backup, self.keystore_path)
os.remove(keystore_backup)
self.result['err'] = import_keystore_err
return self.module.fail_json(**self.result)
self.update_permissions()
return {
'changed': True,
'msg': import_keystore_out,
'cmd': import_keystore_cmd,
'rc': rc
}
if keystore_backup is not None:
os.remove(keystore_backup)
self.result['changed'] = True
return self.result
def exists(self):
return os.path.exists(self.keystore_path)
@ -465,14 +537,14 @@ def create_file(content):
def hex_decode(s):
if PY2:
return s.decode('hex')
else:
return s.hex()
class ArgumentSpec(object):
def __init__(self):
self.supports_check_mode = True
self.add_file_common_args = True
def main():
choose_between = (['certificate', 'certificate_path'],
['private_key', 'private_key_path'])
module = AnsibleModule(
argument_spec=dict(
name=dict(type='str', required=True),
dest=dict(type='path', required=True),
@ -483,25 +555,13 @@ class ArgumentSpec(object):
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),
)
choose_between = (
['certificate', 'certificate_path'],
['private_key', 'private_key_path'],
)
self.argument_spec = argument_spec
self.required_one_of = choose_between
self.mutually_exclusive = choose_between
def main():
spec = ArgumentSpec()
module = AnsibleModule(
argument_spec=spec.argument_spec,
required_one_of=spec.required_one_of,
mutually_exclusive=spec.mutually_exclusive,
supports_check_mode=spec.supports_check_mode,
add_file_common_args=spec.add_file_common_args,
),
required_one_of=choose_between,
mutually_exclusive=choose_between,
supports_check_mode=True,
add_file_common_args=True,
)
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C')

View file

@ -24,6 +24,7 @@
private_key_passphrase: "{{ item.passphrase | d(omit) }}"
password: changeit
ssl_backend: "{{ ssl_backend }}"
keystore_type: "{{ item.keystore_type | d(omit) }}"
loop: "{{ java_keystore_certs }}"
check_mode: yes
register: result_check
@ -91,6 +92,98 @@
loop: "{{ java_keystore_new_certs }}"
register: result_pw_change
- name: Create a Java keystore for the given certificates (force keystore type pkcs12, check mode)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: hunter2
keystore_type: pkcs12
loop: "{{ java_keystore_new_certs }}"
check_mode: yes
register: result_type_pkcs12_check
- name: Create a Java keystore for the given certificates (force keystore type jks, check mode)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: hunter2
keystore_type: jks
loop: "{{ java_keystore_new_certs }}"
check_mode: yes
register: result_type_jks_check
- name: Create a Java keystore for the given certificates (force keystore type jks)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: hunter2
keystore_type: jks
loop: "{{ java_keystore_new_certs }}"
register: result_type_jks
- name: Stat keystore (before failure)
ansible.builtin.stat:
path: "{{ output_dir ~ '/' ~ (item.keyname | d(item.name)) ~ '.jks' }}"
loop: "{{ java_keystore_new_certs }}"
register: result_stat_before
- name: Fail to create a Java keystore for the given certificates (password too short)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: short
keystore_type: jks
loop: "{{ java_keystore_new_certs }}"
register: result_fail_jks
ignore_errors: true
- name: Stat keystore (after failure)
ansible.builtin.stat:
path: "{{ output_dir ~ '/' ~ (item.keyname | d(item.name)) ~ '.jks' }}"
loop: "{{ java_keystore_new_certs }}"
register: result_stat_after
- name: Create a Java keystore for the given certificates (keystore type changed, check mode)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: hunter2
keystore_type: pkcs12
loop: "{{ java_keystore_new_certs }}"
check_mode: yes
register: result_type_change_check
- name: Create a Java keystore for the given certificates (keystore type changed)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: hunter2
keystore_type: pkcs12
loop: "{{ java_keystore_new_certs }}"
register: result_type_change
- name: Create a Java keystore for the given certificates (omit keystore type, check mode)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: hunter2
loop: "{{ java_keystore_new_certs }}"
check_mode: yes
register: result_type_omit_check
- name: Create a Java keystore for the given certificates (omit keystore type)
community.general.java_keystore:
<<: *java_keystore_params
name: foobar
password: hunter2
loop: "{{ java_keystore_new_certs }}"
register: result_type_omit
- name: Check that the remote certificates have not been removed
ansible.builtin.file:
path: "{{ output_dir ~ '/' ~ item.name ~ '.pem' }}"
@ -118,3 +211,25 @@
- result_alias_change_check is changed
- result_pw_change is changed
- result_pw_change_check is changed
# We don't know if we start from jks or pkcs12 format, anyway check mode
# and actual mode must return the same 'changed' state, and 'jks' and
# 'pkcs12' must give opposite results on a same host.
- result_type_jks_check.changed != result_type_pkcs12_check.changed
- result_type_jks_check.changed == result_type_jks.changed
- result_type_change is changed
- result_type_change_check is changed
- result_type_omit is not changed
- result_type_omit_check is not changed
# keystore properties must remain the same after failure
- result_fail_jks is failed
- result_stat_before.results[0].stat.uid == result_stat_after.results[0].stat.uid
- result_stat_before.results[1].stat.uid == result_stat_after.results[1].stat.uid
- result_stat_before.results[0].stat.gid == result_stat_after.results[0].stat.gid
- result_stat_before.results[1].stat.gid == result_stat_after.results[1].stat.gid
- result_stat_before.results[0].stat.mode == result_stat_after.results[0].stat.mode
- result_stat_before.results[1].stat.mode == result_stat_after.results[1].stat.mode
- result_stat_before.results[0].stat.checksum == result_stat_after.results[0].stat.checksum
- result_stat_before.results[1].stat.checksum == result_stat_after.results[1].stat.checksum

View file

@ -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()