From 547a29805e269846595d82f71382e93f2a8e3c9a Mon Sep 17 00:00:00 2001 From: lolcube <42739510+lolcube@users.noreply.github.com> Date: Mon, 24 Jun 2019 21:45:49 +0200 Subject: [PATCH] =?UTF-8?q?openssh=5Fkeypair:=20bugfix=20make=20regenerati?= =?UTF-8?q?ng=20keypairs=20via=20force=20possible=E2=80=A6=20(#57801)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * openssh_keypair: bugfix make regenerating keypairs via force possible / add invalid file handling * openssh_keypair: change permissions of read-only file instead of deleting it for regeneration; add changelog fragment * address review feedbak, refactor * add integration tests for bigfixes * linter: fix indent * fixup integration tests: use force when regenerating an invalid file * linter: fix indent * openssh_keypair: address review feedback * openssh_keypair: fixup, remove backtick * openssh_keypair: address review feedback * Only pass 'y' into stdin of ssh-keygen when file exists. --- ...make-regenerating-valid-files-possible.yml | 2 + lib/ansible/modules/crypto/openssh_keypair.py | 16 +++++++- .../targets/openssh_keypair/tasks/main.yml | 40 +++++++++++++++++++ .../openssh_keypair/tests/validate.yml | 18 +++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/57801-openssh_keypair-fix-make-regenerating-valid-files-possible.yml diff --git a/changelogs/fragments/57801-openssh_keypair-fix-make-regenerating-valid-files-possible.yml b/changelogs/fragments/57801-openssh_keypair-fix-make-regenerating-valid-files-possible.yml new file mode 100644 index 00000000000..19308e129c2 --- /dev/null +++ b/changelogs/fragments/57801-openssh_keypair-fix-make-regenerating-valid-files-possible.yml @@ -0,0 +1,2 @@ +bugfixes: + - openssh_keypair - make regeneration of valid keypairs with the ``force`` option possible, add better handling for invalid files diff --git a/lib/ansible/modules/crypto/openssh_keypair.py b/lib/ansible/modules/crypto/openssh_keypair.py index 06722b86ce4..61c8513eb13 100644 --- a/lib/ansible/modules/crypto/openssh_keypair.py +++ b/lib/ansible/modules/crypto/openssh_keypair.py @@ -116,6 +116,7 @@ public_key: ''' import os +import stat import errno from ansible.module_utils.basic import AnsibleModule @@ -180,8 +181,13 @@ class Keypair(object): args.extend(['-C', ""]) try: + if os.path.exists(self.path) and not os.access(self.path, os.W_OK): + os.chmod(self.path, stat.S_IWUSR + stat.S_IRUSR) self.changed = True - module.run_command(args) + stdin_data = None + if os.path.exists(self.path): + stdin_data = 'y' + module.run_command(args, data=stdin_data) proc = module.run_command([module.get_bin_path('ssh-keygen', True), '-lf', self.path]) self.fingerprint = proc[1].split() pubkey = module.run_command([module.get_bin_path('ssh-keygen', True), '-yf', self.path]) @@ -201,7 +207,13 @@ class Keypair(object): return os.path.exists(self.path) if _check_state(): - proc = module.run_command([module.get_bin_path('ssh-keygen', True), '-lf', self.path]) + proc = module.run_command([module.get_bin_path('ssh-keygen', True), '-lf', self.path], check_rc=False) + if not proc[0] == 0: + if os.path.isdir(self.path): + module.fail_json(msg='%s is a directory. Please specify a path to a file.' % (self.path)) + + return False + fingerprint = proc[1].split() pubkey = module.run_command([module.get_bin_path('ssh-keygen', True), '-yf', self.path]) pubkey = pubkey[1].strip('\n') diff --git a/test/integration/targets/openssh_keypair/tasks/main.yml b/test/integration/targets/openssh_keypair/tasks/main.yml index e81f620962f..25116c63a94 100644 --- a/test/integration/targets/openssh_keypair/tasks/main.yml +++ b/test/integration/targets/openssh_keypair/tasks/main.yml @@ -27,4 +27,44 @@ path: '{{ output_dir }}/privatekey5' register: publickey_gen +- name: Generate privatekey6 + openssh_keypair: + path: '{{ output_dir }}/privatekey6' + type: rsa + +- name: Regenerate privatekey6 via force + openssh_keypair: + path: '{{ output_dir }}/privatekey6' + type: rsa + force: yes + register: output_regenerated_via_force + +- name: Create broken key + copy: + dest: '{{ item }}' + content: '' + mode: '0700' + loop: + - '{{ output_dir }}/privatekeybroken' + - '{{ output_dir }}/privatekeybroken.pub' + +- name: Regenerate broken key + openssh_keypair: + path: '{{ output_dir }}/privatekeybroken' + type: rsa + register: output_broken + +- name: Generate read-only private key + openssh_keypair: + path: '{{ output_dir }}/privatekeyreadonly' + type: rsa + mode: '0200' + +- name: Regenerate read-only private key via force + openssh_keypair: + path: '{{ output_dir }}/privatekeyreadonly' + type: rsa + force: yes + register: output_read_only + - import_tasks: ../tests/validate.yml diff --git a/test/integration/targets/openssh_keypair/tests/validate.yml b/test/integration/targets/openssh_keypair/tests/validate.yml index 47fa6259ff8..266665a4548 100644 --- a/test/integration/targets/openssh_keypair/tests/validate.yml +++ b/test/integration/targets/openssh_keypair/tests/validate.yml @@ -1,3 +1,4 @@ +--- - name: Log privatekey1 return values debug: var: privatekey1_result @@ -73,3 +74,20 @@ assert: that: - "publickey_gen.public_key == lookup('file', output_dir ~ '/privatekey5.pub').strip('\n')" + +- name: Verify that privatekey6 will be regenerated via force + assert: + that: + - output_regenerated_via_force is changed + + +- name: Verify that broken key will be regenerated + assert: + that: + - output_broken is changed + + +- name: Verify that read-only key will be regenerated + assert: + that: + - output_read_only is changed \ No newline at end of file