{"action":"created","comment":{"url":"https://api.github.com/repos/ansible/ansible/pulls/comments/99489343","pull_request_review_id":20169350,"id":99489343,"diff_hunk":"@@ -0,0 +1,250 @@\n+#!/usr/bin/python\n+#\n+# (c) 2013, RSD Services S.A\n+#\n+# This file is part of Ansible\n+#\n+# Ansible is free software: you can redistribute it and/or modify\n+# it under the terms of the GNU General Public License as published by\n+# the Free Software Foundation, either version 3 of the License, or\n+# (at your option) any later version.\n+#\n+# Ansible is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+# GNU General Public License for more details.\n+#\n+# You should have received a copy of the GNU General Public License\n+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n+\n+DOCUMENTATION = '''\n+---\n+module: java_cert\n+version_added: 2.3\n+short_description: Uses keytool to import/remove key from java keystore(cacerts)\n+description:\n+  - This is a wrapper module around keytool. Which can be used to import/remove certificates from a given java keystore.\n+options:\n+  cert_url:\n+    description:\n+      - Basic URL to fetch SSL certificate from\n+    required: true\n+  cert_port:\n+    description:\n+      - Port to connect to URL. This will be used to create server URL:PORT\n+    required: false\n+    default: 443\n+  cert_path:\n+    description:\n+      - Local path to load certificate from\n+    required: false\n+    default: null\n+  cert_alias:\n+    description:\n+      - Imported certificate alias\n+    required: false\n+    default: null\n+  keystore_path:\n+    description:\n+      - Path to keystore.\n+    required: false\n+    default: null\n+  keystore_pass:\n+    description:\n+      - Keystore password\n+    required: false\n+    default: null\n+  keystore_create:\n+    description:\n+      - Create keystore if it doesn't exist\n+    required: false\n+    default: null\n+  state:\n+    description:\n+      - Defines action which can be either certificate import or removal.\n+    choices: [ 'present', 'absent' ]\n+    default: present\n+    required: false\n+\n+author: Adam Hamsik @haad\n+'''\n+\n+EXAMPLES = '''\n+# Import SSL certificate from google.com to a given cacerts keystore\n+java_certs:\n+  cert_url: google.com\n+  cert_port: 443\n+  keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts\n+  keystore_pass: changeit\n+  state: present\n+\n+# Remove certificate with given alias from a keystore\n+java_certs:\n+  cert_url: google.com\n+  keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts\n+  keystore_pass: changeit\n+  state: absent\n+\n+# Import SSL certificate from google.com to a keystore, create it if it doesn't exist\n+java_certs:\n+  cert_url: google.com\n+  keystore_path: /tmp/cacerts\n+  keystore_pass: changeit\n+  keystore_create: yes\n+  state: present\n+'''\n+\n+RETURN = '''\n+msg:\n+  description: Output from stdou of keytool command after execution of given command.\n+  returned: success\n+  type: string\n+  sample: \"Module require existing keystore at keystore_path '/tmp/test/cacerts'\"\n+\n+rc:\n+  description: Keytool command execution return value\n+  returned: success\n+  type: int\n+  sample: \"0\"\n+\n+cmd:\n+  description: Executed command to get action done\n+  returned: success\n+  type: string\n+  sample: \"keytool -importcert -noprompt -keystore\"\n+'''\n+\n+import os\n+\n+def check_cert_present(module, keystore_path, keystore_pass, alias):\n+    ''' Check if certificate with alias is present in keystore located at keystore_path '''\n+    test_cmd = (\"keytool -noprompt -list -keystore '{}' -storepass '{}' \"\n+                \"-alias '{}'\").format(keystore_path, keystore_pass, alias)\n+\n+    (check_rc, _, _) = module.run_command(test_cmd)\n+    if check_rc == 0:\n+        return True\n+    return False\n+\n+def import_cert_url(module, url, port, keystore_path, keystore_pass, alias):\n+    ''' Import certificate from URL into keystore located at keystore_path '''\n+    fetch_cmd = (\"keytool -printcert -rfc -sslserver {}:{}\").format(url, port)\n+    import_cmd = (\"keytool -importcert -noprompt -keystore '{}' -storepass '{}' \"\n+                  \"-alias '{}'\").format(keystore_path, keystore_pass, alias)\n+\n+    # Fetch SSL certificate from remote host.\n+    (_, fetch_out, _) = module.run_command(fetch_cmd, check_rc=True)\n+\n+    # Use remote certificate from remote host and import it to a java keystore\n+    (import_rc, import_out, import_err) = module.run_command(import_cmd, data=fetch_out,\n+                                                             check_rc=False)\n+    if import_rc == 0:\n+        return module.exit_json(changed=True, msg=import_out,\n+                                rc=import_rc, cmd=import_cmd, stdout_lines=import_out)\n+    else:\n+        return module.fail_json(msg=import_out, rc=import_rc, cmd=import_cmd, error=import_err)\n+\n+def import_cert_path(module, path, keystore_path, keystore_pass, alias):\n+    ''' Import certificate from path into keystore located on keystore_path as alias '''\n+    import_cmd = (\"keytool -importcert -noprompt -keystore '{}' -storepass '{}' \"\n+                  \"-file '{}' -alias '{}'\").format(keystore_path, keystore_pass, path, alias)\n+\n+    # Use local certificate from local path and import it to a java keystore\n+    (import_rc, import_out, import_err) = module.run_command(import_cmd, check_rc=False)\n+    if import_rc == 0:\n+        return module.exit_json(changed=True, msg=import_out,\n+                                rc=import_rc, cmd=import_cmd, stdout_lines=import_out,\n+                                error=import_err)\n+    else:\n+        return module.fail_json(msg=import_out, rc=import_rc, cmd=import_cmd)\n+\n+def delete_cert(module, keystore_path, keystore_pass, alias):\n+    ''' Delete cerificate identified with alias from keystore on keystore_path '''\n+    del_cmd = (\"keytool -delete -keystore '{}' -storepass '{}' \"\n+               \"-alias '{}'\").format(keystore_path, keystore_pass, alias)\n+\n+    # Delete SSL certificate from keystore\n+    (del_rc, del_out, del_err) = module.run_command(del_cmd, check_rc=True)\n+\n+    return module.exit_json(changed=True, msg=del_out,\n+                            rc=del_rc, cmd=del_cmd, stdout_lines=del_out,\n+                            error=del_err)\n+\n+def test_keytool(module):\n+    ''' Test if keytool is actuall executable or not '''\n+    test_cmd = \"keytool\"\n+\n+    module.run_command(test_cmd, check_rc=True)\n+\n+def test_keystore(module, keystore_path):\n+    ''' Check if we can access keystore as file or not '''\n+    if keystore_path is None:\n+        keystore_path = ''\n+\n+    if not os.path.exists(keystore_path) and not os.path.isfile(keystore_path):\n+        ## Keystore doesn't exist we want to create it\n+        return module.fail_json(changed=False,\n+                                msg=\"Module require existing keystore at keystore_path '{}'\"\n+                                .format(keystore_path))\n+\n+def main():\n+    argument_spec = dict(\n+        cert_url=dict(required=False, type='str'),\n+        cert_path=dict(required=False, type='str'),\n+        cert_alias=dict(required=False, type='str'),\n+        cert_port=dict(required=False, default='443'),\n+        keystore_path=dict(required=False, type='str'),\n+        keystore_pass=dict(required=False, default='changeit', type='str'),\n+        keystore_create=dict(required=False, default=False, type='bool'),\n+        state=dict(required=False, default='present', choices=['present', 'absent'])\n+    )\n+\n+    module = AnsibleModule(\n+        argument_spec=argument_spec,\n+        required_one_of=[['cert_path', 'cert_url']],\n+        required_together=[['keystore_path', 'keystore_pass']],\n+        mutually_exclusive=[\n+            ['cert_url', 'cert_path']\n+        ],\n+    )","path":"lib/ansible/modules/system/java_certs.py","position":209,"original_position":209,"commit_id":"a94ae2c7928d8a0f387b432fd3404185b5e6d52a","original_commit_id":"a94ae2c7928d8a0f387b432fd3404185b5e6d52a","user":{"login":"haad","id":67790,"avatar_url":"https://avatars.githubusercontent.com/u/67790?v=3","gravatar_id":"","url":"https://api.github.com/users/haad","html_url":"https://github.com/haad","followers_url":"https://api.github.com/users/haad/followers","following_url":"https://api.github.com/users/haad/following{/other_user}","gists_url":"https://api.github.com/users/haad/gists{/gist_id}","starred_url":"https://api.github.com/users/haad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haad/subscriptions","organizations_url":"https://api.github.com/users/haad/orgs","repos_url":"https://api.github.com/users/haad/repos","events_url":"https://api.github.com/users/haad/events{/privacy}","received_events_url":"https://api.github.com/users/haad/received_events","type":"User","site_admin":false},"body":"Do you have any documentation about implementing diff support ? I can't find anything about it here http://docs.ansible.com/ansible/dev_guide/developing_modules_general.html","created_at":"2017-02-05T13:33:54Z","updated_at":"2017-02-05T13:33:54Z","html_url":"https://github.com/ansible/ansible/pull/20274#discussion_r99489343","pull_request_url":"https://api.github.com/repos/ansible/ansible/pulls/20274","_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible/pulls/comments/99489343"},"html":{"href":"https://github.com/ansible/ansible/pull/20274#discussion_r99489343"},"pull_request":{"href":"https://api.github.com/repos/ansible/ansible/pulls/20274"}}},"pull_request":{"url":"https://api.github.com/repos/ansible/ansible/pulls/20274","id":101611472,"html_url":"https://github.com/ansible/ansible/pull/20274","diff_url":"https://github.com/ansible/ansible/pull/20274.diff","patch_url":"https://github.com/ansible/ansible/pull/20274.patch","issue_url":"https://api.github.com/repos/ansible/ansible/issues/20274","number":20274,"state":"open","locked":false,"title":"Add simple module to import/delete ssl certificate from/to java keystore","user":{"login":"haad","id":67790,"avatar_url":"https://avatars.githubusercontent.com/u/67790?v=3","gravatar_id":"","url":"https://api.github.com/users/haad","html_url":"https://github.com/haad","followers_url":"https://api.github.com/users/haad/followers","following_url":"https://api.github.com/users/haad/following{/other_user}","gists_url":"https://api.github.com/users/haad/gists{/gist_id}","starred_url":"https://api.github.com/users/haad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haad/subscriptions","organizations_url":"https://api.github.com/users/haad/orgs","repos_url":"https://api.github.com/users/haad/repos","events_url":"https://api.github.com/users/haad/events{/privacy}","received_events_url":"https://api.github.com/users/haad/received_events","type":"User","site_admin":false},"body":"ISSUE TYPE\r\n\r\n    Feature Pull Request\r\n\r\nSUMMARY\r\n\r\nAdd module for managing java keystore file from ansible.","created_at":"2017-01-15T21:58:11Z","updated_at":"2017-02-05T13:33:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5a39cbb407e145de72dcd46a789be846a19a84d8","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/ansible/ansible/pulls/20274/commits","review_comments_url":"https://api.github.com/repos/ansible/ansible/pulls/20274/comments","review_comment_url":"https://api.github.com/repos/ansible/ansible/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ansible/ansible/issues/20274/comments","statuses_url":"https://api.github.com/repos/ansible/ansible/statuses/a94ae2c7928d8a0f387b432fd3404185b5e6d52a","head":{"label":"haad:java_certs","ref":"java_certs","sha":"a94ae2c7928d8a0f387b432fd3404185b5e6d52a","user":{"login":"haad","id":67790,"avatar_url":"https://avatars.githubusercontent.com/u/67790?v=3","gravatar_id":"","url":"https://api.github.com/users/haad","html_url":"https://github.com/haad","followers_url":"https://api.github.com/users/haad/followers","following_url":"https://api.github.com/users/haad/following{/other_user}","gists_url":"https://api.github.com/users/haad/gists{/gist_id}","starred_url":"https://api.github.com/users/haad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haad/subscriptions","organizations_url":"https://api.github.com/users/haad/orgs","repos_url":"https://api.github.com/users/haad/repos","events_url":"https://api.github.com/users/haad/events{/privacy}","received_events_url":"https://api.github.com/users/haad/received_events","type":"User","site_admin":false},"repo":{"id":22702536,"name":"ansible","full_name":"haad/ansible","owner":{"login":"haad","id":67790,"avatar_url":"https://avatars.githubusercontent.com/u/67790?v=3","gravatar_id":"","url":"https://api.github.com/users/haad","html_url":"https://github.com/haad","followers_url":"https://api.github.com/users/haad/followers","following_url":"https://api.github.com/users/haad/following{/other_user}","gists_url":"https://api.github.com/users/haad/gists{/gist_id}","starred_url":"https://api.github.com/users/haad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haad/subscriptions","organizations_url":"https://api.github.com/users/haad/orgs","repos_url":"https://api.github.com/users/haad/repos","events_url":"https://api.github.com/users/haad/events{/privacy}","received_events_url":"https://api.github.com/users/haad/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/haad/ansible","description":"Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.","fork":true,"url":"https://api.github.com/repos/haad/ansible","forks_url":"https://api.github.com/repos/haad/ansible/forks","keys_url":"https://api.github.com/repos/haad/ansible/keys{/key_id}","collaborators_url":"https://api.github.com/repos/haad/ansible/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/haad/ansible/teams","hooks_url":"https://api.github.com/repos/haad/ansible/hooks","issue_events_url":"https://api.github.com/repos/haad/ansible/issues/events{/number}","events_url":"https://api.github.com/repos/haad/ansible/events","assignees_url":"https://api.github.com/repos/haad/ansible/assignees{/user}","branches_url":"https://api.github.com/repos/haad/ansible/branches{/branch}","tags_url":"https://api.github.com/repos/haad/ansible/tags","blobs_url":"https://api.github.com/repos/haad/ansible/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/haad/ansible/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/haad/ansible/git/refs{/sha}","trees_url":"https://api.github.com/repos/haad/ansible/git/trees{/sha}","statuses_url":"https://api.github.com/repos/haad/ansible/statuses/{sha}","languages_url":"https://api.github.com/repos/haad/ansible/languages","stargazers_url":"https://api.github.com/repos/haad/ansible/stargazers","contributors_url":"https://api.github.com/repos/haad/ansible/contributors","subscribers_url":"https://api.github.com/repos/haad/ansible/subscribers","subscription_url":"https://api.github.com/repos/haad/ansible/subscription","commits_url":"https://api.github.com/repos/haad/ansible/commits{/sha}","git_commits_url":"https://api.github.com/repos/haad/ansible/git/commits{/sha}","comments_url":"https://api.github.com/repos/haad/ansible/comments{/number}","issue_comment_url":"https://api.github.com/repos/haad/ansible/issues/comments{/number}","contents_url":"https://api.github.com/repos/haad/ansible/contents/{+path}","compare_url":"https://api.github.com/repos/haad/ansible/compare/{base}...{head}","merges_url":"https://api.github.com/repos/haad/ansible/merges","archive_url":"https://api.github.com/repos/haad/ansible/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/haad/ansible/downloads","issues_url":"https://api.github.com/repos/haad/ansible/issues{/number}","pulls_url":"https://api.github.com/repos/haad/ansible/pulls{/number}","milestones_url":"https://api.github.com/repos/haad/ansible/milestones{/number}","notifications_url":"https://api.github.com/repos/haad/ansible/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/haad/ansible/labels{/name}","releases_url":"https://api.github.com/repos/haad/ansible/releases{/id}","deployments_url":"https://api.github.com/repos/haad/ansible/deployments","created_at":"2014-08-07T00:13:10Z","updated_at":"2016-03-30T09:16:20Z","pushed_at":"2017-02-05T12:59:07Z","git_url":"git://github.com/haad/ansible.git","ssh_url":"git@github.com:haad/ansible.git","clone_url":"https://github.com/haad/ansible.git","svn_url":"https://github.com/haad/ansible","homepage":"http://ansible.com/","size":61004,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"devel"}},"base":{"label":"ansible:devel","ref":"devel","sha":"c5d3aac8229307de09e9411ce0b0eed44cb712cc","user":{"login":"ansible","id":1507452,"avatar_url":"https://avatars.githubusercontent.com/u/1507452?v=3","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"repo":{"id":3638964,"name":"ansible","full_name":"ansible/ansible","owner":{"login":"ansible","id":1507452,"avatar_url":"https://avatars.githubusercontent.com/u/1507452?v=3","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ansible/ansible","description":"Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.","fork":false,"url":"https://api.github.com/repos/ansible/ansible","forks_url":"https://api.github.com/repos/ansible/ansible/forks","keys_url":"https://api.github.com/repos/ansible/ansible/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ansible/ansible/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ansible/ansible/teams","hooks_url":"https://api.github.com/repos/ansible/ansible/hooks","issue_events_url":"https://api.github.com/repos/ansible/ansible/issues/events{/number}","events_url":"https://api.github.com/repos/ansible/ansible/events","assignees_url":"https://api.github.com/repos/ansible/ansible/assignees{/user}","branches_url":"https://api.github.com/repos/ansible/ansible/branches{/branch}","tags_url":"https://api.github.com/repos/ansible/ansible/tags","blobs_url":"https://api.github.com/repos/ansible/ansible/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ansible/ansible/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ansible/ansible/git/refs{/sha}","trees_url":"https://api.github.com/repos/ansible/ansible/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ansible/ansible/statuses/{sha}","languages_url":"https://api.github.com/repos/ansible/ansible/languages","stargazers_url":"https://api.github.com/repos/ansible/ansible/stargazers","contributors_url":"https://api.github.com/repos/ansible/ansible/contributors","subscribers_url":"https://api.github.com/repos/ansible/ansible/subscribers","subscription_url":"https://api.github.com/repos/ansible/ansible/subscription","commits_url":"https://api.github.com/repos/ansible/ansible/commits{/sha}","git_commits_url":"https://api.github.com/repos/ansible/ansible/git/commits{/sha}","comments_url":"https://api.github.com/repos/ansible/ansible/comments{/number}","issue_comment_url":"https://api.github.com/repos/ansible/ansible/issues/comments{/number}","contents_url":"https://api.github.com/repos/ansible/ansible/contents/{+path}","compare_url":"https://api.github.com/repos/ansible/ansible/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ansible/ansible/merges","archive_url":"https://api.github.com/repos/ansible/ansible/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ansible/ansible/downloads","issues_url":"https://api.github.com/repos/ansible/ansible/issues{/number}","pulls_url":"https://api.github.com/repos/ansible/ansible/pulls{/number}","milestones_url":"https://api.github.com/repos/ansible/ansible/milestones{/number}","notifications_url":"https://api.github.com/repos/ansible/ansible/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ansible/ansible/labels{/name}","releases_url":"https://api.github.com/repos/ansible/ansible/releases{/id}","deployments_url":"https://api.github.com/repos/ansible/ansible/deployments","created_at":"2012-03-06T14:58:02Z","updated_at":"2017-02-05T11:48:57Z","pushed_at":"2017-02-05T12:59:09Z","git_url":"git://github.com/ansible/ansible.git","ssh_url":"git@github.com:ansible/ansible.git","clone_url":"https://github.com/ansible/ansible.git","svn_url":"https://github.com/ansible/ansible","homepage":"http://ansible.com/","size":65034,"stargazers_count":21211,"watchers_count":21211,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":6751,"mirror_url":null,"open_issues_count":2354,"forks":6751,"open_issues":2354,"watchers":21211,"default_branch":"devel"}},"_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible/pulls/20274"},"html":{"href":"https://github.com/ansible/ansible/pull/20274"},"issue":{"href":"https://api.github.com/repos/ansible/ansible/issues/20274"},"comments":{"href":"https://api.github.com/repos/ansible/ansible/issues/20274/comments"},"review_comments":{"href":"https://api.github.com/repos/ansible/ansible/pulls/20274/comments"},"review_comment":{"href":"https://api.github.com/repos/ansible/ansible/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ansible/ansible/pulls/20274/commits"},"statuses":{"href":"https://api.github.com/repos/ansible/ansible/statuses/a94ae2c7928d8a0f387b432fd3404185b5e6d52a"}}}}
{"actor":{"display_login":"haad"}}