openssh_keypair - Adding backend option and refactoring backend code (#236)

* Refactoring openssh_keypair for multiple backends

* Fixing cryptography backend validations

* Simplifying conditionals and excess variable assignments

* Fixing docs and adding cleanup for integration tests

* Fixing docs and public key validation bugs in crypto backend

* Enhancing cryptogagraphy utils to raise OpenSSHErrors when file not found

* Adding missed copyright and cleanup for idempotency test keys

* Fixing doc style

* Readding crypto/openssh for backwards compatibility

* Adding changelog fragment and final simplifications of conditional statements

* Applied initial review suggestions
This commit is contained in:
Ajpantuso
2021-05-23 16:36:55 -04:00
committed by GitHub
parent 2bf0bb5fb3
commit c6483751b5
14 changed files with 1212 additions and 997 deletions

View File

@@ -1,3 +1,4 @@
dependencies:
- setup_ssh_keygen
- setup_openssl
- setup_bcrypt

View File

@@ -0,0 +1,557 @@
---
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
# Ensures no conflicts from previous test runs
- name: "({{ backend }}) Cleanup Output Directory"
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_fileglob:
- "{{ output_dir }}/privatekey*"
- "{{ output_dir }}/regenerate*"
- name: "({{ backend }}) Generate privatekey1 - standard (check mode)"
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
backend: "{{ backend }}"
register: privatekey1_result_check
check_mode: true
- name: "({{ backend }}) Generate privatekey1 - standard"
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
backend: "{{ backend }}"
register: privatekey1_result
- name: "({{ backend }}) Generate privatekey1 - standard (check mode idempotent)"
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
backend: "{{ backend }}"
register: privatekey1_idem_result_check
check_mode: true
- name: "({{ backend }}) Generate privatekey1 - standard (idempotent)"
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
backend: "{{ backend }}"
register: privatekey1_idem_result
- name: "({{ backend }}) Generate privatekey2 - default size"
openssh_keypair:
path: '{{ output_dir }}/privatekey2'
backend: "{{ backend }}"
- name: "({{ backend }}) Generate privatekey3 - type dsa"
openssh_keypair:
path: '{{ output_dir }}/privatekey3'
type: dsa
backend: "{{ backend }}"
- name: "({{ backend }}) Generate privatekey4 - standard"
openssh_keypair:
path: '{{ output_dir }}/privatekey4'
size: 2048
backend: "{{ backend }}"
- name: "({{ backend }}) Delete privatekey4 - standard"
openssh_keypair:
state: absent
path: '{{ output_dir }}/privatekey4'
backend: "{{ backend }}"
- name: "({{ backend }}) Generate privatekey5 - standard"
openssh_keypair:
path: '{{ output_dir }}/privatekey5'
size: 2048
backend: "{{ backend }}"
register: publickey_gen
- name: "({{ backend }}) Generate privatekey6"
openssh_keypair:
path: '{{ output_dir }}/privatekey6'
type: rsa
size: 2048
backend: "{{ backend }}"
- name: "({{ backend }}) Regenerate privatekey6 via force"
openssh_keypair:
path: '{{ output_dir }}/privatekey6'
type: rsa
size: 2048
force: yes
backend: "{{ backend }}"
register: output_regenerated_via_force
- name: "({{ backend }}) Create broken key"
copy:
dest: '{{ item }}'
content: ''
mode: '0700'
loop:
- '{{ output_dir }}/privatekeybroken'
- '{{ output_dir }}/privatekeybroken.pub'
- name: "({{ backend }}) Regenerate broken key - should fail"
openssh_keypair:
path: '{{ output_dir }}/privatekeybroken'
type: rsa
size: 2048
backend: "{{ backend }}"
register: output_broken
ignore_errors: yes
- name: "({{ backend }}) Regenerate broken key with force"
openssh_keypair:
path: '{{ output_dir }}/privatekeybroken'
type: rsa
force: yes
size: 2048
backend: "{{ backend }}"
register: output_broken_force
- name: "({{ backend }}) Generate read-only private key"
openssh_keypair:
path: '{{ output_dir }}/privatekeyreadonly'
type: rsa
mode: '0200'
size: 2048
backend: "{{ backend }}"
- name: "({{ backend }}) Regenerate read-only private key via force"
openssh_keypair:
path: '{{ output_dir }}/privatekeyreadonly'
type: rsa
force: yes
size: 2048
backend: "{{ backend }}"
register: output_read_only
- name: "({{ backend }}) Generate privatekey7 - standard with comment"
openssh_keypair:
path: '{{ output_dir }}/privatekey7'
comment: 'test@privatekey7'
size: 2048
backend: "{{ backend }}"
register: privatekey7_result
- name: "({{ backend }}) Modify privatekey7 comment"
openssh_keypair:
path: '{{ output_dir }}/privatekey7'
comment: 'test_modified@privatekey7'
size: 2048
backend: "{{ backend }}"
register: privatekey7_modified_result
- name: "({{ backend }}) Generate password protected key"
command: 'ssh-keygen -f {{ output_dir }}/privatekey8 -N {{ passphrase }}'
- name: "({{ backend }}) Try to modify the password protected key - should fail"
openssh_keypair:
path: '{{ output_dir }}/privatekey8'
size: 2048
backend: "{{ backend }}"
register: privatekey8_result
ignore_errors: yes
- name: "({{ backend }}) Try to modify the password protected key with force=yes"
openssh_keypair:
path: '{{ output_dir }}/privatekey8'
force: yes
size: 2048
backend: "{{ backend }}"
register: privatekey8_result_force
- name: "({{ backend }}) Generate another password protected key"
command: 'ssh-keygen -f {{ output_dir }}/privatekey9 -N {{ passphrase }}'
- name: "({{ backend }}) Try to modify the password protected key with passphrase"
openssh_keypair:
path: '{{ output_dir }}/privatekey9'
size: 1024
passphrase: "{{ passphrase }}"
backend: "{{ backend }}"
register: privatekey9_modified_result
when: backend == 'cryptography'
- name: "({{ backend }}) Generate another unprotected key"
openssh_keypair:
path: '{{ output_dir }}/privatekey10'
size: 2048
backend: "{{ backend }}"
- name: "({{ backend }}) Try to Modify unprotected key with passphrase"
openssh_keypair:
path: '{{ output_dir }}/privatekey10'
size: 2048
passphrase: "{{ passphrase }}"
backend: "{{ backend }}"
ignore_errors: true
register: privatekey10_result
when: backend == 'cryptography'
- name: "({{ backend }}) Try to force modify the password protected key with force=true"
openssh_keypair:
path: '{{ output_dir }}/privatekey10'
size: 2048
passphrase: "{{ passphrase }}"
force: true
backend: "{{ backend }}"
register: privatekey10_result_force
when: backend == 'cryptography'
- name: "({{ backend }}) Ensure that ssh-keygen can read keys generated with passphrase"
command: 'ssh-keygen -yf {{ output_dir }}/privatekey10 -P {{ passphrase }}'
register: privatekey10_result_sshkeygen
when: backend == 'cryptography'
- name: "({{ backend }}) Generate PEM encoded key with passphrase"
command: 'ssh-keygen -f {{ output_dir }}/privatekey11 -N {{ passphrase }} -m PEM'
when: backend == 'cryptography'
- name: "({{ backend }}) Try to verify a PEM encoded key"
openssh_keypair:
path: '{{ output_dir }}/privatekey11'
size: 2048
passphrase: "{{ passphrase }}"
backend: "{{ backend }}"
register: privatekey11_result
when: backend == 'cryptography'
- import_tasks: ../tests/validate.yml
# Test regenerate option
- name: "({{ backend }}) Regenerate - setup simple keys"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1024
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
- name: "({{ backend }}) Regenerate - setup password protected keys"
command: 'ssh-keygen -f {{ output_dir }}/regenerate-b-{{ item }} -N {{ passphrase }}'
loop: "{{ regenerate_values }}"
- name: "({{ backend }}) Regenerate - setup broken keys"
copy:
dest: '{{ output_dir }}/regenerate-c-{{ item.0 }}{{ item.1 }}'
content: 'broken key'
mode: '0700'
with_nested:
- "{{ regenerate_values }}"
- [ '', '.pub' ]
-
- name: "({{ backend }}) Regenerate - setup password protected keys for passphrse test"
command: 'ssh-keygen -f {{ output_dir }}/regenerate-d-{{ item }} -N {{ passphrase }}'
loop: "{{ regenerate_values }}"
- name: "({{ backend }}) Regenerate - modify broken keys (check mode)"
openssh_keypair:
path: '{{ output_dir }}/regenerate-c-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - modify broken keys"
openssh_keypair:
path: '{{ output_dir }}/regenerate-c-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - modify password protected keys (check mode)"
openssh_keypair:
path: '{{ output_dir }}/regenerate-b-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - modify password protected keys with passphrase (check mode)"
openssh_keypair:
path: '{{ output_dir }}/regenerate-b-{{ item }}'
type: rsa
size: 1024
passphrase: "{{ passphrase }}"
regenerate: '{{ item }}'
backend: "{{ backend }}"
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
when: backend == 'cryptography'
- assert:
that:
- result.results[0] is success
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
when: backend == 'cryptography'
- name: "({{ backend }}) Regenerate - modify password protected keys"
openssh_keypair:
path: '{{ output_dir }}/regenerate-b-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - modify password protected keys with passphrase"
openssh_keypair:
path: '{{ output_dir }}/regenerate-d-{{ item }}'
type: rsa
size: 1024
passphrase: "{{ passphrase }}"
regenerate: '{{ item }}'
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
when: backend == 'cryptography'
- assert:
that:
- result.results[0] is success
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
when: backend == 'cryptography'
- name: "({{ backend }}) Regenerate - not modify regular keys (check mode)"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
check_mode: yes
loop: "{{ regenerate_values }}"
register: result
- assert:
that:
- result.results[0] is not changed
- result.results[1] is not changed
- result.results[2] is not changed
- result.results[3] is not changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - not modify regular keys"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
register: result
- assert:
that:
- result.results[0] is not changed
- result.results[1] is not changed
- result.results[2] is not changed
- result.results[3] is not changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - adjust key size (check mode)"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1048
regenerate: '{{ item }}'
backend: "{{ backend }}"
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - adjust key size"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1048
regenerate: '{{ item }}'
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - redistribute keys"
copy:
src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
remote_src: true
with_nested:
- "{{ regenerate_values }}"
- [ '', '.pub' ]
when: "item.0 != 'always'"
- name: "({{ backend }}) Regenerate - adjust key type (check mode)"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - adjust key type"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
regenerate: '{{ item }}'
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: "({{ backend }}) Regenerate - redistribute keys"
copy:
src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
remote_src: true
with_nested:
- "{{ regenerate_values }}"
- [ '', '.pub' ]
when: "item.0 != 'always'"
- name: "({{ backend }}) Regenerate - adjust comment (check mode)"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
comment: test comment
regenerate: '{{ item }}'
backend: "{{ backend }}"
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result is changed
- name: "({{ backend }}) Regenerate - adjust comment"
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
comment: test comment
regenerate: '{{ item }}'
backend: "{{ backend }}"
loop: "{{ regenerate_values }}"
register: result
- assert:
that:
- result is changed
# for all values but 'always', the key should have not been regenerated.
# verify this by comparing fingerprints:
- result.results[0].fingerprint == result.results[1].fingerprint
- result.results[0].fingerprint == result.results[2].fingerprint
- result.results[0].fingerprint == result.results[3].fingerprint
- result.results[0].fingerprint != result.results[4].fingerprint

View File

@@ -4,509 +4,20 @@
# and should not be used as examples of how to write Ansible roles #
####################################################################
# Bumps up cryptography and bcrypt versions to be compatible with OpenSSH >= 7.8
- import_tasks: ./setup_bcrypt.yml
- name: Generate privatekey1 - standard (check mode)
- name: Backend auto-detection test
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
register: privatekey1_result_check
check_mode: true
path: '{{ output_dir }}/auto_backend_key'
state: "{{ item }}"
loop: ['present', 'absent']
- name: Generate privatekey1 - standard
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
register: privatekey1_result
- set_fact:
backends: ['opensshbin']
- name: Generate privatekey1 - standard (check mode idempotent)
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
register: privatekey1_idem_result_check
check_mode: true
- name: Generate privatekey1 - standard (idempotent)
openssh_keypair:
path: '{{ output_dir }}/privatekey1'
size: 2048
register: privatekey1_idem_result
- name: Generate privatekey2 - default size
openssh_keypair:
path: '{{ output_dir }}/privatekey2'
- name: Generate privatekey3 - type dsa
openssh_keypair:
path: '{{ output_dir }}/privatekey3'
type: dsa
- name: Generate privatekey4 - standard
openssh_keypair:
path: '{{ output_dir }}/privatekey4'
size: 2048
- name: Delete privatekey4 - standard
openssh_keypair:
state: absent
path: '{{ output_dir }}/privatekey4'
- name: Generate privatekey5 - standard
openssh_keypair:
path: '{{ output_dir }}/privatekey5'
size: 2048
register: publickey_gen
- name: Generate privatekey6
openssh_keypair:
path: '{{ output_dir }}/privatekey6'
type: rsa
size: 2048
- name: Regenerate privatekey6 via force
openssh_keypair:
path: '{{ output_dir }}/privatekey6'
type: rsa
size: 2048
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 - should fail
openssh_keypair:
path: '{{ output_dir }}/privatekeybroken'
type: rsa
size: 2048
register: output_broken
ignore_errors: yes
- name: Regenerate broken key with force
openssh_keypair:
path: '{{ output_dir }}/privatekeybroken'
type: rsa
force: yes
size: 2048
register: output_broken_force
- name: Generate read-only private key
openssh_keypair:
path: '{{ output_dir }}/privatekeyreadonly'
type: rsa
mode: '0200'
size: 2048
- name: Regenerate read-only private key via force
openssh_keypair:
path: '{{ output_dir }}/privatekeyreadonly'
type: rsa
force: yes
size: 2048
register: output_read_only
- name: Generate privatekey7 - standard with comment
openssh_keypair:
path: '{{ output_dir }}/privatekey7'
comment: 'test@privatekey7'
size: 2048
register: privatekey7_result
- name: Modify privatekey7 comment
openssh_keypair:
path: '{{ output_dir }}/privatekey7'
comment: 'test_modified@privatekey7'
size: 2048
register: privatekey7_modified_result
- name: Generate password protected key
command: 'ssh-keygen -f {{ output_dir }}/privatekey8 -N {{ passphrase }}'
- name: Try to modify the password protected key - should fail
openssh_keypair:
path: '{{ output_dir }}/privatekey8'
size: 2048
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
size: 2048
register: privatekey8_result_force
- name: Generate another password protected key
command: 'ssh-keygen -f {{ output_dir }}/privatekey9 -N {{ passphrase }}'
- name: Try to modify the password protected key with passphrase
openssh_keypair:
path: '{{ output_dir }}/privatekey9'
size: 1024
passphrase: "{{ passphrase }}"
register: privatekey9_modified_result
- set_fact:
backends: "{{ backends + ['cryptography'] }}"
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- name: Generate another unprotected key
openssh_keypair:
path: '{{ output_dir }}/privatekey10'
size: 2048
- name: Try to Modify unprotected key with passphrase
openssh_keypair:
path: '{{ output_dir }}/privatekey10'
size: 2048
passphrase: "{{ passphrase }}"
ignore_errors: true
register: privatekey10_result
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- name: Try to force modify the password protected key with force=true
openssh_keypair:
path: '{{ output_dir }}/privatekey10'
size: 2048
passphrase: "{{ passphrase }}"
force: true
register: privatekey10_result_force
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- name: Ensure that ssh-keygen can read keys generated with passphrase
command: 'ssh-keygen -yf {{ output_dir }}/privatekey10 -P {{ passphrase }}'
register: privatekey10_result_sshkeygen
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- name: Generate PEM encoded key with passphrase
command: 'ssh-keygen -f {{ output_dir }}/privatekey11 -N {{ passphrase }} -m PEM'
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- name: Try to verify a PEM encoded key
openssh_keypair:
path: '{{ output_dir }}/privatekey11'
size: 2048
passphrase: "{{ passphrase }}"
register: privatekey11_result
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- import_tasks: ../tests/validate.yml
# Test regenerate option
- name: Regenerate - setup simple keys
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1024
loop: "{{ regenerate_values }}"
- name: Regenerate - setup password protected keys
command: 'ssh-keygen -f {{ output_dir }}/regenerate-b-{{ item }} -N {{ passphrase }}'
loop: "{{ regenerate_values }}"
- name: Regenerate - setup broken keys
copy:
dest: '{{ output_dir }}/regenerate-c-{{ item.0 }}{{ item.1 }}'
content: 'broken key'
mode: '0700'
with_nested:
- "{{ regenerate_values }}"
- [ '', '.pub' ]
-
- name: Regenerate - setup password protected keys for passphrse test
command: 'ssh-keygen -f {{ output_dir }}/regenerate-d-{{ item }} -N {{ passphrase }}'
loop: "{{ regenerate_values }}"
- name: Regenerate - modify broken keys (check mode)
openssh_keypair:
path: '{{ output_dir }}/regenerate-c-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - modify broken keys
openssh_keypair:
path: '{{ output_dir }}/regenerate-c-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - modify password protected keys (check mode)
openssh_keypair:
path: '{{ output_dir }}/regenerate-b-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - modify password protected keys with passphrase (check mode)
openssh_keypair:
path: '{{ output_dir }}/regenerate-b-{{ item }}'
type: rsa
size: 1024
passphrase: "{{ passphrase }}"
regenerate: '{{ item }}'
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- assert:
that:
- result.results[0] is success
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- name: Regenerate - modify password protected keys
openssh_keypair:
path: '{{ output_dir }}/regenerate-b-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
- result.results[1] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
- result.results[2] is failed
- "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - modify password protected keys with passphrase
openssh_keypair:
path: '{{ output_dir }}/regenerate-d-{{ item }}'
type: rsa
size: 1024
passphrase: "{{ passphrase }}"
regenerate: '{{ item }}'
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- assert:
that:
- result.results[0] is success
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
- name: Regenerate - not modify regular keys (check mode)
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
check_mode: yes
loop: "{{ regenerate_values }}"
register: result
- assert:
that:
- result.results[0] is not changed
- result.results[1] is not changed
- result.results[2] is not changed
- result.results[3] is not changed
- result.results[4] is changed
- name: Regenerate - not modify regular keys
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1024
regenerate: '{{ item }}'
loop: "{{ regenerate_values }}"
register: result
- assert:
that:
- result.results[0] is not changed
- result.results[1] is not changed
- result.results[2] is not changed
- result.results[3] is not changed
- result.results[4] is changed
- name: Regenerate - adjust key size (check mode)
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1048
regenerate: '{{ item }}'
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - adjust key size
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: rsa
size: 1048
regenerate: '{{ item }}'
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - redistribute keys
copy:
src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
remote_src: true
with_nested:
- "{{ regenerate_values }}"
- [ '', '.pub' ]
when: "item.0 != 'always'"
- name: Regenerate - adjust key type (check mode)
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
regenerate: '{{ item }}'
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - adjust key type
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
regenerate: '{{ item }}'
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result.results[0] is success and result.results[0] is not changed
- result.results[1] is failed
- "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
- result.results[2] is changed
- result.results[3] is changed
- result.results[4] is changed
- name: Regenerate - redistribute keys
copy:
src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
remote_src: true
with_nested:
- "{{ regenerate_values }}"
- [ '', '.pub' ]
when: "item.0 != 'always'"
- name: Regenerate - adjust comment (check mode)
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
comment: test comment
regenerate: '{{ item }}'
check_mode: yes
loop: "{{ regenerate_values }}"
ignore_errors: yes
register: result
- assert:
that:
- result is changed
- name: Regenerate - adjust comment
openssh_keypair:
path: '{{ output_dir }}/regenerate-a-{{ item }}'
type: dsa
size: 1024
comment: test comment
regenerate: '{{ item }}'
loop: "{{ regenerate_values }}"
register: result
- assert:
that:
- result is changed
# for all values but 'always', the key should have not been regenerated.
# verify this by comparing fingerprints:
- result.results[0].fingerprint == result.results[1].fingerprint
- result.results[0].fingerprint == result.results[2].fingerprint
- result.results[0].fingerprint == result.results[3].fingerprint
- result.results[0].fingerprint != result.results[4].fingerprint
- include_tasks: ./impl.yml
loop: "{{ backends }}"
loop_control:
loop_var: backend

View File

@@ -1,9 +1,9 @@
---
- name: Log privatekey1 return values
- name: "({{ backend }}) Log privatekey1 return values"
debug:
var: privatekey1_result
- name: Validate general behavior
- name: "({{ backend }}) Validate general behavior"
assert:
that:
- privatekey1_result_check is changed
@@ -12,7 +12,7 @@
- privatekey1_idem_result_check.public_key.startswith("ssh-rsa")
- privatekey1_idem_result is not changed
- name: Validate privatekey1 return fingerprint
- name: "({{ backend }}) Validate privatekey1 return fingerprint"
assert:
that:
- privatekey1_result["fingerprint"] is string
@@ -20,150 +20,150 @@
# only distro old enough that it still gives md5 with no prefix
when: ansible_distribution != 'CentOS' and ansible_distribution_major_version != '6'
- name: Validate privatekey1 return public_key
- name: "({{ backend }}) Validate privatekey1 return public_key"
assert:
that:
- privatekey1_result["public_key"] is string
- privatekey1_result["public_key"].startswith("ssh-rsa ")
- name: Validate privatekey1 return size value
- name: "({{ backend }}) Validate privatekey1 return size value"
assert:
that:
- privatekey1_result["size"]|type_debug == 'int'
- privatekey1_result["size"] == 2048
- name: Validate privatekey1 return key type
- name: "({{ backend }}) Validate privatekey1 return key type"
assert:
that:
- privatekey1_result["type"] is string
- privatekey1_result["type"] == "rsa"
- name: Validate privatekey1 (test - RSA key with size 2048 bits)
- name: "({{ backend }}) Validate privatekey1 (test - RSA key with size 2048 bits)"
shell: "ssh-keygen -lf {{ output_dir }}/privatekey1 | grep -o -E '^[0-9]+'"
register: privatekey1
- name: Validate privatekey1 (assert - RSA key with size 2048 bits)
- name: "({{ backend }}) Validate privatekey1 (assert - RSA key with size 2048 bits)"
assert:
that:
- privatekey1.stdout == '2048'
- name: Validate privatekey1 idempotence
- name: "({{ backend }}) Validate privatekey1 idempotence"
assert:
that:
- privatekey1_idem_result is not changed
- name: Validate privatekey2 (test - RSA key with default size 4096 bits)
- name: "({{ backend }}) Validate privatekey2 (test - RSA key with default size 4096 bits)"
shell: "ssh-keygen -lf {{ output_dir }}/privatekey2 | grep -o -E '^[0-9]+'"
register: privatekey2
- name: Validate privatekey2 (assert - RSA key with size 4096 bits)
- name: "({{ backend }}) Validate privatekey2 (assert - RSA key with size 4096 bits)"
assert:
that:
- privatekey2.stdout == '4096'
- name: Validate privatekey3 (test - DSA key with size 1024 bits)
- name: "({{ backend }}) Validate privatekey3 (test - DSA key with size 1024 bits)"
shell: "ssh-keygen -lf {{ output_dir }}/privatekey3 | grep -o -E '^[0-9]+'"
register: privatekey3
- name: Validate privatekey3 (assert - DSA key with size 4096 bits)
- name: "({{ backend }}) Validate privatekey3 (assert - DSA key with size 4096 bits)"
assert:
that:
- privatekey3.stdout == '1024'
- name: Validate privatekey4 (test - Ensure key has been removed)
- name: "({{ backend }}) Validate privatekey4 (test - Ensure key has been removed)"
stat:
path: '{{ output_dir }}/privatekey4'
register: privatekey4
- name: Validate privatekey4 (assert - Ensure key has been removed)
- name: "({{ backend }}) Validate privatekey4 (assert - Ensure key has been removed)"
assert:
that:
- privatekey4.stat.exists == False
- name: Validate privatekey5 (assert - Public key module output equal to the public key on host)
- name: "({{ backend }}) Validate privatekey5 (assert - Public key module output equal to the public key on host)"
assert:
that:
- "publickey_gen.public_key == lookup('file', output_dir ~ '/privatekey5.pub').strip('\n')"
- name: Verify that privatekey6 will be regenerated via force
- name: "({{ backend }}) Verify that privatekey6 will be regenerated via force"
assert:
that:
- output_regenerated_via_force is changed
- name: Verify that broken key will cause failure
- name: "({{ backend }}) Verify that broken key will cause failure"
assert:
that:
- 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
- name: "({{ backend }}) 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
- name: "({{ backend }}) Verify that read-only key will be regenerated"
assert:
that:
- output_read_only is changed
- name: Validate privatekey7 (assert - Public key remains the same after comment change)
- name: "({{ backend }}) Validate privatekey7 (assert - Public key remains the same after comment change)"
assert:
that:
- privatekey7_result.public_key == privatekey7_modified_result.public_key
- name: Validate privatekey7 comment on creation
- name: "({{ backend }}) Validate privatekey7 comment on creation"
assert:
that:
- privatekey7_result.comment == 'test@privatekey7'
- name: Validate privatekey7 comment update
- name: "({{ backend }}) Validate privatekey7 comment update"
assert:
that:
- privatekey7_modified_result.comment == 'test_modified@privatekey7'
- name: Check that password protected key made module fail
- name: "({{ backend }}) Check that password protected key made module fail"
assert:
that:
- 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
- name: "({{ backend }}) Check that password protected key was regenerated with force=yes"
assert:
that:
- privatekey8_result_force is changed
- block:
- name: Check that password protected key with passphrase was regenerated
- name: "({{ backend }}) Check that password protected key with passphrase was regenerated"
assert:
that:
- privatekey9_modified_result is changed
- name: Check that modifying unprotected key with passphrase fails
- name: "({{ backend }}) Check that modifying unprotected key with passphrase fails"
assert:
that:
- privatekey10_result is failed
- "'Unable to read the key. The key is protected with a passphrase or broken.' in privatekey8_result.msg"
- name: Check that unprotected key was regenerated with force=yes and passphrase supplied
- name: "({{ backend }}) Check that unprotected key was regenerated with force=yes and passphrase supplied"
assert:
that:
- privatekey10_result_force is changed
- name: Check that ssh-keygen output from passphrase protected key matches openssh_keypair
- name: "({{ backend }}) Check that ssh-keygen output from passphrase protected key matches openssh_keypair"
assert:
that:
- privatekey10_result_force.public_key == privatekey10_result_sshkeygen.stdout
- name: Check that PEM encoded private keys are loaded successfully
- name: "({{ backend }}) Check that PEM encoded private keys are loaded successfully"
assert:
that:
- privatekey11_result is success
when: cryptography_version.stdout is version('3.0', '>=') and bcrypt_version.stdout is version('3.1.5', '>=')
when: backend == 'cryptography'

View File

@@ -0,0 +1,3 @@
dependencies:
- setup_remote_constraints
- setup_pkg_mgr

View File

@@ -21,4 +21,4 @@
set_fact:
bcrypt_version:
stdout: 0.0
when: bcrypt_version is not defined
when: bcrypt_version is not defined