mirror of
https://github.com/willshersystems/ansible-sshd
synced 2024-11-10 05:33:29 +01:00
860e533713
Previously no hostkeys were checked if they were not present in the generated configuration file. When the drop-in directory is used, usually, there are no hostkeys in that file and no sanity check for hostkeys was executed. This amends the "auto" value for the hostkeys check to allow checking for default hostkeys that are read by OpenSSH by default. Signed-off-by: Jakub Jelen <jjelen@redhat.com>
239 lines
7.7 KiB
YAML
239 lines
7.7 KiB
YAML
---
|
|
- 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 | d([])
|
|
|
|
- name: Check the userspace FIPS mode
|
|
slurp:
|
|
src: /etc/system-fips
|
|
register: __sshd_userspace_fips_mode
|
|
failed_when: false
|
|
when:
|
|
- __sshd_hostkeys_nofips | d([])
|
|
|
|
- name: Make sure hostkeys are available and have expected permissions
|
|
vars: &share_vars
|
|
__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
|
|
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)
|
|
|
|
- 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) != 'kvm'
|
|
- ansible_virtualization_type|default(None) != 'docker'
|
|
- ansible_virtualization_type|default(None) != 'podman'
|
|
- ansible_virtualization_type|default(None) != 'container'
|
|
- 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
|