From 518847a92c7984197990521d4701d88882687015 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 4 Jul 2024 10:15:22 +0200 Subject: [PATCH] CI: DSA SSH keys are no longer supported with OpenSSH 9.8p1 (#776) * DSA SSH keys are no longer supported with OpenSSH 9.8p1. * Add more compatibility tests. --- .../targets/openssh_keypair/meta/main.yml | 1 + .../targets/openssh_keypair/tests/options.yml | 12 +- .../openssh_keypair/tests/regenerate.yml | 151 +++++++++--------- .../filter_plugins/jinja_compatibility.py | 25 +++ .../targets/setup_ssh_keygen/tasks/main.yml | 4 + 5 files changed, 115 insertions(+), 78 deletions(-) diff --git a/tests/integration/targets/openssh_keypair/meta/main.yml b/tests/integration/targets/openssh_keypair/meta/main.yml index 649911a9c..28c4c8495 100644 --- a/tests/integration/targets/openssh_keypair/meta/main.yml +++ b/tests/integration/targets/openssh_keypair/meta/main.yml @@ -4,6 +4,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later dependencies: + - prepare_jinja2_compat - setup_ssh_keygen - setup_openssl - setup_bcrypt diff --git a/tests/integration/targets/openssh_keypair/tests/options.yml b/tests/integration/targets/openssh_keypair/tests/options.yml index 0d324939c..96d7e4f5c 100644 --- a/tests/integration/targets/openssh_keypair/tests/options.yml +++ b/tests/integration/targets/openssh_keypair/tests/options.yml @@ -9,9 +9,11 @@ #################################################################### - set_fact: - key_types: + key_types: "{{ key_types_src | reject('equalto', '') | list }}" + vars: + key_types_src: - rsa - - dsa + - "{{ 'dsa' if openssh_supports_dsa else '' }}" - ecdsa - name: "({{ backend }}) Generate keys with default size - size" @@ -29,9 +31,9 @@ - name: "({{ backend }}) Assert key sizes match default size - size" assert: that: - - key_size_output.results[0].stdout == '4096' - - key_size_output.results[1].stdout == '1024' - - key_size_output.results[2].stdout == '256' + - (key_size_output.results | selectattr('item', 'equalto', 'rsa') | first).stdout == '4096' + - not openssh_supports_dsa or (key_size_output.results | selectattr('item', 'equalto', 'dsa') | first).stdout == '1024' + - (key_size_output.results | selectattr('item', 'equalto', 'ecdsa') | first).stdout == '256' - name: "({{ backend }}) Remove keys - size" openssh_keypair: diff --git a/tests/integration/targets/openssh_keypair/tests/regenerate.yml b/tests/integration/targets/openssh_keypair/tests/regenerate.yml index f9e2f43b3..7d9e0b113 100644 --- a/tests/integration/targets/openssh_keypair/tests/regenerate.yml +++ b/tests/integration/targets/openssh_keypair/tests/regenerate.yml @@ -264,90 +264,95 @@ - [ '', '.pub' ] when: "item.0 != 'always'" -- name: "({{ backend }}) Regenerate - adjust key type (check mode)" - openssh_keypair: - path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}' - type: dsa - size: 1024 - regenerate: '{{ item }}' - backend: "{{ backend }}" - check_mode: true - loop: "{{ regenerate_values }}" - ignore_errors: true - 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 +- vars: + ssh_type: '{{ "dsa" if openssh_supports_dsa else "ecdsa" }}' + ssh_size: '{{ 1024 if openssh_supports_dsa else omit }}' -- name: "({{ backend }}) Regenerate - adjust key type" - openssh_keypair: - path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}' - type: dsa - size: 1024 - regenerate: '{{ item }}' - backend: "{{ backend }}" - loop: "{{ regenerate_values }}" - ignore_errors: true - 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 + block: + - name: "({{ backend }}) Regenerate - adjust key type (check mode)" + openssh_keypair: + path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}' + type: '{{ ssh_type }}' + size: '{{ ssh_size }}' + regenerate: '{{ item }}' + backend: "{{ backend }}" + check_mode: true + loop: "{{ regenerate_values }}" + ignore_errors: true + 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: '{{ remote_tmp_dir }}/regenerate-a-always{{ item.1 }}' - dest: '{{ remote_tmp_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" + openssh_keypair: + path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}' + type: '{{ ssh_type }}' + size: '{{ ssh_size }}' + regenerate: '{{ item }}' + backend: "{{ backend }}" + loop: "{{ regenerate_values }}" + ignore_errors: true + 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 comment (check mode)" - openssh_keypair: - path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}' - type: dsa - size: 1024 - comment: test comment - regenerate: '{{ item }}' - backend: "{{ backend }}" - check_mode: true - loop: "{{ regenerate_values }}" - ignore_errors: true - register: result -- assert: - that: - - result is changed + - name: "({{ backend }}) Regenerate - redistribute keys" + copy: + src: '{{ remote_tmp_dir }}/regenerate-a-always{{ item.1 }}' + dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}' + remote_src: true + with_nested: + - "{{ regenerate_values }}" + - [ '', '.pub' ] + when: "item.0 != 'always'" -# Support for updating comments for key types other than rsa1 was added in OpenSSH 7.2 -- when: not (backend == 'opensshbin' and openssh_version is version('7.2', '<')) - block: - - name: "({{ backend }}) Regenerate - adjust comment" + - name: "({{ backend }}) Regenerate - adjust comment (check mode)" openssh_keypair: path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}' - type: dsa - size: 1024 + type: '{{ ssh_type }}' + size: '{{ ssh_size }}' comment: test comment regenerate: '{{ item }}' backend: "{{ backend }}" + check_mode: true loop: "{{ regenerate_values }}" + ignore_errors: true register: result - assert: that: - result is changed - # for all values but 'always', the key should not be 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 + + # Support for updating comments for key types other than rsa1 was added in OpenSSH 7.2 + - when: not (backend == 'opensshbin' and openssh_version is version('7.2', '<')) + block: + - name: "({{ backend }}) Regenerate - adjust comment" + openssh_keypair: + path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}' + type: '{{ ssh_type }}' + size: '{{ ssh_size }}' + 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 not be 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 diff --git a/tests/integration/targets/prepare_jinja2_compat/filter_plugins/jinja_compatibility.py b/tests/integration/targets/prepare_jinja2_compat/filter_plugins/jinja_compatibility.py index 98180a177..6a27dcc4c 100644 --- a/tests/integration/targets/prepare_jinja2_compat/filter_plugins/jinja_compatibility.py +++ b/tests/integration/targets/prepare_jinja2_compat/filter_plugins/jinja_compatibility.py @@ -85,6 +85,20 @@ def call_filter(environment, name, value, args=None, kwargs=None, return func(value, *args, **(kwargs or {})) +@contextfilter +def compatibility_select_filter(context, sequence, test_name, *args, **kwargs): + for item in sequence: + if call_test(context.environment, test_name, item, args, kwargs): + yield item + + +@contextfilter +def compatibility_reject_filter(context, sequence, test_name, *args, **kwargs): + for item in sequence: + if not call_test(context.environment, test_name, item, args, kwargs): + yield item + + def make_attrgetter(environment, attribute_str, default=None): attributes = [int(attribute) if attribute.isdigit() else attribute for attribute in attribute_str.split(".")] @@ -106,6 +120,14 @@ def compatibility_selectattr_filter(context, sequence, attribute_str, test_name, yield item +@contextfilter +def compatibility_rejectattr_filter(context, sequence, attribute_str, test_name, *args, **kwargs): + f = make_attrgetter(context.environment, attribute_str) + for item in sequence: + if not call_test(context.environment, test_name, f(item), args, kwargs): + yield item + + def prepare_map(context, args, kwargs): if len(args) == 0 and "attribute" in kwargs: attribute = kwargs.pop("attribute") @@ -139,6 +161,9 @@ class FilterModule: def filters(self): return { + 'select': compatibility_select_filter, 'selectattr': compatibility_selectattr_filter, + 'reject': compatibility_reject_filter, + 'rejectattr': compatibility_rejectattr_filter, 'map': compatibility_map_filter, } diff --git a/tests/integration/targets/setup_ssh_keygen/tasks/main.yml b/tests/integration/targets/setup_ssh_keygen/tasks/main.yml index 22574431d..3798388ab 100644 --- a/tests/integration/targets/setup_ssh_keygen/tasks/main.yml +++ b/tests/integration/targets/setup_ssh_keygen/tasks/main.yml @@ -25,3 +25,7 @@ - name: Set ssh version facts set_fact: openssh_version: "{{ rc_openssh_version_output.stdout.strip() }}" + +- name: Set ssh support facts + set_fact: + openssh_supports_dsa: "{{ openssh_version is version('9.8', '<') }}"