openssh_cert - cleanup and diff support (#255)

* Initial commit

* Fixing units

* Adding changelog fragment

* Enhanced encapsulation of certificate data

* Avoiding failure when path is not parseable

* Diff refactor

* Applying initial review suggestions
This commit is contained in:
Ajpantuso
2021-07-16 13:00:22 -04:00
committed by GitHub
parent f3c6c1172e
commit 4908f1a8ec
9 changed files with 1030 additions and 863 deletions

View File

@@ -3,465 +3,34 @@
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: openssh_cert integration tests
when: not (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6")
block:
- name: Generate keypair
openssh_keypair:
path: '{{ output_dir }}/id_key'
type: rsa
size: 2048
- name: Generate always valid cert (check mode)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
check_mode: yes
- name: Generate always valid cert
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
- name: Generate always valid cert (idempotent)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
- name: Generate always valid cert (idempotent, check mode)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
check_mode: yes
- name: Generate restricted validity cert with valid_at (check mode)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: +0s
valid_to: +32w
valid_at: +2w
check_mode: yes
- name: Generate restricted validity cert with valid_at
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: +0s
valid_to: +32w
valid_at: +2w
- name: Generate restricted validity cert with valid_at (idempotent)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: +0s
valid_to: +32w
valid_at: +2w
- name: Generate restricted validity cert with valid_at (idempotent, check mode)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: +0s
valid_to: +32w
valid_at: +2w
check_mode: yes
- name: Generate always valid cert only for example.com and examplehost (check mode)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
principals:
- example.com
- examplehost
check_mode: yes
- name: Generate always valid cert only for example.com and examplehost
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
principals:
- example.com
- examplehost
- name: Generate always valid cert only for example.com and examplehost (idempotent)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
principals:
- example.com
- examplehost
- name: Generate always valid cert only for example.com and examplehost (idempotent, check mode)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
principals:
- example.com
- examplehost
check_mode: yes
- name: Generate always valid cert only for example.com and examplehost (idempotent, switch)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: always
valid_to: forever
principals:
- examplehost
- example.com
- name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (check mode)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: yes
- name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: "2001-01-21"
valid_to: "2019-01-21"
- name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (idempotent)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: "2001-01-21"
valid_to: "2019-01-21"
- name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (idempotent, check mode)
openssh_cert:
type: host
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: yes
- name: Generate an OpenSSH user Certificate with clear and force-command option (check mode)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
options:
- "clear"
- "force-command=/tmp/bla/foo"
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: yes
- name: Generate an OpenSSH user Certificate with clear and force-command option
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
options:
- "clear"
- "force-command=/tmp/bla/foo"
valid_from: "2001-01-21"
valid_to: "2019-01-21"
- name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
options:
- "clear"
- "force-command=/tmp/bla/foo"
valid_from: "2001-01-21"
valid_to: "2019-01-21"
- name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent, check mode)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
options:
- "clear"
- "force-command=/tmp/bla/foo"
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: yes
- name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent, switch)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert'
options:
- "force-command=/tmp/bla/foo"
- "clear"
valid_from: "2001-01-21"
valid_to: "2019-01-21"
- name: Generate cert without serial
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_no_serial'
valid_from: always
valid_to: forever
register: rc_no_serial_number
- name: check default serial
assert:
that:
- "'Serial: 0' in rc_no_serial_number.info"
msg: OpenSSH user certificate contains the default serial number.
- name: Generate cert without serial (idempotent)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_no_serial'
valid_from: always
valid_to: forever
register: rc_no_serial_number_idempotent
- name: check idempotent
assert:
that:
- rc_no_serial_number_idempotent is not changed
msg: OpenSSH certificate generation without serial number is idempotent.
- name: Generate cert with serial 42
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_serial_42'
valid_from: always
valid_to: forever
serial_number: 42
register: rc_serial_number
- name: check serial 42
assert:
that:
- "'Serial: 42' in rc_serial_number.info"
msg: OpenSSH user certificate contains the serial number from the params.
- name: Generate cert with serial 42 (idempotent)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_serial_42'
valid_from: always
valid_to: forever
serial_number: 42
register: rc_serial_number_idempotent
- name: check idempotent
assert:
that:
- rc_serial_number_idempotent is not changed
msg: OpenSSH certificate generation with serial number is idempotent.
- name: Generate cert with changed serial number
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_serial_42'
valid_from: always
valid_to: forever
serial_number: 1337
register: rc_serial_number_changed
- name: check changed
assert:
that:
- rc_serial_number_changed is changed
msg: OpenSSH certificate regenerated upon serial number change.
- name: Generate cert with removed serial number
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_serial_42'
valid_from: always
valid_to: forever
serial_number: 0
register: rc_serial_number_removed
- name: check changed
assert:
that:
- rc_serial_number_removed is changed
msg: OpenSSH certificate regenerated upon serial number removal.
- name: Generate a new cert with serial number
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_serial_ignore'
valid_from: always
valid_to: forever
serial_number: 42
- name: Generate cert again, omitting the parameter serial_number (idempotent)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_serial_ignore'
valid_from: always
valid_to: forever
register: rc_serial_number_ignored
- name: check idempotent
assert:
that:
- rc_serial_number_ignored is not changed
msg: OpenSSH certificate generation with omitted serial number is idempotent.
- name: Remove certificate (check mode)
openssh_cert:
state: absent
path: '{{ output_dir }}/id_cert'
#type: user
#signing_key: '{{ output_dir }}/id_key'
#public_key: '{{ output_dir }}/id_key.pub'
#valid_from: "2001-01-21"
#valid_to: "2019-01-21"
check_mode: yes
- name: Remove certificate
openssh_cert:
state: absent
path: '{{ output_dir }}/id_cert'
#type: user
#signing_key: '{{ output_dir }}/id_key'
#public_key: '{{ output_dir }}/id_key.pub'
#valid_from: "2001-01-21"
#valid_to: "2019-01-21"
- name: Remove certificate (idempotent)
openssh_cert:
state: absent
path: '{{ output_dir }}/id_cert'
#type: user
#signing_key: '{{ output_dir }}/id_key'
#public_key: '{{ output_dir }}/id_key.pub'
#valid_from: "2001-01-21"
#valid_to: "2019-01-21"
- name: Remove certificate (idempotent, check mode)
openssh_cert:
state: absent
path: '{{ output_dir }}/id_cert'
#type: user
#signing_key: '{{ output_dir }}/id_key'
#public_key: '{{ output_dir }}/id_key.pub'
#valid_from: "2001-01-21"
#valid_to: "2019-01-21"
check_mode: yes
- name: Remove keypair
openssh_keypair:
path: '{{ output_dir }}/id_key'
state: absent
- name: Declare global variables
set_fact:
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
certificate_path: '{{ output_dir }}/id_cert'
- name: openssh_cert integration tests that require ssh-agent
- name: Generate keypair
openssh_keypair:
path: "{{ signing_key }}"
type: rsa
size: 2048
- block:
- name: Import idempotency tests
import_tasks: ../tests/idempotency.yml
- name: Import key_idempotency tests
import_tasks: ../tests/key_idempotency.yml
- name: Import remove tests
import_tasks: ../tests/remove.yml
when: not (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6")
- name: Import ssh-agent tests
import_tasks: ../tests/ssh-agent.yml
when: openssh_version is version("7.6",">=")
environment:
SSH_AUTH_SOCK: "{{ openssh_agent_sock }}"
block:
- name: Generate keypair for agent tests
openssh_keypair:
path: '{{ output_dir }}/id_key'
type: rsa
size: 2048
- name: Generate always valid cert using agent without key in agent (should fail)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: yes
valid_from: always
valid_to: forever
register: rc_no_key_in_agent
ignore_errors: yes
- name: Make sure cert creation with agent fails if key not in agent
assert:
that:
- rc_no_key_in_agent is failed
- "'agent contains no identities' in rc_no_key_in_agent.msg or 'not found in agent' in rc_no_key_in_agent.msg"
- name: Add key to agent
command: 'ssh-add {{ output_dir }}/id_key'
- name: Generate always valid cert with agent (check mode)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: yes
valid_from: always
valid_to: forever
check_mode: yes
- name: Generate always valid cert with agent
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: yes
valid_from: always
valid_to: forever
- name: Generate always valid cert with agent (idempotent)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: yes
valid_from: always
valid_to: forever
register: rc_cert_with_agent_idempotent
- name: Check agent idempotency
assert:
that:
- rc_cert_with_agent_idempotent is not changed
msg: OpenSSH certificate generation without serial number is idempotent.
- name: Generate always valid cert with agent (idempotent, check mode)
openssh_cert:
type: user
signing_key: '{{ output_dir }}/id_key'
public_key: '{{ output_dir }}/id_key.pub'
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: yes
valid_from: always
valid_to: forever
check_mode: yes
- name: Remove keypair for agent tests
openssh_keypair:
path: '{{ output_dir }}/id_key'
state: absent
- name: Remove certificate
openssh_cert:
state: absent
path: '{{ output_dir }}/id_cert_with_agent'
- name: Remove keypair
openssh_keypair:
path: "{{ signing_key }}"
state: absent

View File

@@ -0,0 +1,272 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- set_fact:
test_cases:
- test_name: Generate cert - force option (check_mode)
force: true
type: user
valid_from: always
valid_to: forever
check_mode: true
changed: true
- test_name: Generate cert - force option
force: true
type: user
valid_from: always
valid_to: forever
check_mode: true
changed: true
- test_name: Generate cert - force option (idempotent)
force: true
type: user
valid_from: always
valid_to: forever
check_mode: true
changed: true
- test_name: Generate cert - force option (idemopotent, check mode)
force: true
type: user
valid_from: always
valid_to: forever
check_mode: true
changed: true
- test_name: Generate always valid cert (check mode)
type: user
valid_from: always
valid_to: forever
check_mode: true
changed: true
- test_name: Generate always valid cert
type: user
valid_from: always
valid_to: forever
changed: true
- test_name: Generate always valid cert (idempotent)
type: user
valid_from: always
valid_to: forever
changed: false
- test_name: Generate always valid cert (idempotent, check mode)
type: user
valid_from: always
valid_to: forever
check_mode: true
changed: false
- test_name: Generate restricted validity cert with valid_at (check mode)
type: host
valid_from: +0s
valid_to: +32w
valid_at: +2w
check_mode: true
changed: true
- test_name: Generate restricted validity cert with valid_at
type: host
valid_from: +0s
valid_to: +32w
valid_at: +2w
changed: true
# Relative date time is based on current time so re-generation will occur in this case
- test_name: Generate restricted validity cert with valid_at (idempotent)
type: host
valid_from: +0s
valid_to: +32w
valid_at: +2w
changed: true
# Relative date time is based on current time so re-generation will occur in this case
- test_name: Generate restricted validity cert with valid_at (idempotent, check mode)
type: host
valid_from: +0s
valid_to: +32w
valid_at: +2w
check_mode: true
changed: true
- test_name: Generate always valid cert only for example.com and examplehost (check mode)
type: host
valid_from: always
valid_to: forever
principals: &principals
- example.com
- examplehost
check_mode: true
changed: true
- test_name: Generate always valid cert only for example.com and examplehost
type: host
valid_from: always
valid_to: forever
principals: *principals
changed: true
- test_name: Generate always valid cert only for example.com and examplehost (idempotent)
type: host
valid_from: always
valid_to: forever
principals: *principals
changed: false
- test_name: Generate always valid cert only for example.com and examplehost (idempotent, check mode)
type: host
valid_from: always
valid_to: forever
principals: *principals
check_mode: true
changed: false
- test_name: Generate always valid cert only for example.com and examplehost (idempotent, switch)
type: host
valid_from: always
valid_to: forever
principals:
- examplehost
- example.com
changed: false
- test_name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (check mode)
type: host
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: true
changed: true
- test_name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019
type: host
valid_from: "2001-01-21"
valid_to: "2019-01-21"
changed: true
- test_name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (idempotent)
type: host
valid_from: "2001-01-21"
valid_to: "2019-01-21"
changed: false
- test_name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (idempotent, check mode)
type: host
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: true
changed: false
- test_name: Generate an OpenSSH user Certificate with clear and force-command option (check mode)
type: user
options: &options
- "clear"
- "force-command=/tmp/bla/foo"
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: true
changed: true
- test_name: Generate an OpenSSH user Certificate with clear and force-command option
type: user
options: *options
valid_from: "2001-01-21"
valid_to: "2019-01-21"
changed: true
- test_name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent)
type: user
options: *options
valid_from: "2001-01-21"
valid_to: "2019-01-21"
changed: false
- test_name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent, check mode)
type: user
options: *options
valid_from: "2001-01-21"
valid_to: "2019-01-21"
check_mode: true
changed: false
- test_name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent, switch)
type: user
options:
- "force-command=/tmp/bla/foo"
- "clear"
valid_from: "2001-01-21"
valid_to: "2019-01-21"
changed: false
# Options are currently not checked for idempotency purposes
- test_name: Generate an OpenSSH user Certificate with no options (idempotent)
type: user
valid_from: "2001-01-21"
valid_to: "2019-01-21"
changed: false
- test_name: Generate cert without serial
type: user
valid_from: always
valid_to: forever
changed: true
- test_name: Generate cert without serial (idempotent)
type: user
valid_from: always
valid_to: forever
changed: false
- test_name: Generate cert with serial 42
type: user
valid_from: always
valid_to: forever
serial_number: 42
changed: true
- test_name: Generate cert with serial 42 (idempotent)
type: user
valid_from: always
valid_to: forever
serial_number: 42
changed: false
- test_name: Generate cert with changed serial number
type: user
valid_from: always
valid_to: forever
serial_number: 1337
changed: true
- test_name: Generate cert with removed serial number
type: user
valid_from: always
valid_to: forever
serial_number: 0
changed: true
- test_name: Generate a new cert with serial number
type: user
valid_from: always
valid_to: forever
serial_number: 42
changed: true
- test_name: Generate cert again, omitting the parameter serial_number (idempotent)
type: user
valid_from: always
valid_to: forever
changed: false
# Identifiers are not included in idempotency checks so a new cert will not be generated
- test_name: Generate cert with identifier
type: user
identifier: foo
valid_from: always
valid_to: forever
changed: false
- name: Execute idempotency tests
openssh_cert:
force: "{{ test_case.force | default(omit) }}"
identifier: "{{ test_case.identifier | default(omit) }}"
options: "{{ test_case.options | default(omit) }}"
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
principals: "{{ test_case.principals | default(omit) }}"
serial_number: "{{ test_case.serial_number | default(omit) }}"
signing_key: "{{ signing_key }}"
state: "{{ test_case.state | default(omit) }}"
type: "{{ test_case.type | default(omit) }}"
valid_at: "{{ test_case.valid_at | default(omit) }}"
valid_from: "{{ test_case.valid_from | default(omit) }}"
valid_to: "{{ test_case.valid_to | default(omit) }}"
check_mode: "{{ test_case.check_mode | default(omit) }}"
register: idempotency_test_output
loop: "{{ test_cases }}"
loop_control:
loop_var: test_case
- name: Assert task statuses
assert:
that:
- result.changed == test_cases[index].changed
loop: "{{ idempotency_test_output.results }}"
loop_control:
index_var: index
loop_var: result
- name: Remove certificate
openssh_cert:
path: "{{ certificate_path }}"
state: absent

View File

@@ -0,0 +1,58 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- set_fact:
new_signing_key: "{{ output_dir }}/new_key"
new_public_key: "{{ output_dir }}/new_key.pub"
- name: Generate new test key
openssh_keypair:
path: "{{ new_signing_key }}"
- name: Generate cert with original keys
openssh_cert:
type: user
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ signing_key }}"
valid_from: always
valid_to: forever
- name: Generate cert with new signing key
openssh_cert:
type: user
path: "{{ certificate_path }}"
public_key: "{{ public_key }}"
signing_key: "{{ new_signing_key }}"
valid_from: always
valid_to: forever
register: new_signing_key_output
- name: Generate cert with new public key
openssh_cert:
type: user
path: "{{ certificate_path }}"
public_key: "{{ new_public_key }}"
signing_key: "{{ signing_key }}"
valid_from: always
valid_to: forever
register: new_public_key_output
# Signing key and public key are not considered during idempotency checks
- name: Assert changes to public key or signing key results in no change
assert:
that:
- new_signing_key_output is not changed
- new_public_key_output is not changed
- name: Remove certificate
openssh_cert:
path: "{{ certificate_path }}"
state: absent
- name: Remove new keypair
openssh_keypair:
path: "{{ new_signing_key }}"
state: absent

View File

@@ -0,0 +1,61 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- set_fact:
test_cases:
- test_name: Generate certificate
type: user
signing_key: "{{ signing_key }}"
public_key: "{{ public_key }}"
path: "{{ certificate_path }}"
valid_from: always
valid_to: forever
changed: true
- test_name: Remove certificate (check mode)
state: absent
path: "{{ certificate_path }}"
check_mode: true
changed: true
- test_name: Remove certificate
state: absent
path: "{{ certificate_path }}"
changed: true
- test_name: Remove certificate (idempotent)
state: absent
path: "{{ certificate_path }}"
changed: false
- test_name: Remove certificate (idempotent, check mode)
state: absent
path: "{{ certificate_path }}"
check_mode: true
changed: false
- name: Execute remove tests
openssh_cert:
options: "{{ test_case.options | default(omit) }}"
path: "{{ test_case.path | default(omit) }}"
public_key: "{{ test_case.public_key | default(omit) }}"
principals: "{{ test_case.principals | default(omit) }}"
serial_number: "{{ test_case.serial_number | default(omit) }}"
signing_key: "{{ test_case.signing_key | default(omit) }}"
state: "{{ test_case.state | default(omit) }}"
type: "{{ test_case.type | default(omit) }}"
valid_at: "{{ test_case.valid_at | default(omit) }}"
valid_from: "{{ test_case.valid_from | default(omit) }}"
valid_to: "{{ test_case.valid_to | default(omit) }}"
check_mode: "{{ test_case.check_mode | default(omit) }}"
register: remove_test_output
loop: "{{ test_cases }}"
loop_control:
loop_var: test_case
- name: Assert task statuses
assert:
that:
- result.changed == test_cases[index].changed
loop: "{{ remove_test_output.results }}"
loop_control:
index_var: index
loop_var: result

View File

@@ -0,0 +1,83 @@
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: SSH-agent test block
environment:
SSH_AUTH_SOCK: "{{ openssh_agent_sock }}"
block:
- name: Generate always valid cert using agent without key in agent (should fail)
openssh_cert:
type: user
signing_key: "{{ signing_key }}"
public_key: "{{ public_key }}"
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: true
valid_from: always
valid_to: forever
register: rc_no_key_in_agent
ignore_errors: true
- name: Make sure cert creation with agent fails if key not in agent
assert:
that:
- rc_no_key_in_agent is failed
- "'agent contains no identities' in rc_no_key_in_agent.msg or 'not found in agent' in rc_no_key_in_agent.msg"
- name: Add key to agent
command: 'ssh-add {{ signing_key }}'
- name: Generate always valid cert with agent (check mode)
openssh_cert:
type: user
signing_key: "{{ signing_key }}"
public_key: "{{ public_key }}"
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: true
valid_from: always
valid_to: forever
check_mode: true
- name: Generate always valid cert with agent
openssh_cert:
type: user
signing_key: "{{ signing_key }}"
public_key: "{{ public_key }}"
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: true
valid_from: always
valid_to: forever
- name: Generate always valid cert with agent (idempotent)
openssh_cert:
type: user
signing_key: "{{ signing_key }}"
public_key: "{{ public_key }}"
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: true
valid_from: always
valid_to: forever
register: rc_cert_with_agent_idempotent
- name: Check agent idempotency
assert:
that:
- rc_cert_with_agent_idempotent is not changed
msg: OpenSSH certificate generation without serial number is idempotent.
- name: Generate always valid cert with agent (idempotent, check mode)
openssh_cert:
type: user
signing_key: "{{ signing_key }}"
public_key: "{{ public_key }}"
path: '{{ output_dir }}/id_cert_with_agent'
use_agent: true
valid_from: always
valid_to: forever
check_mode: true
- name: Remove certificate
openssh_cert:
state: absent
path: '{{ output_dir }}/id_cert_with_agent'