From 8f10db85520bd6203b489ca31e80af5271d20208 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 2 Feb 2020 13:54:28 +0100 Subject: [PATCH] Do fail instead of regenerate for password protected and invalid keys. (#65638) --- ...ypair-add-password-protected-key-check.yml | 4 +++- lib/ansible/modules/crypto/openssh_keypair.py | 7 +++++-- .../targets/openssh_keypair/tasks/main.yml | 20 ++++++++++++++++-- .../openssh_keypair/tests/validate.yml | 21 +++++++++++++++---- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/changelogs/fragments/64436-openssh_keypair-add-password-protected-key-check.yml b/changelogs/fragments/64436-openssh_keypair-add-password-protected-key-check.yml index 3ac996edefb..53b9680bb97 100644 --- a/changelogs/fragments/64436-openssh_keypair-add-password-protected-key-check.yml +++ b/changelogs/fragments/64436-openssh_keypair-add-password-protected-key-check.yml @@ -1,2 +1,4 @@ bugfixes: - - openssh_keypair - add logic to handle password protected or broken key + - openssh_keypair - add logic to avoid breaking password protected keys. +minor_changes: + - openssh_keypair - instead of regenerating some broken or password protected keys, fail the module. Keys can still be regenerated by calling the module with ``force=yes``. diff --git a/lib/ansible/modules/crypto/openssh_keypair.py b/lib/ansible/modules/crypto/openssh_keypair.py index 57b297cf4bf..70f77f5aec0 100644 --- a/lib/ansible/modules/crypto/openssh_keypair.py +++ b/lib/ansible/modules/crypto/openssh_keypair.py @@ -64,7 +64,7 @@ options: type: str version_added: "2.9" notes: - - In case the ssh key is broken or password protected, it will be regenerated. + - In case the ssh key is broken or password protected, the module will fail. Set the I(force) option to C(yes) if you want to regenerate the keypair. extends_documentation_fragment: files ''' @@ -245,13 +245,16 @@ class Keypair(object): def _check_pass_protected_or_broken_key(): key_state = module.run_command([module.get_bin_path('ssh-keygen', True), '-P', '', '-yf', self.path], check_rc=False) + if key_state[0] == 255 or 'is not a public key file' in key_state[2]: + return True if 'incorrect passphrase' in key_state[2] or 'load failed' in key_state[2]: return True return False if _check_state(): if _check_pass_protected_or_broken_key(): - return False + module.fail_json(msg='Unable to read the key. The key is protected with a passphrase or broken.' + ' Will not proceed. To force regeneration, call the module with `force=yes`.') proc = module.run_command([module.get_bin_path('ssh-keygen', True), '-lf', self.path], check_rc=False) if not proc[0] == 0: diff --git a/test/integration/targets/openssh_keypair/tasks/main.yml b/test/integration/targets/openssh_keypair/tasks/main.yml index 5851f93ec0c..5bdb242b094 100644 --- a/test/integration/targets/openssh_keypair/tasks/main.yml +++ b/test/integration/targets/openssh_keypair/tasks/main.yml @@ -1,3 +1,4 @@ +--- - name: Generate privatekey1 - standard openssh_keypair: path: '{{ output_dir }}/privatekey1' @@ -53,11 +54,19 @@ - '{{ output_dir }}/privatekeybroken' - '{{ output_dir }}/privatekeybroken.pub' -- name: Regenerate broken key +- name: Regenerate broken key - should fail openssh_keypair: path: '{{ output_dir }}/privatekeybroken' type: rsa register: output_broken + ignore_errors: yes + +- name: Regenerate broken key with force + openssh_keypair: + path: '{{ output_dir }}/privatekeybroken' + type: rsa + force: yes + register: output_broken_force - name: Generate read-only private key openssh_keypair: @@ -87,9 +96,16 @@ - name: Generate password protected key command: 'ssh-keygen -f {{ output_dir }}/privatekey8 -N password' -- name: Try to modify the password protected key - should be overridden +- name: Try to modify the password protected key - should fail openssh_keypair: path: '{{ output_dir }}/privatekey8' register: privatekey8_result + ignore_errors: yes + +- name: Try to modify the password protected key with force=yes + openssh_keypair: + path: '{{ output_dir }}/privatekey8' + force: yes + register: privatekey8_result_force - 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 9091bac2dfd..9f34ab225b5 100644 --- a/test/integration/targets/openssh_keypair/tests/validate.yml +++ b/test/integration/targets/openssh_keypair/tests/validate.yml @@ -86,10 +86,17 @@ - output_regenerated_via_force is changed -- name: Verify that broken key will be regenerated +- name: Verify that broken key will cause failure assert: that: - - output_broken is changed + - output_broken is failed + - "'Unable to read the key. The key is protected with a passphrase or broken.' in output_broken.msg" + + +- name: Verify that broken key will be regenerated if force=yes is specified + assert: + that: + - output_broken_force is changed - name: Verify that read-only key will be regenerated @@ -113,7 +120,13 @@ that: - privatekey7_modified_result.comment == 'test_modified@privatekey7' -- name: Check that password protected key has been regenerated +- name: Check that password protected key made module fail assert: that: - - privatekey8_result is changed + - privatekey8_result is failed + - "'Unable to read the key. The key is protected with a passphrase or broken.' in privatekey8_result.msg" + +- name: Check that password protected key was regenerated with force=yes + assert: + that: + - privatekey8_result_force is changed