tMakes drop-in functionality configurable by the user

This commit is contained in:
Nikolaos Kakouros 2022-08-17 14:34:35 +00:00
parent 5f67c9b3d2
commit 6bb0d7b456
14 changed files with 140 additions and 30 deletions

View file

@ -17,7 +17,11 @@ jobs:
' __sshd_skip_virt_env: "{{ __sshd_skip_virt_env }}"'
' __sshd_config_file: "{{ __sshd_config_file }}"'
>> tasks/variables.yml
- run: "sed -i -e '/public: true/d' tests/tasks/restore.yml tests/tests_duplicate_role.yml"
- run: >-
sed -i -e '/public: true/d'
tests/tasks/restore.yml
tests/tests_duplicate_role.yml
tests/tests_os_defaults.yml
- run: "sed -i -e 's/ansible.builtin.//g' */*.yml */*/*.yml"
- name: ansible check with centos 6

View file

@ -59,8 +59,7 @@ If set to *false*, the role will be completely disabled. Defaults to *true*.
If set to *true*, don't apply default values. This means that you must have a
complete set of configuration defaults via either the `sshd` dict, or
`sshd_Key` variables. Defaults to *false* unless `sshd_config_namespace` is
set or `sshd_config_file` points to the drop-in directory defined by
`__sshd_drop_in_dir` to avoid recursive include.
set or `sshd_config_file` points to a drop-in directory to avoid recursive include.
* `sshd_manage_service`
@ -167,17 +166,17 @@ The path where the openssh configuration produced by this role should be saved.
This is useful mostly when generating configuration snippets to Include from
drop-in directory (default in Fedora and RHEL9).
When this path points to system drop-in directory (defined with internal
variable `__sshd_drop_in_dir`), the main configuration file (defined with
internal variable `__sshd_main_config_file`) is checked to contain the
default `Include` directive from `__sshd_defaults` dict.
When this path points to a drop-in directory (like
`/etc/ssh/sshd_confg.d/00-custom.conf`), the main configuration file (defined
with the variable `sshd_main_config_file`) is checked to contain a proper
`Include` directive.
* `sshd_config_namespace`
By default (*null*), the role defines whole content of the configuration file
including system defaults. You can use this variable to invoke this role from
other roles or from multiple places in a single playbook on systems that do not
support drop-in directory. The `sshd_skip_defaults` is ignored and no system
other roles or from multiple places in a single playbook as an alternative to
using a drop-in directory. The `sshd_skip_defaults` is ignored and no system
defaults are used in this case.
When this variable is set, the role places the configuration that you specify

View file

@ -57,6 +57,9 @@ sshd_binary: "{{ __sshd_binary }}"
sshd_service: "{{ __sshd_service }}"
sshd_sftp_server: "{{ __sshd_sftp_server }}"
sshd_drop_in_dir_mode: "{{ __sshd_drop_in_dir_mode }}"
sshd_main_config_file: "{{ __sshd_main_config_file }}"
# This lists by default all hostkeys as rendered in the generated configuration
# file ("auto"). Before attempting to run sshd (either for verification of
# configuration or restarting), we make sure the keys exist and have correct

View file

@ -20,8 +20,9 @@
{% set value = override %}
{% elif sshd[key] is defined %}
{% set value = sshd[key] %}
{% elif __sshd_drop_in_dir and sshd_config_file.startswith(__sshd_drop_in_dir) %}
{# The drop-in directory does not use the defaults from main file to avoid recursion #}
{% elif sshd_main_config_file is not none
and sshd_config_file | dirname != sshd_main_config_file | dirname %}
{# Do not use the defaults from main file to avoid recursion #}
{% elif __sshd_defaults[key] is defined and not sshd_skip_defaults %}
{% if key == 'HostKey' and __sshd_fips_mode %}
{% set value = __sshd_defaults[key] | difference(__sshd_hostkeys_nofips) %}

View file

@ -119,7 +119,7 @@
group: root
mode: "{{ __sshd_runtime_directory_mode }}"
when:
- __sshd_runtime_directory | d(false)
- __sshd_runtime_directory is not none
- name: Create the complete configuration file
ansible.builtin.include_tasks: install_config.yml

View file

@ -1,4 +1,13 @@
---
- name: Create a directory for drop-in configuration snippets
ansible.builtin.file:
path: "{{ sshd_config_file | dirname }}"
state: directory
mode: "{{ sshd_drop_in_dir_mode }}"
when:
- sshd_main_config_file is not none
- sshd_config_file | dirname != sshd_main_config_file | dirname
- name: Create the complete configuration file
ansible.builtin.template:
src: sshd_config.j2
@ -18,8 +27,8 @@
- name: Make sure the include path is present in the main sshd_config
ansible.builtin.lineinfile:
insertbefore: BOF
line: "Include {{ __sshd_defaults['Include'] }}"
path: "{{ __sshd_main_config_file }}"
line: "Include {{ sshd_config_file | dirname }}/*.conf"
path: "{{ sshd_main_config_file }}"
owner: "{{ sshd_config_owner }}"
group: "{{ sshd_config_group }}"
mode: "{{ sshd_config_mode }}"
@ -32,7 +41,5 @@
backup: "{{ sshd_backup }}"
notify: reload_sshd
when:
- __sshd_defaults['Include'] | d(false)
- __sshd_main_config_file is not none
- __sshd_drop_in_dir is not none
- sshd_config_file.startswith(__sshd_drop_in_dir)
- sshd_main_config_file is not none
- sshd_config_file | dirname != sshd_main_config_file | dirname

View file

@ -21,8 +21,9 @@
{% set value = override %}
{% elif sshd[key] is defined %}
{% set value = sshd[key] %}
{% elif __sshd_drop_in_dir and sshd_config_file.startswith(__sshd_drop_in_dir) %}
{# The drop-in directory does not use the defaults from main file to avoid recursion #}
{% elif sshd_main_config_file is not none
and sshd_config_file | dirname != sshd_main_config_file | dirname %}
{# Do not use the defaults from main file to avoid recursion #}
{% elif __sshd_defaults[key] is defined and not sshd_skip_defaults %}
{% if key == 'HostKey' and __sshd_fips_mode %}
{% set value = __sshd_defaults[key] | difference(__sshd_hostkeys_nofips) %}

View file

@ -20,8 +20,9 @@
{% set value = override %}
{% elif sshd[key] is defined %}
{% set value = sshd[key] %}
{% elif __sshd_drop_in_dir and sshd_config_file.startswith(__sshd_drop_in_dir) %}
{# The drop-in directory does not use the defaults from main file to avoid recursion #}
{% elif sshd_main_config_file is not none
and sshd_config_file | dirname != sshd_main_config_file | dirname %}
{# Do not use the defaults from main file to avoid recursion #}
{% elif __sshd_defaults[key] is defined and not sshd_skip_defaults %}
{% if key == 'HostKey' and __sshd_fips_mode %}
{% set value = __sshd_defaults[key] | difference(__sshd_hostkeys_nofips) %}

View file

@ -81,3 +81,85 @@
- name: "Restore configuration files"
ansible.builtin.include_tasks: tasks/restore.yml
- hosts: all
vars:
__sshd_test_backup_files:
- /etc/ssh/custom_sshd_config
- /etc/ssh/custom_sshd_config.d/custom-drop-in
tasks:
- name: Run only for a specific OS with an capable OpenSSH version
ansible.builtin.meta: end_play
when:
ansible_facts['distribution'] != 'Ubuntu'
or ansible_facts['distribution_major_version']|int != 20
- name: "Backup configuration files"
ansible.builtin.include_tasks: tasks/backup.yml
- name: Create dummy main configuration file
# Normally, this should not be needed. For test, however, we need a file
# different to the one in the first play.
file:
path: /etc/ssh/custom_sshd_config
state: touch
- name: Create a new configuration in a custom drop-in directory
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd_config_file: /etc/ssh/custom_sshd_config.d/custom-drop-in
sshd_main_config_file: /etc/ssh/custom_sshd_config
sshd_drop_in_dir_mode: '0770'
sshd:
Banner: /etc/include-issue
Ciphers: aes192-ctr
- name: Verify the options are correctly set
block:
- name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: Print custom drop-in configuration file
ansible.builtin.slurp:
src: /etc/ssh/custom_sshd_config.d/custom-drop-in
register: custom_drop_in
- name: Print the custom configuration file
ansible.builtin.slurp:
src: /etc/ssh/custom_sshd_config
register: custom_config
- name: Check content of custom drop-in configuration file
ansible.builtin.assert:
that:
- "'Banner /etc/include-issue' in custom_drop_in.content | b64decode"
- "'Ciphers aes192-ctr' in custom_drop_in.content | b64decode"
- "'Include /etc/ssh/custom_sshd_config.d/*.conf' not in custom_drop_in.content | b64decode"
- "'Subsystem sftp /usr/libexec/openssh/sftp-server' not in custom_drop_in.content | b64decode"
- "'Subsystem sftp /usr/lib/openssh/sftp-server' not in custom_drop_in.content | b64decode"
- name: Check common content of the custom configuration file
ansible.builtin.assert:
that:
- "'Banner /etc/include-issue' not in custom_config.content | b64decode"
- "'Ciphers aes192-ctr' not in custom_config.content | b64decode"
- "'Include /etc/ssh/custom_sshd_config.d/*.conf' in custom_config.content | b64decode"
- name: Read drop in directory mode
ansible.builtin.stat:
path: "/etc/ssh/custom_sshd_config.d"
register: drop_in_dir_stat
- name: Check drop in directory mode has been set correctly
assert:
that:
- drop_in_dir_stat.stat.isdir | bool
- drop_in_dir_stat.stat.mode == '0770'
msg: "effective mode: {{ drop_in_dir_stat.stat.mode }}, desired mode: 0770"
tags: tests::verify
- name: "Restore configuration files"
ansible.builtin.include_tasks: tasks/restore.yml

View file

@ -27,6 +27,7 @@
- name: Configure sshd
ansible.builtin.include_role:
name: ansible-sshd
public: true
- name: Show effective configuration after running role (role defaults)
ansible.builtin.command: sshd -T
@ -41,5 +42,17 @@
# RHEL6/CentOS6 images have modified sshd_config, different from what is in rpm package
- not (ansible_facts['os_family'] == 'RedHat' and ansible_facts['distribution_major_version'] == '6')
- name: Read drop in directory mode
ansible.builtin.stat:
path: "{{ __sshd_defaults.Include | dirname }}"
register: drop_in_dir_stat
when: __sshd_defaults.Include is defined
- name: Check drop in directory mode has not changed
assert:
that:
- drop_in_dir_stat.stat.mode == __sshd_drop_in_dir_mode
when: __sshd_defaults.Include is defined
- name: Restore configuration files
ansible.builtin.include_tasks: tasks/restore.yml

View file

@ -23,5 +23,5 @@ __sshd_hostkeys_nofips:
__sshd_hostkey_group: ssh_keys
__sshd_hostkey_mode: "0640"
__sshd_drop_in_dir: /etc/ssh/sshd_config.d/
__sshd_drop_in_dir_mode: '0700'
__sshd_main_config_file: /etc/ssh/sshd_config

View file

@ -23,5 +23,5 @@ __sshd_hostkeys_nofips:
__sshd_hostkey_group: ssh_keys
__sshd_hostkey_mode: "0640"
__sshd_drop_in_dir: /etc/ssh/sshd_config.d/
__sshd_drop_in_dir_mode: '0700'
__sshd_main_config_file: /etc/ssh/sshd_config

View file

@ -19,5 +19,5 @@ __sshd_defaults:
__sshd_runtime_directory: /run/sshd
__sshd_drop_in_dir: /etc/ssh/sshd_config.d/
__sshd_drop_in_dir_mode: '0755'
__sshd_main_config_file: /etc/ssh/sshd_config

View file

@ -31,15 +31,14 @@ __sshd_os_supported: no
__sshd_sysconfig_supports_crypto_policy: false
__sshd_sysconfig_supports_use_strong_rng: false
__sshd_runtime_directory: false
__sshd_runtime_directory: ~
__sshd_runtime_directory_mode: "0755"
# If the system supports drop-in directory, it is configured in this variable. It is used
# to distinguish if we are writing a configuration snippet or we should write defaults.
__sshd_drop_in_dir: false
# this is the path to the main sshd_config which is checked for Include directive when
# drop-in directory is used
__sshd_main_config_file: false
__sshd_main_config_file: ~
__sshd_drop_in_dir_mode: '0755'
# The list of hostkeys to check when there are none listed in configuration file.
# This is usually the case when the selection is up to the OpenSSH defaults or