diff options
Diffstat (limited to '')
5 files changed, 424 insertions, 0 deletions
diff --git a/test/integration/targets/known_hosts/aliases b/test/integration/targets/known_hosts/aliases new file mode 100644 index 0000000..765b70d --- /dev/null +++ b/test/integration/targets/known_hosts/aliases @@ -0,0 +1 @@ +shippable/posix/group2 diff --git a/test/integration/targets/known_hosts/defaults/main.yml b/test/integration/targets/known_hosts/defaults/main.yml new file mode 100644 index 0000000..b1b56ac --- /dev/null +++ b/test/integration/targets/known_hosts/defaults/main.yml @@ -0,0 +1,6 @@ +--- +example_org_rsa_key: > + example.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAglyZmHHWskQ9wkh8LYbIqzvg99/oloneH7BaZ02ripJUy/2Zynv4tgUfm9fdXvAb1XXCEuTRnts9FBer87+voU0FPRgx3CfY9Sgr0FspUjnm4lqs53FIab1psddAaS7/F7lrnjl6VqBtPwMRQZG7qlml5uogGJwYJHxX0PGtsdoTJsM= + +example_org_ed25519_key: > + example.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzlnSq5ESxLgW0avvPk3j7zLV59hcAPkxrMNdnZMKP2
\ No newline at end of file diff --git a/test/integration/targets/known_hosts/files/existing_known_hosts b/test/integration/targets/known_hosts/files/existing_known_hosts new file mode 100644 index 0000000..2564f40 --- /dev/null +++ b/test/integration/targets/known_hosts/files/existing_known_hosts @@ -0,0 +1,5 @@ +example.com ssh-dss AAAAB3NzaC1kc3MAAACBALT8YHxZ59d8yX4oQNPbpdK9AMPRQGKFY9X13S2fp4UMPijiB3ETxU1bAyVTjTbsoag065naFt13aIVl+u0MDPfMuYgVJFEorAZkDlBixvT25zpKyQhI4CtHhZ9Y9YWug4xLqSaFUYEPO31Bie7k8xRfDwsHtzTRPp/0zRURwARHAAAAFQDLx2DZMm3cR8cZtbq4zdSvkXLh0wAAAIAalkQYziu2b5dDRQMiFpDLpPdbymyVhDMmRKnXwAB1+dhGyJLGvfe0xO+ibqGXMp1aZ1iC3a/vHTpYKDVqKIIpFg5r0fxAcAZkJR0aRC8RDxW/IclbIliETD71osIT8I47OFc7vAVCWP8JbV3ZYzR+i98WUkmZ4/ZUzsDl2gi7WAAAAIAsdTGwAo4Fs784TdP2tIHCqxAIz2k4tWmZyeRmXkH5K/P1o9XSh3RNxvFKK7BY6dQK+h9jLunMBs0SCzhMoTcXaJq331kmLJltjq5peo0PnLGnQz5pas0PD7p7gb+soklmHoVp7J2oMC/U4N1Rxr6g9sv8Rpsf1PTPDT3sEbze6A== root@freezer +|1|d71/U7CbOH3Su+d2zxlbmiNfXtI=|g2YSPAVoK7bmg16FCOOPKTZe2BM= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ== +|1|L0TqxOhAVh6mLZ2lbHdTv3owun0=|vn0La5pbHNxin3XzQQdvaOulvVU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCNLCAA/SjVF3jkmlAlkgh+GtZdgxtusHaK66fcA7XSgCpQOdri1dGmND6pQDGwsxiKMy4Ou1GB2DR4N0G9T5E8= +|1|WPo7yAOdlQKLSuRatNJCmDoga0k=|D/QybGglKokWuEQUe9Okpy5uSh0= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCNLCAA/SjVF3jkmlAlkgh+GtZdgxtusHaK66fcA7XSgCpQOdri1dGmND6pQDGwsxiKMy4Ou1GB2DR4N0G9T5E8= +# example.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM6OSqweGdPdQ/metQaf738AdN3P+itYp1AypOTgXkyj root@localhost diff --git a/test/integration/targets/known_hosts/meta/main.yml b/test/integration/targets/known_hosts/meta/main.yml new file mode 100644 index 0000000..cb6005d --- /dev/null +++ b/test/integration/targets/known_hosts/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_tests + - setup_remote_tmp_dir diff --git a/test/integration/targets/known_hosts/tasks/main.yml b/test/integration/targets/known_hosts/tasks/main.yml new file mode 100644 index 0000000..dc00ded --- /dev/null +++ b/test/integration/targets/known_hosts/tasks/main.yml @@ -0,0 +1,409 @@ +# test code for the known_hosts module +# (c) 2017, Marius Gedminas <marius@gedmin.as> + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +- name: copy an existing file in place + copy: + src: existing_known_hosts + dest: "{{ remote_tmp_dir }}/known_hosts" + +# test addition + +- name: add a new host in check mode + check_mode: yes + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + register: diff + +- name: assert that the diff looks as expected (the key was added at the end) + assert: + that: + - 'diff is changed' + - 'diff.diff.before_header == diff.diff.after_header == remote_tmp_dir|expanduser + "/known_hosts"' + - 'diff.diff.after.splitlines()[:-1] == diff.diff.before.splitlines()' + - 'diff.diff.after.splitlines()[-1] == example_org_rsa_key.strip()' + +- name: add a new host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts + +- name: assert that the key was added and ordering preserved + assert: + that: + - 'result is changed' + - 'known_hosts.stdout_lines[0].startswith("example.com")' + - 'known_hosts.stdout_lines[4].startswith("# example.net")' + - 'known_hosts.stdout_lines[-1].strip() == example_org_rsa_key.strip()' + +# test idempotence of addition + +- name: add the same host in check mode + check_mode: yes + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + register: check + +- name: assert that no changes were expected + assert: + that: + - 'check is not changed' + - 'check.diff.before == check.diff.after' + +- name: add the same host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v2 + +- name: assert that no changes happened + assert: + that: + - 'result is not changed' + - 'result.diff.before == result.diff.after' + - 'known_hosts.stdout == known_hosts_v2.stdout' + +# https://github.com/ansible/ansible/issues/78598 +# test removing nonexistent host key when the other keys exist for the host +- name: remove different key + known_hosts: + name: example.org + key: "{{ example_org_ed25519_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + register: result + +- name: remove nonexistent key with check mode + known_hosts: + name: example.org + key: "{{ example_org_ed25519_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + check_mode: yes + register: check_mode_result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_different_key_removal + +- name: assert that no changes happened + assert: + that: + - 'result is not changed' + - 'check_mode_result is not changed' + - 'result.diff.before == result.diff.after' + - 'known_hosts_v2.stdout == known_hosts_different_key_removal.stdout' + +# test removal + +- name: remove the host in check mode + check_mode: yes + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + register: diff + +- name: assert that the diff looks as expected (the key was removed) + assert: + that: + - 'diff.diff.before_header == diff.diff.after_header == remote_tmp_dir|expanduser + "/known_hosts"' + - 'diff.diff.before.splitlines()[-1] == example_org_rsa_key.strip()' + - 'diff.diff.after.splitlines() == diff.diff.before.splitlines()[:-1]' + +- name: remove the host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v3 + +- name: assert that the key was removed and ordering preserved + assert: + that: + - 'diff is changed' + - 'result is changed' + - '"example.org" not in known_hosts_v3.stdout' + - 'known_hosts_v3.stdout_lines[0].startswith("example.com")' + - 'known_hosts_v3.stdout_lines[-1].startswith("# example.net")' + +# test idempotence of removal + +- name: remove the same host in check mode + check_mode: yes + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + register: check + +- name: assert that no changes were expected + assert: + that: + - 'check is not changed' + - 'check.diff.before == check.diff.after' + +- name: remove the same host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v4 + +- name: assert that no changes happened + assert: + that: + - 'result is not changed' + - 'result.diff.before == result.diff.after' + - 'known_hosts_v3.stdout == known_hosts_v4.stdout' + +# test addition as hashed_host + +- name: add a new hashed host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + hash_host: yes + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v5 + +- name: assert that the key was added and ordering preserved + assert: + that: + - 'result is changed' + - 'known_hosts_v5.stdout_lines[0].startswith("example.com")' + - 'known_hosts_v5.stdout_lines[4].startswith("# example.net")' + - 'known_hosts_v5.stdout_lines[-1].strip().startswith("|1|")' + - 'known_hosts_v5.stdout_lines[-1].strip().endswith(example_org_rsa_key.strip().split()[-1])' + +# test idempotence of hashed addition + +- name: add the same host hashed + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + hash_host: yes + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v6 + +- name: assert that no changes happened + assert: + that: + - 'result is not changed' + - 'result.diff.before == result.diff.after' + - 'known_hosts_v5.stdout == known_hosts_v6.stdout' + +# test hashed removal + +- name: remove the hashed host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v7 + +- name: assert that the key was removed and ordering preserved + assert: + that: + - 'result is changed' + - 'example_org_rsa_key.strip().split()[-1] not in known_hosts_v7.stdout' + - 'known_hosts_v7.stdout_lines[0].startswith("example.com")' + - 'known_hosts_v7.stdout_lines[-1].startswith("# example.net")' + +# test idempotence of removal + +- name: remove the same hashed host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: absent + path: "{{remote_tmp_dir}}/known_hosts" + register: result + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v8 + +- name: assert that no changes happened + assert: + that: + - 'result is not changed' + - 'result.diff.before == result.diff.after' + - 'known_hosts_v7.stdout == known_hosts_v8.stdout' + +# test roundtrip plaintext => hashed => plaintext +# The assertions are rather relaxed, because most of this hash been tested previously + +- name: add a new host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v8 + +- name: assert the plaintext host is there + assert: + that: + - 'known_hosts_v8.stdout_lines[-1].strip() == example_org_rsa_key.strip()' + +- name: update the host to hashed mode + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + hash_host: true + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v9 + +- name: assert the hashed host is there + assert: + that: + - 'known_hosts_v9.stdout_lines[-1].strip().startswith("|1|")' + - 'known_hosts_v9.stdout_lines[-1].strip().endswith(example_org_rsa_key.strip().split()[-1])' + +- name: downgrade the host to plaintext mode + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v10 + +- name: assert the plaintext host is there + assert: + that: + - 'known_hosts_v10.stdout_lines[5].strip() == example_org_rsa_key.strip()' + +# ... and remove the host again for the next test + +- name: copy an existing file in place + copy: + src: existing_known_hosts + dest: "{{ remote_tmp_dir }}/known_hosts" + +# Test key changes + +- name: add a hashed host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + hash_host: true + +- name: change the key of a hashed host + known_hosts: + name: example.org + key: "{{ example_org_rsa_key.strip()[:-7] + 'RANDOM=' }}" + state: present + path: "{{remote_tmp_dir}}/known_hosts" + hash_host: true + +- name: get the file content + command: "cat {{remote_tmp_dir}}/known_hosts" + register: known_hosts_v11 + +- name: assert the change took place and the key got modified + assert: + that: + - 'known_hosts_v11.stdout_lines[-1].strip().endswith("RANDOM=")' + +# test errors + +- name: Try using a comma separated list of hosts + known_hosts: + name: example.org,acme.com + key: "{{ example_org_rsa_key }}" + path: "{{remote_tmp_dir}}/known_hosts" + ignore_errors: yes + register: result + +- name: Assert that error message was displayed + assert: + that: + - result is failed + - result.msg == 'Comma separated list of names is not supported. Please pass a single name to lookup in the known_hosts file.' + +- name: Try using a name that does not match the key + known_hosts: + name: example.com + key: "{{ example_org_rsa_key }}" + path: "{{remote_tmp_dir}}/known_hosts" + ignore_errors: yes + register: result + +- name: Assert that name checking failed with error message + assert: + that: + - result is failed + - result.msg == 'Host parameter does not match hashed host field in supplied key' |