From 982e3222874640541d9ecaab7f9e41d264fe9264 Mon Sep 17 00:00:00 2001 From: tmarlok88 Date: Tue, 22 Aug 2017 09:45:30 +0200 Subject: [PATCH] java_cert role pkcs12 import (#24616) * java_cert pkcs12 import * documentation and formatting * update examples * update examples #2 * integration tests * integration tests #2 * added aliases.txt * renamed aliases * bugfix * empty it alieses --- lib/ansible/modules/system/java_cert.py | 116 +++++++++++++----- test/integration/targets/java_cert/aliases | 0 .../targets/java_cert/defaults/main.yml | 3 + .../targets/java_cert/files/testpkcs.p12 | Bin 0 -> 2532 bytes .../targets/java_cert/tasks/main.yml | 56 +++++++++ 5 files changed, 146 insertions(+), 29 deletions(-) create mode 100644 test/integration/targets/java_cert/aliases create mode 100644 test/integration/targets/java_cert/defaults/main.yml create mode 100644 test/integration/targets/java_cert/files/testpkcs.p12 create mode 100644 test/integration/targets/java_cert/tasks/main.yml diff --git a/lib/ansible/modules/system/java_cert.py b/lib/ansible/modules/system/java_cert.py index bce834e015d..4ac1eb84d05 100644 --- a/lib/ansible/modules/system/java_cert.py +++ b/lib/ansible/modules/system/java_cert.py @@ -34,6 +34,20 @@ options: cert_alias: description: - Imported certificate alias. + pkcs12_path: + description: + - Local path to load PKCS12 keystore from. + version_added: "2.4" + pkcs12_password: + description: + - Password for importing from PKCS12 keystore. + default: '' + version_added: "2.4" + pkcs12_alias: + description: + - Alias in the PKCS12 keystore. + default: 1 + version_added: "2.4" keystore_path: description: - Path to keystore. @@ -58,30 +72,38 @@ author: Adam Hamsik @haad ''' EXAMPLES = ''' -# Import SSL certificate from google.com to a given cacerts keystore -java_cert: - cert_url: google.com - cert_port: 443 - keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts - keystore_pass: changeit - state: present - -# Remove certificate with given alias from a keystore -java_cert: - cert_url: google.com - keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts - keystore_pass: changeit - executable: /usr/lib/jvm/jre7/bin/keytool - state: absent - -# Import SSL certificate from google.com to a keystore, -# create it if it doesn't exist -java_cert: - cert_url: google.com - keystore_path: /tmp/cacerts - keystore_pass: changeit - keystore_create: yes - state: present +- name: Import SSL certificate from google.com to a given cacerts keystore + java_cert: + cert_url: google.com + cert_port: 443 + keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts + keystore_pass: changeit + state: present + +- name: Remove certificate with given alias from a keystore + java_cert: + cert_url: google.com + keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts + keystore_pass: changeit + executable: /usr/lib/jvm/jre7/bin/keytool + state: absent + +- name: Import SSL certificate from google.com to a keystore, create it if it doesn't exist + java_cert: + cert_url: google.com + keystore_path: /tmp/cacerts + keystore_pass: changeit + keystore_create: yes + state: present + +- name: Import a pkcs12 keystore with a specified alias, create it if it doesn't exist + java_cert: + pkcs12_path: "/tmp/importkeystore.p12" + cert_alias: default + keystore_path: /opt/wildfly/standalone/configuration/defaultkeystore.jks + keystore_pass: changeit + keystore_create: yes + state: present ''' RETURN = ''' @@ -170,6 +192,30 @@ def import_cert_path(module, executable, path, keystore_path, keystore_pass, ali else: return module.fail_json(msg=import_out, rc=import_rc, cmd=import_cmd) +def import_pkcs12_path(module, executable, path, keystore_path, keystore_pass, pkcs12_pass, pkcs12_alias, alias): + ''' Import pkcs12 from path into keystore located on + keystore_path as alias ''' + import_cmd = ("%s -importkeystore -noprompt -destkeystore '%s' -srcstoretype PKCS12 " + "-deststorepass '%s' -destkeypass '%s' -srckeystore '%s' -srcstorepass '%s' " + "-srcalias '%s' -destalias '%s'") % (executable, keystore_path, keystore_pass, + keystore_pass, path, pkcs12_pass, pkcs12_alias, alias) + + if module.check_mode: + module.exit_json(changed=True) + + # Use local certificate from local path and import it to a java keystore + (import_rc, import_out, import_err) = module.run_command(import_cmd, + check_rc=False) + + diff = {'before': '\n', 'after': '%s\n'%alias} + if import_rc == 0: + return module.exit_json(changed=True, msg=import_out, + rc=import_rc, cmd=import_cmd, stdout=import_out, + error=import_err, diff=diff) + else: + return module.fail_json(msg=import_out, rc=import_rc, cmd=import_cmd) + + def delete_cert(module, executable, keystore_path, keystore_pass, alias): ''' Delete certificate identified with alias from keystore on keystore_path ''' del_cmd = ("%s -delete -keystore '%s' -storepass '%s' " @@ -202,15 +248,18 @@ def test_keystore(module, keystore_path): ## Keystore doesn't exist we want to create it return module.fail_json(changed=False, msg="Module require existing keystore at keystore_path '%s'" - %(keystore_path)) + % (keystore_path)) def main(): argument_spec = dict( cert_url=dict(type='str'), - cert_path=dict(type='str'), + cert_path=dict(type='path'), + pkcs12_path=dict(type='path'), + pkcs12_password=dict(type='str', no_log=True), + pkcs12_alias=dict(type='str'), cert_alias=dict(type='str'), cert_port=dict(default='443', type='int'), - keystore_path=dict(type='str'), + keystore_path=dict(type='path'), keystore_pass=dict(required=True, type='str', no_log=True), keystore_create=dict(default=False, type='bool'), executable=dict(default='keytool', type='str'), @@ -220,10 +269,10 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, - required_one_of=[['cert_path', 'cert_url']], + required_one_of=[['cert_path', 'cert_url', 'pkcs12_path']], required_together=[['keystore_path', 'keystore_pass']], mutually_exclusive=[ - ['cert_url', 'cert_path'] + ['cert_url', 'cert_path', 'pkcs12_path'] ], supports_check_mode=True, ) @@ -231,6 +280,11 @@ def main(): url = module.params.get('cert_url') path = module.params.get('cert_path') port = module.params.get('cert_port') + + pkcs12_path = module.params.get('pkcs12_path') + pkcs12_pass = module.params.get('pkcs12_password', '') + pkcs12_alias = module.params.get('pkcs12_alias', '1') + cert_alias = module.params.get('cert_alias') or url keystore_path = module.params.get('keystore_path') @@ -258,6 +312,10 @@ def main(): elif state == 'present': if not cert_present: + if pkcs12_path: + import_pkcs12_path(module, executable, pkcs12_path, keystore_path, + keystore_pass, pkcs12_pass, pkcs12_alias, cert_alias) + if path: import_cert_path(module, executable, path, keystore_path, keystore_pass, cert_alias) diff --git a/test/integration/targets/java_cert/aliases b/test/integration/targets/java_cert/aliases new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/integration/targets/java_cert/defaults/main.yml b/test/integration/targets/java_cert/defaults/main.yml new file mode 100644 index 00000000000..22723ff1770 --- /dev/null +++ b/test/integration/targets/java_cert/defaults/main.yml @@ -0,0 +1,3 @@ +--- +test_pkcs12_path: testpkcs.p12 +test_keystore_path: keystore.jks \ No newline at end of file diff --git a/test/integration/targets/java_cert/files/testpkcs.p12 b/test/integration/targets/java_cert/files/testpkcs.p12 new file mode 100644 index 0000000000000000000000000000000000000000..e0fee618c7b18026213327e631ed0b204f67486f GIT binary patch literal 2532 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 literal 0 HcmV?d00001 diff --git a/test/integration/targets/java_cert/tasks/main.yml b/test/integration/targets/java_cert/tasks/main.yml new file mode 100644 index 00000000000..ad43c08986b --- /dev/null +++ b/test/integration/targets/java_cert/tasks/main.yml @@ -0,0 +1,56 @@ +--- +- name: prep pkcs12 file + copy: src="{{ test_pkcs12_path }}" dest="{{output_dir}}/{{ test_pkcs12_path }}" + +- name: import pkcs12 + local_action: + module: java_cert + pkcs12_path: "{{output_dir}}/{{ test_pkcs12_path }}" + pkcs12_password: changeit + pkcs12_alias: default + cert_alias: default + keystore_path: "{{output_dir}}/{{ test_keystore_path }}" + keystore_pass: changeme_keystore + keystore_create: yes + state: present + register: result_success +- name: verify success + assert: + that: + - result_success|success + +- name: import pkcs12 with wrong password + local_action: + module: java_cert + pkcs12_path: "{{output_dir}}/{{ test_pkcs12_path }}" + pkcs12_password: wrong_pass + pkcs12_alias: default + cert_alias: default_new + keystore_path: "{{output_dir}}/{{ test_keystore_path }}" + keystore_pass: changeme_keystore + keystore_create: yes + state: present + ignore_errors: true + register: result_wrong_pass + +- name: verify fail with wrong import password + assert: + that: + - result_wrong_pass|failed + +- name: test fail on mutually exclusive params + local_action: + module: java_cert + cert_path: ca.crt + pkcs12_path: "{{output_dir}}/{{ test_pkcs12_path }}" + cert_alias: default + keystore_path: "{{output_dir}}/{{ test_keystore_path }}" + keystore_pass: changeme_keystore + keystore_create: yes + state: present + ignore_errors: true + register: result_excl_params +- name: verify failed exclusive params + assert: + that: + - result_excl_params|failed