--- - name: OS is supported ansible.builtin.meta: end_host when: - not __sshd_os_supported | bool - name: Install ssh packages ansible.builtin.package: name: "{{ sshd_packages }}" state: present use: "{{ (__sshd_is_ostree | d(false)) | ternary('ansible.posix.rhel_rpm_ostree', omit) }}" - name: Sysconfig configuration ansible.builtin.template: src: sysconfig.j2 dest: "/etc/sysconfig/sshd" owner: "root" group: "root" mode: "600" backup: "{{ sshd_backup }}" when: - sshd_sysconfig | bool - __sshd_sysconfig_supports_use_strong_rng or __sshd_sysconfig_supports_crypto_policy notify: reload_sshd - name: Check FIPS mode ansible.builtin.include_tasks: check_fips.yml when: - __sshd_hostkeys_nofips | d([]) - name: Make sure hostkeys are available and have expected permissions vars: &share_vars # 'MAo=' evaluates to '0\n' in base 64 encoding, which is default __sshd_fips_mode: >- {{ __sshd_hostkeys_nofips | d([]) and (__sshd_kernel_fips_mode.content | d('MAo=') | b64decode | trim == '1' or __sshd_userspace_fips_mode.content | d('MAo=') | b64decode | trim != '0') }} # This mimics the macro body_option() in sshd_config.j2 # The explicit to_json filter is needed for Python 2 compatibility __sshd_hostkeys_from_config: >- {% if sshd_HostKey is defined %} {{ sshd_HostKey | to_json }} {% elif sshd['HostKey'] is defined %} {{ sshd['HostKey'] | to_json }} {% elif __sshd_defaults['HostKey'] is defined and not sshd_skip_defaults %} {% if __sshd_fips_mode %} {{ __sshd_defaults['HostKey'] | difference(__sshd_hostkeys_nofips) | to_json }} {% else %} {{ __sshd_defaults['HostKey'] | to_json }} {% endif %} {% else %} {{ [] | to_json }} {% endif %} __sshd_verify_hostkeys: >- {% if not sshd_verify_hostkeys %} {{ [] | to_json }} {% elif sshd_verify_hostkeys == 'auto' %} {% if not __sshd_hostkeys_from_config | from_json %} {% if __sshd_fips_mode %} {{ __sshd_verify_hostkeys_default | difference(__sshd_hostkeys_nofips) | to_json }} {% else %} {{ __sshd_verify_hostkeys_default | to_json }} {% endif %} {% elif __sshd_hostkeys_from_config | from_json is string %} {{ [__sshd_hostkeys_from_config | from_json] | to_json }} {% else %} {{ __sshd_hostkeys_from_config }} {% endif %} {% else %} {{ sshd_verify_hostkeys | to_json }} {% endif %} block: - name: Make sure hostkeys are available ansible.builtin.shell: | set -eu if set -o | grep pipefail 2>&1 /dev/null ; then set -o pipefail fi {% if sshd_sysconfig %} source /etc/sysconfig/sshd {% endif %} ssh-keygen -q -t {{ item | regex_search('(rsa|dsa|ecdsa|ed25519)') }} -f {{ item }} -C '' -N '' args: creates: "{{ item }}" loop: "{{ __sshd_verify_hostkeys | from_json | list }}" changed_when: false - name: Make sure private hostkeys have expected permissions ansible.builtin.file: path: "{{ item }}" owner: "{{ sshd_hostkey_owner }}" group: "{{ sshd_hostkey_group }}" mode: "{{ sshd_hostkey_mode }}" loop: "{{ __sshd_verify_hostkeys | from_json | list }}" - name: Apply configuration vars: <<: *share_vars block: - name: Create a temporary hostkey for syntax verification if needed ansible.builtin.tempfile: state: directory register: sshd_test_hostkey changed_when: false when: - __sshd_hostkeys_from_config | from_json == [] - __sshd_supports_validate - name: Generate temporary hostkey ansible.builtin.command: > ssh-keygen -q -t rsa -f '{{ sshd_test_hostkey.path }}/rsa_key' -C '' -N '' changed_when: false when: sshd_test_hostkey.path is defined - name: Make sure sshd runtime directory is present ansible.builtin.file: path: "/run/{{ __sshd_runtime_directory }}" state: directory owner: root group: root mode: "{{ __sshd_runtime_directory_mode }}" when: - __sshd_runtime_directory is not none - name: Find SSHD ports ansible.builtin.include_tasks: find_ports.yml - name: Configure firewall ansible.builtin.include_tasks: firewall.yml when: - sshd_manage_firewall | bool - ansible_facts['os_family'] == 'RedHat' - ansible_facts['distribution_version'] is version('7', '>=') - ansible_facts['virtualization_type']|default(None) not in __sshd_skip_virt_env - name: Configure selinux ansible.builtin.include_tasks: selinux.yml when: - sshd_manage_selinux | bool - ansible_facts['os_family'] == 'RedHat' - ansible_facts['virtualization_type']|default(None) not in __sshd_skip_virt_env - name: Create the complete configuration file ansible.builtin.include_tasks: install_config.yml when: sshd_config_namespace is none - name: Update configuration file snippet ansible.builtin.include_tasks: install_namespace.yml when: sshd_config_namespace is not none - name: Configure sshd to use SSH certificates ansible.builtin.include_tasks: certificates.yml when: sshd_trusted_user_ca_keys_list != [] rescue: - name: Re-raise the error ansible.builtin.fail: msg: "{{ ansible_failed_result }}" always: - name: Remove temporary host keys ansible.builtin.file: path: "{{ sshd_test_hostkey.path }}" state: absent changed_when: false when: sshd_test_hostkey.path is defined - name: Install and start systemd service ansible.builtin.include_tasks: install_service.yml - name: Register that this role has run ansible.builtin.set_fact: sshd_has_run: true when: sshd_has_run is not defined