--- - name: OS is supported meta: end_host when: - not __sshd_os_supported|bool - name: Install ssh packages package: name: "{{ sshd_packages }}" state: present - name: Sysconfig configuration 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 the kernel FIPS mode slurp: src: /proc/sys/crypto/fips_enabled register: __sshd_kernel_fips_mode failed_when: false when: - __sshd_hostkeys_nofips != [] - name: Check the userspace FIPS mode slurp: src: /etc/system-fips register: __sshd_userspace_fips_mode failed_when: false when: - __sshd_hostkeys_nofips != [] - name: Make sure hostkeys are available and have expected permissions vars: &share_vars __sshd_fips_mode: >- __sshd_hostkeys_nofips != [] and \ (__sshd_kernel_fips_mode.content | b64decode == "1" | bool or \ __sshd_kernel_fips_mode.content | b64decode != "0" | bool) # 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 %} [] {% endif %} __sshd_verify_hostkeys: >- {% if not sshd_verify_hostkeys %} [] {% elif sshd_verify_hostkeys == 'auto' %} {% if sshd_HostKey is string %} [ {{ __sshd_hostkeys_from_config }} ] {% else %} {{ __sshd_hostkeys_from_config }} {% endif %} {% else %} {{ sshd_verify_hostkeys | to_json }} {% endif %} block: - name: Make sure hostkeys are available 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 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 tempfile: state: directory register: sshd_test_hostkey changed_when: false when: - __sshd_hostkeys_from_config | from_json == [] - name: Generate temporary hostkey 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 file: path: "{{ __sshd_runtime_directory }}" state: directory owner: root group: root mode: "{{ __sshd_runtime_directory_mode }}" when: - __sshd_runtime_directory | d(false) | bool - name: Create the complete configuration file template: src: sshd_config.j2 dest: "{{ sshd_config_file }}" owner: "{{ sshd_config_owner }}" group: "{{ sshd_config_group }}" mode: "{{ sshd_config_mode }}" validate: >- {% if sshd_test_hostkey is defined and sshd_test_hostkey.path is defined %} {{ sshd_binary }} -t -f %s -h {{ sshd_test_hostkey.path }}/rsa_key {% else %} {{ sshd_binary }} -t -f %s {% endif %} backup: "{{ sshd_backup }}" notify: reload_sshd when: sshd_config_namespace is none - name: Update configuration file snippet vars: sshd_skip_defaults: true blockinfile: path: "{{ sshd_config_file }}" owner: "{{ sshd_config_owner }}" group: "{{ sshd_config_group }}" mode: "{{ sshd_config_mode }}" block: | {{ __sshd_compat_match_all }} {{ lookup('template', 'sshd_config_snippet.j2') }} create: yes marker: "# {mark} sshd system role managed block: namespace {{ sshd_config_namespace }}" validate: >- {% if sshd_test_hostkey is defined and sshd_test_hostkey.path is defined %} {{ sshd_binary }} -t -f %s -h {{ sshd_test_hostkey.path }}/rsa_key {% else %} {{ sshd_binary }} -t -f %s {% endif %} backup: "{{ sshd_backup }}" notify: reload_sshd when: sshd_config_namespace is not none rescue: - name: re-raise the error fail: msg: "{{ ansible_failed_result }}" always: - name: Remove temporary host keys file: path: "{{ sshd_test_hostkey.path }}" state: absent changed_when: false when: sshd_test_hostkey.path is defined - name: Install systemd service files block: - name: Install service unit file template: src: "{{ sshd_service_template_service }}" dest: "/etc/systemd/system/{{ sshd_service }}.service" owner: root group: root mode: "0644" notify: reload_sshd - name: Install instanced service unit file template: src: "{{ sshd_service_template_at_service }}" dest: "/etc/systemd/system/{{ sshd_service }}@.service" owner: root group: root mode: "0644" notify: reload_sshd - name: Install socket unit file template: src: "{{ sshd_service_template_socket }}" dest: "/etc/systemd/system/{{ sshd_service }}.socket" owner: root group: root mode: "0644" notify: reload_sshd when: sshd_install_service|bool - name: Service enabled and running service: name: "{{ sshd_service }}" enabled: true state: started when: - sshd_manage_service|bool - ansible_virtualization_type|default(None) != 'docker' - ansible_virtualization_type|default(None) != 'podman' - ansible_virtualization_type|default(None) != 'containerd' - ansible_virtualization_type|default(None) != 'VirtualPC' # for Github Actions - ansible_connection != 'chroot' # Due to ansible bug 21026, cannot use service module on RHEL 7 - name: Enable service in chroot command: systemctl enable {{ sshd_service }} # noqa 303 when: - ansible_connection == 'chroot' - ansible_os_family == 'RedHat' - ansible_distribution_major_version|int >= 7 - name: Register that this role has run set_fact: sshd_has_run: true when: sshd_has_run is not defined