From a97a54dc30ab8e7a8e27fee2989caa337ed48057 Mon Sep 17 00:00:00 2001 From: seven-beep <142155646+seven-beep@users.noreply.github.com> Date: Sun, 13 Oct 2024 12:34:52 +0200 Subject: [PATCH] Provide granular noop for ssh configuration (#789) * Provide granular noop for shh configuration We would like to have more fine grained options on applying or not specific configurations. This commit let the user choose to noop some configuration with a few new boolean variables. Motivation for theses options are we may configure ourselves some (ssh host key regeneration in a templating system) or we are not ready for others (ssh_kex will break dist-upgrades, letting the operator without ssh). Signed-off-by: seven beep * Provide granula noop for ssh configuration We would like to have more fine grained options on applying or not specific configurations. This commit let the user choose to disable configurations for `ssh_host_key_config`, `ssh_ciphers_config`, `ssh_host_key_config`, `ssh_macs_config` by setting them to False. Motivation for theses options are we may configure ourselves some (ssh host key regeneration in a templating system) or we are not ready for others (ssh_kex will break dist-upgrades, letting the operator without ssh). Signed-off-by: seven beep --------- Signed-off-by: seven beep --- roles/ssh_hardening/README.md | 16 ++++++------ roles/ssh_hardening/defaults/main.yml | 6 ----- roles/ssh_hardening/meta/argument_specs.yml | 8 +++--- roles/ssh_hardening/tasks/hardening.yml | 11 +++++--- .../ssh_hardening/templates/opensshd.conf.j2 | 26 ++++++++++++++----- 5 files changed, 39 insertions(+), 28 deletions(-) diff --git a/roles/ssh_hardening/README.md b/roles/ssh_hardening/README.md index a0159040..00094185 100644 --- a/roles/ssh_hardening/README.md +++ b/roles/ssh_hardening/README.md @@ -139,8 +139,8 @@ For more information, see [this issue](https://github.com/dev-sec/ansible-collec - Type: bool - Required: no - `ssh_ciphers` - - Default: `` - - Description: Change this list to overwrite ciphers. Defaults found in `defaults/main.yml` + - Default: undefined + - Description: Set a list of ciphers to override the one defined in `vars/main.yml`, or set it to false to skip this configuration. - Type: list - Required: no - `ssh_client_alive_count` @@ -244,8 +244,8 @@ For more information, see [this issue](https://github.com/dev-sec/ansible-collec - Type: list - Required: no - `ssh_host_key_files` - - Default: `` - - Description: Host keys for sshd. If empty ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key'] will be used, as far as supported by the installed sshd version. + - Default: undefined + - Description: Host keys for sshd. If undefined ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key'] will be used, as far as supported by the installed sshd version, and a new `ssh_host_rsa_key` may be generated according to `ssh_host_rsa_key_size`. Set it to false to skip this configuration. - Type: list - Required: no - `ssh_host_rsa_key_size` @@ -259,8 +259,8 @@ For more information, see [this issue](https://github.com/dev-sec/ansible-collec - Type: bool - Required: no - `ssh_kex` - - Default: `` - - Description: Change this list to overwrite kexs. Defaults found in `defaults/main.yml` + - Default: undefined + - Description: Set a list of Key Exchange Algorithms to override the one defined in `vars/main.yml`, or set it to false to skip this configuration. - Type: list - Required: no - `ssh_listen_to` @@ -274,8 +274,8 @@ For more information, see [this issue](https://github.com/dev-sec/ansible-collec - Type: str - Required: no - `ssh_macs` - - Default: `` - - Description: Change this list to overwrite macs. Defaults found in `defaults/main.yml` + - Default: undefined + - Description: Set a list of macs to override the one defined in `vars/main.yml`, or set it to false to skip this configuration. - Type: list - Required: no - `ssh_max_auth_retries` diff --git a/roles/ssh_hardening/defaults/main.yml b/roles/ssh_hardening/defaults/main.yml index d70b8da6..d96f8c00 100644 --- a/roles/ssh_hardening/defaults/main.yml +++ b/roles/ssh_hardening/defaults/main.yml @@ -40,9 +40,6 @@ ssh_client_port: "22" # ssh # Default is empty, but should be configured for security reasons! ssh_listen_to: [0.0.0.0] # sshd -# Host keys to look for when starting sshd. -ssh_host_key_files: [] # sshd - # Host RSA key size in bits ssh_host_rsa_key_size: 4096 # sshd @@ -206,9 +203,6 @@ ssh_max_startups: 10:30:60 # sshd ssh_ps59: sandbox -ssh_macs: [] -ssh_ciphers: [] -ssh_kex: [] # directory where to store ssh_password policy ssh_custom_selinux_dir: /etc/selinux/local-policies diff --git a/roles/ssh_hardening/meta/argument_specs.yml b/roles/ssh_hardening/meta/argument_specs.yml index ab769bfd..a5885c19 100644 --- a/roles/ssh_hardening/meta/argument_specs.yml +++ b/roles/ssh_hardening/meta/argument_specs.yml @@ -29,7 +29,7 @@ argument_specs: Default is all IPv4 addresses, but should be configured to specific addresses for security reasons ssh_host_key_files: - default: [] + default: undefined type: list description: Host keys for sshd. If empty ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key'] will be used, as far as supported by the @@ -318,15 +318,15 @@ argument_specs: description: Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. ssh_macs: - default: [] + default: undefined type: list description: Change this list to overwrite macs. Defaults found in `defaults/main.yml` ssh_kex: - default: [] + default: undefined type: list description: Change this list to overwrite kexs. Defaults found in `defaults/main.yml` ssh_ciphers: - default: [] + default: undefined type: list description: Change this list to overwrite ciphers. Defaults found in `defaults/main.yml` ssh_custom_options: diff --git a/roles/ssh_hardening/tasks/hardening.yml b/roles/ssh_hardening/tasks/hardening.yml index 3b09c5c3..fdc6e094 100644 --- a/roles/ssh_hardening/tasks/hardening.yml +++ b/roles/ssh_hardening/tasks/hardening.yml @@ -39,19 +39,22 @@ ansible.builtin.include_tasks: crypto_hostkeys.yml when: - ssh_server_hardening | bool - - not ssh_host_key_files + - ssh_host_key_files is undefined - name: Set default for ssh_macs if not supplied ansible.builtin.include_tasks: crypto_macs.yml - when: not ssh_macs + when: + - ssh_macs is undefined - name: Set default for ssh_ciphers if not supplied ansible.builtin.include_tasks: crypto_ciphers.yml - when: not ssh_ciphers + when: + - ssh_ciphers is undefined - name: Set default for ssh_kex if not supplied ansible.builtin.include_tasks: crypto_kex.yml - when: not ssh_kex + when: + - ssh_kex is undefined - name: Create revoked_keys and set permissions to root/600 ansible.builtin.template: diff --git a/roles/ssh_hardening/templates/opensshd.conf.j2 b/roles/ssh_hardening/templates/opensshd.conf.j2 index 4ac0e713..4f2a9f50 100644 --- a/roles/ssh_hardening/templates/opensshd.conf.j2 +++ b/roles/ssh_hardening/templates/opensshd.conf.j2 @@ -34,9 +34,11 @@ ListenAddress {{ address }} {% endfor %} # HostKeys are listed here. -{% for key in ssh_host_key_files %} +{% if ssh_host_key_files is defined and ssh_host_key_files -%} +{% for key in ssh_host_key_files %} HostKey {{ key }} -{% endfor %} +{% endfor %} +{% endif %} # HostCertificates are listed here. {% for certificate in ssh_host_certificates -%} @@ -73,14 +75,22 @@ LogLevel {{ sshd_log_level }} # -- see: (http://net-ssh.github.com/net-ssh/classes/Net/SSH/Transport/CipherFactory.html) # {# This outputs 'Ciphers ' if ssh_ciphers is defined or '#Ciphers' if ssh_ciphers is undefined -#} -{{ 'Ciphers ' ~ ssh_ciphers|join(',') if ssh_ciphers else 'Ciphers'|comment }} +{% if ssh_ciphers is defined and ssh_ciphers -%} +{{ 'Ciphers ' ~ ssh_ciphers|join(',') }} +{% else -%} +{{ 'Ciphers'|comment }} +{% endif %} # **Hash algorithms** -- SHA-1 is formally deprecated by NIST in 2011 because of security issues. # Weak HMAC is sometimes required if older package versions are used # eg Ruby's Net::SSH at around 2.2.* doesn't support sha2 for hmac, so this will have to be set true in this case. # {# This outputs 'MACs ' if ssh_macs is defined or '#MACs' if ssh_macs is undefined -#} -{{ 'MACs ' ~ ssh_macs|join(',') if ssh_macs else 'MACs'|comment }} +{% if ssh_macs is defined and ssh_macs -%} +{{ 'MACs ' ~ ssh_macs|join(',') }} +{% else -%} +{{ 'MACs'|comment }} +{% endif %} {% if sshd_version is version('5.9', '<') %} # Alternative setting, if OpenSSH version is below v5.9 @@ -92,8 +102,12 @@ LogLevel {{ sshd_log_level }} # eg ruby's Net::SSH at around 2.2.* doesn't support sha2 for kex, so this will have to be set true in this case. # based on: https://bettercrypto.org/static/applied-crypto-hardening.pdf # -{# This outputs 'KexAlgorithms ' if ssh_kex is defined or '#KexAlgorithms' if ssh_kex is undefined #} -{{ 'KexAlgorithms ' ~ ssh_kex|join(',') if ssh_kex else 'KexAlgorithms'|comment }} +{# This outputs 'KexAlgorithms ' if ssh_kex is defined and ssh_kex or '#KexAlgorithms' if ssh_kex is undefined #} +{% if ssh_kex is defined and ssh_kex -%} +{{ 'KexAlgorithms ' ~ ssh_kex|join(',') }} +{% else -%} +{{ 'KexAlgorithms'|comment }} +{% endif %} # Authentication # --------------