diff --git a/lib/ansible/modules/system/java_cert.py b/lib/ansible/modules/system/java_cert.py index bce834e015..4ac1eb84d0 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 +- 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 -# 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: 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 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 0000000000..e69de29bb2 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 0000000000..22723ff177 --- /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 0000000000..e0fee618c7 Binary files /dev/null and b/test/integration/targets/java_cert/files/testpkcs.p12 differ 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 0000000000..ad43c08986 --- /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