fix: rename var sshd -> sshd_config and debug output (#299)

This commit is contained in:
Matt Willsher 2024-10-24 17:59:04 +01:00 committed by GitHub
parent 3331fa7b35
commit da3e33ec46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 203 additions and 66 deletions

View file

@ -4,8 +4,8 @@ exclude_paths:
- .tox/
- .markdownlint.yaml
skip_list:
- var-naming[no-role-prefix]
- meta-runtime[unsupported-version]
- experimental
mock_roles:
- willshersystems.sshd.ansible-sshd
mock_modules:

View file

@ -130,17 +130,20 @@ NOTE: `sshd_manage_selinux` is limited to *adding* policy. It cannot be used
for *removing* policy. If you want to remove ports, you will need to use the
selinux system role directly.
#### sshd
#### sshd_config
A dict containing configuration. e.g.
```yaml
sshd:
sshd_config:
Compression: delayed
ListenAddress:
- 0.0.0.0
```
*Note*: This variable was previous called `sshd`. `sshd` is can still be used
but is deprecated and will be removed in a future release.
#### sshd_`<OptionName>`
Simple variables can be used rather than a dict. Simple values override dict
@ -344,7 +347,7 @@ Use these variables to set the ownership and permissions for the Authorized Prin
The SSH server needs this information stored in files so in addition to the above variables, respective configuration options `TrustedUserCAKeys` (mandatory) and `AuthorizedPrincipalsFile` (optional) need to be present the `sshd` dictionary when invoking the role. For example:
```yaml
sshd:
sshd_config:
TrustedUserCAKeys: /etc/ssh/path-to-trusted-user-ca-keys/trusted-user-ca-keys.pub
AuthorizedPrincipalsFile: "/etc/ssh/path-to-auth-principals/auth_principals/%u"
```
@ -370,7 +373,7 @@ provides. Running it will likely break your SSH access to the server!
- hosts: all
vars:
sshd_skip_defaults: true
sshd:
sshd_config:
Compression: true
ListenAddress:
- "0.0.0.0"
@ -413,7 +416,7 @@ for example:
name: willshersystems.sshd
vars:
sshd_skip_defaults: true
sshd:
sshd_config:
Compression: true
ListenAddress:
- "0.0.0.0"
@ -440,7 +443,7 @@ option:
name: willshersystems.sshd
vars:
sshd_config_namespace: accept-env
sshd:
sshd_config:
# there are some handy environment variables to accept
AcceptEnv:
LANG

View file

@ -37,9 +37,6 @@ sshd_sysconfig_override_crypto_policy: false
# generator
sshd_sysconfig_use_strong_rng: 0
# Empty dicts to avoid errors
sshd: {}
# The path to sshd_config file. This is useful when creating an included
# configuration file snippet or configuring second sshd service
sshd_config_file: "{{ __sshd_config_file }}"

View file

@ -7,7 +7,7 @@
name: ansible-sshd
vars:
sshd_config_namespace: accept-env
sshd:
sshd_config:
# there are some handy environment variables to accept
AcceptEnv:
LANG

View file

@ -6,7 +6,7 @@
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
sshd_config:
# root login and password login is enabled only from a particular subnet
PermitRootLogin: false
PasswordAuthentication: false

View file

@ -6,7 +6,7 @@
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
sshd_config:
# Disable password authentication, use SSH Certificates and configure authorized principals
PasswordAuthentication: false
TrustedUserCAKeys: /etc/ssh/trusted-user-ca-keys.pub

View file

@ -21,8 +21,8 @@
{% set value = undefined %}
{% if override is defined %}
{% set value = override %}
{% elif sshd[key] is defined %}
{% set value = sshd[key] %}
{% elif __sshd_config[key] is defined %}
{% set value = __sshd_config[key] %}
{% elif sshd_main_config_file is not none
and sshd_config_file | dirname == sshd_main_config_file ~ '.d' %}
{# Do not use the defaults from main file to avoid recursion #}

View file

@ -1,5 +1,5 @@
{% if sshd['Match'] is defined %}
{{ match_iterate_block(sshd['Match']) -}}
{% if __sshd_config['Match'] is defined %}
{{ match_iterate_block(__sshd_config['Match']) -}}
{% endif %}
{% if sshd_match is defined %}
{{ match_iterate_block(sshd_match) -}}

View file

@ -6,7 +6,7 @@
{% if sshd_TrustedUserCAKeys is defined %}
{{ sshd_TrustedUserCAKeys | to_json }}
{% else %}
{{ sshd['TrustedUserCAKeys'] | to_json }}
{{ __sshd_config['TrustedUserCAKeys'] | to_json }}
{% endif %}
block:
- name: Create Trusted user CA Keys directory
@ -32,7 +32,7 @@
{% if sshd_AuthorizedPrincipalsFile is defined %}
{{ sshd_AuthorizedPrincipalsFile | to_json }}
{% else %}
{{ sshd['AuthorizedPrincipalsFile'] | to_json }}
{{ __sshd_config['AuthorizedPrincipalsFile'] | to_json }}
{% endif %}
when: sshd_principals != {}
block:

View file

@ -6,8 +6,8 @@
__sshd_ports_from_config_tmp: >-
{% if sshd_Port is defined %}
{{ sshd_Port | to_json }}
{% elif sshd['Port'] is defined %}
{{ sshd['Port'] | to_json }}
{% elif __sshd_config['Port'] is defined %}
{{ __sshd_config['Port'] | to_json }}
{% elif __sshd_defaults['Port'] is defined and not sshd_skip_defaults %}
{{ __sshd_defaults['Port'] | to_json }}
{% else %}

View file

@ -5,7 +5,7 @@
ansible.builtin.include_role:
name: fedora.linux_system_roles.firewall
vars:
firewall:
firewall: # noqa: var-naming[no-role-prefix]
- service: ssh
state: enabled
when:
@ -15,11 +15,11 @@
ansible.builtin.include_role:
name: fedora.linux_system_roles.firewall
vars:
firewall:
firewall: # noqa: var-naming[no-role-prefix]
- port: "{{ sshd_item }}/tcp"
state: enabled
loop: "{{ __sshd_ports_from_config | from_json | d([]) }}"
loop_control:
loop_var: sshd_item # avoid conflicts with the firewall loops
loop_var: sshd_item # avoid conflicts with the firewall loops
when:
- __sshd_ports_from_config | from_json != [22]

View file

@ -33,8 +33,8 @@
- __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
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
@ -44,8 +44,8 @@
__sshd_hostkeys_from_config: >-
{% if sshd_HostKey is defined %}
{{ sshd_HostKey | to_json }}
{% elif sshd['HostKey'] is defined %}
{{ sshd['HostKey'] | to_json }}
{% elif __sshd_config['HostKey'] is defined %}
{{ __sshd_config['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 }}

View file

@ -1,4 +1,11 @@
---
- name: Print that the sshd variable is deprecated
when: sshd is defined
ansible.builtin.debug:
msg: >-
The sshd variable is deprecated and will be removed
in a future version. Edit your playbook to use
the sshd_config variable instead.
- name: Invoke the role, if enabled
ansible.builtin.include_tasks: sshd.yml

View file

@ -23,8 +23,8 @@
{% set value = undefined %}
{% if override is defined %}
{% set value = override %}
{% elif sshd[key] is defined %}
{% set value = sshd[key] %}
{% elif __sshd_config[key] is defined %}
{% set value = __sshd_config[key] %}
{% elif sshd_main_config_file is not none
and sshd_config_file | dirname == sshd_main_config_file ~ '.d' %}
{# Do not use the defaults from main file to avoid recursion #}
@ -250,8 +250,8 @@ Match {{ match["Condition"] }}
{{ body_option("X11Forwarding",sshd_X11Forwarding) -}}
{{ body_option("X11UseLocalhost",sshd_X11UseLocalhost) -}}
{{ body_option("XAuthLocation",sshd_XAuthLocation) -}}
{% if sshd['Match'] is defined %}
{{ match_iterate_block(sshd['Match']) -}}
{% if __sshd_config['Match'] is defined %}
{{ match_iterate_block(__sshd_config['Match']) -}}
{% endif %}
{% if sshd_match is defined %}
{{ match_iterate_block(sshd_match) -}}

View file

@ -21,8 +21,8 @@
{% set value = undefined %}
{% if override is defined %}
{% set value = override %}
{% elif sshd[key] is defined %}
{% set value = sshd[key] %}
{% elif __sshd_config[key] is defined %}
{% set value = __sshd_config[key] %}
{% elif sshd_main_config_file is not none
and sshd_config_file | dirname == sshd_main_config_file ~ '.d' %}
{# Do not use the defaults from main file to avoid recursion #}
@ -248,8 +248,8 @@ Match {{ match["Condition"] }}
{{ body_option("X11Forwarding",sshd_X11Forwarding) -}}
{{ body_option("X11UseLocalhost",sshd_X11UseLocalhost) -}}
{{ body_option("XAuthLocation",sshd_XAuthLocation) -}}
{% if sshd['Match'] is defined %}
{{ match_iterate_block(sshd['Match']) -}}
{% if __sshd_config['Match'] is defined %}
{{ match_iterate_block(__sshd_config['Match']) -}}
{% endif %}
{% if sshd_match is defined %}
{{ match_iterate_block(sshd_match) -}}

View file

@ -5,6 +5,13 @@
when:
- ansible_facts['distribution'] == 'Debian'
- name: Ensure unminimize package is installed
ansible.builtin.apt:
pkg:
- unminimize
when:
- ansible_facts['distribution'] == 'Ubuntu' and ansible_facts['distribution_major_version'] | int >= 24
- name: Determine if system is ostree and set flag
when: not __sshd_is_ostree is defined
block:

View file

@ -120,7 +120,7 @@
# The hostkeys are not valid either so do not validate them
sshd_verify_hostkeys: []
sshd_config_file: /tmp/sshd_config
sshd:
sshd_config:
"{{ sshd_c }}"
when: not sshd_skip_test

View file

@ -33,7 +33,7 @@
sshd_config_owner: "nobody"
sshd_config_group: "nobody"
sshd_config_mode: "660"
sshd:
sshd_config:
AcceptEnv: LANG
Banner: /etc/issue
Ciphers: aes256-ctr
@ -46,7 +46,7 @@
# just anything -- will not get processed by sshd
sshd_config_file: /etc/ssh/sshd_config_custom_second
sshd_skip_defaults: true
sshd:
sshd_config:
Banner: /etc/issue2
Ciphers: aes128-ctr
sshd_MaxStartups: 100 # noqa var-naming
@ -56,7 +56,7 @@
name: ansible-sshd
vars:
sshd_config_file: /etc/ssh/sshd_config
sshd:
sshd_config:
Banner: /etc/issue
Ciphers: aes192-ctr
HostKey:

View file

@ -35,7 +35,7 @@
sshd_config_owner: "nobody"
sshd_config_group: "nobody"
sshd_config_mode: "660"
sshd:
sshd_config:
AcceptEnv: LANG
Banner: /etc/issue
Ciphers: aes256-ctr
@ -50,7 +50,7 @@
# just anything -- will not get processed by sshd
sshd_config_file: /etc/ssh/sshd_config_custom_second
sshd_skip_defaults: true
sshd:
sshd_config:
Banner: /etc/issue2
Ciphers: aes128-ctr
sshd_MaxStartups: 100 # noqa var-naming
@ -62,7 +62,7 @@
- ansible-sshd
vars:
sshd_config_file: /etc/ssh/sshd_config
sshd:
sshd_config:
Banner: /etc/issue
Ciphers: aes192-ctr
HostKey:

View file

@ -25,7 +25,7 @@
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
sshd_config:
PasswordAuthentication: false
TrustedUserCAKeys: /etc/ssh/ca-keys/trusted-user-ca-keys.pub
AuthorizedPrincipalsFile: "/etc/ssh/auth_principals/%u"

View file

@ -16,7 +16,7 @@
vars:
sshd_config_file: /etc/ssh/sshd_config
sshd_config_namespace: nm1
sshd:
sshd_config:
PasswordAuthentication: true
PermitRootLogin: true
Match:
@ -29,7 +29,7 @@
vars:
sshd_config_file: /etc/ssh/sshd_config
sshd_config_namespace: nm2
sshd:
sshd_config:
PasswordAuthentication: false
PermitRootLogin: false
Match:

View file

@ -0,0 +1,122 @@
---
- name: Test deprecated sshd variable via include_role using some common options
hosts: all
vars:
__sshd_test_backup_files:
- /etc/ssh/sshd_config
- /etc/ssh/sshd_config.d/00-ansible_system_role.conf
tasks:
- name: "Backup configuration files"
ansible.builtin.include_tasks: tasks/backup.yml
- name: Configure sshd
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
AcceptEnv: LANG
Banner: /etc/issue
Ciphers: aes256-ctr
Subsystem: "sftp internal-sftp"
sshd_config_file: /etc/ssh/sshd_config
- name: Verify the options are correctly set
tags: tests::verify
block:
- name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: List effective configuration using sshd -T
ansible.builtin.shell: |
set -eu
if set -o | grep pipefail 2>&1 /dev/null ; then
set -o pipefail
fi
if test ! -f /etc/ssh/ssh_host_rsa_key; then
ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C '' -N ''
fi
sshd -T
register: runtime
changed_when: false
- name: Print current configuration file
ansible.builtin.slurp:
src: /etc/ssh/sshd_config
register: config
- name: Check the options are effective
# note, the options are in lower-case here
ansible.builtin.assert:
that:
- "'acceptenv LANG' in runtime.stdout"
- "'banner /etc/issue' in runtime.stdout"
- "'ciphers aes256-ctr' in runtime.stdout"
- "'subsystem sftp internal-sftp' in runtime.stdout"
- name: Check the options are in configuration file
ansible.builtin.assert:
that:
- "'AcceptEnv LANG' in config.content | b64decode"
- "'Banner /etc/issue' in config.content | b64decode"
- "'Ciphers aes256-ctr' in config.content | b64decode"
- "'Subsystem sftp internal-sftp' in config.content | b64decode"
- name: "Restore configuration files"
ansible.builtin.include_tasks: tasks/restore.yml
- name: Test deprecated sshd variable via role using some common options
hosts: all
vars:
__sshd_test_backup_files:
- /etc/ssh/sshd_config
- /etc/ssh/sshd_config.d/00-ansible_system_role.conf
pre_tasks:
- name: "Backup configuration files"
ansible.builtin.include_tasks: tasks/backup.yml
roles:
- role: ansible-sshd
vars:
sshd:
AcceptEnv: LANG
Banner: /etc/issue
Ciphers: aes256-ctr
Subsystem: "sftp internal-sftp"
sshd_config_file: /etc/ssh/sshd_config
tasks:
- name: Verify the options are correctly set
tags: tests::verify
block:
- name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: List effective configuration using sshd -T
ansible.builtin.command: sshd -T
register: runtime
changed_when: false
- name: Print current configuration file
ansible.builtin.slurp:
src: /etc/ssh/sshd_config
register: config
- name: Check the options are effective
# note, the options are in lower-case here
ansible.builtin.assert:
that:
- "'acceptenv LANG' in runtime.stdout"
- "'banner /etc/issue' in runtime.stdout"
- "'ciphers aes256-ctr' in runtime.stdout"
- "'subsystem sftp internal-sftp' in runtime.stdout"
- name: Check the options are in configuration file
ansible.builtin.assert:
that:
- "'AcceptEnv LANG' in config.content | b64decode"
- "'Banner /etc/issue' in config.content | b64decode"
- "'Ciphers aes256-ctr' in config.content | b64decode"
- "'Subsystem sftp internal-sftp' in config.content | b64decode"
- name: "Restore configuration files"
ansible.builtin.include_tasks: tasks/restore.yml

View file

@ -36,7 +36,7 @@
vars:
sshd_manage_selinux: "{{ __sshd_test_selinux }}"
sshd_manage_firewall: "{{ __sshd_test_firewall }}"
sshd:
sshd_config:
Port: 22
- name: Verify the options are correctly set
@ -65,7 +65,7 @@
vars:
sshd_manage_firewall: "{{ __sshd_test_firewall }}"
sshd_manage_selinux: "{{ __sshd_test_selinux }}"
sshd:
sshd_config:
Port: 222
- name: Verify the options are correctly set
@ -93,7 +93,7 @@
vars:
sshd_manage_firewall: "{{ __sshd_test_firewall }}"
sshd_manage_selinux: "{{ __sshd_test_selinux }}"
sshd:
sshd_config:
Port:
- 22
- 222
@ -124,7 +124,7 @@
ansible.builtin.include_role:
name: fedora.linux_system_roles.firewall
vars:
firewall:
firewall: # noqa: var-naming[no-role-prefix]
- port: "222/tcp"
state: disabled
when: __sshd_test_firewall
@ -133,7 +133,7 @@
ansible.builtin.include_role:
name: fedora.linux_system_roles.selinux
vars:
selinux:
selinux: # noqa: var-naming[no-role-prefix]
port: 222
proto: tcp
setype: ssh_port_t

View file

@ -35,7 +35,7 @@
sshd_hostkey_owner: "nobody"
sshd_hostkey_group: "nobody"
sshd_hostkey_mode: "0664"
sshd:
sshd_config:
HostKey:
- /tmp/ssh_host_rsa_key2

View file

@ -21,7 +21,7 @@
name: ansible-sshd
vars:
sshd_verify_hostkeys: []
sshd:
sshd_config:
HostKey:
- /tmp/missing_ssh_host_rsa_key
register: role_result

View file

@ -37,7 +37,7 @@
sshd_hostkey_owner: "nobody"
sshd_hostkey_group: "nobody"
sshd_hostkey_mode: "0664"
sshd:
sshd_config:
HostKey:
- /tmp/ssh_host_rsa_key2

View file

@ -24,7 +24,7 @@
name: ansible-sshd
vars:
sshd_config_file: /etc/ssh/sshd_config.d/00-ansible_system_role.conf
sshd:
sshd_config:
Banner: /etc/include-issue
Ciphers: aes192-ctr
when:
@ -114,7 +114,7 @@
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:
sshd_config:
Banner: /etc/include-issue
Ciphers: aes192-ctr

View file

@ -13,7 +13,7 @@
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
sshd_config:
PasswordAuthentication: true
PermitRootLogin: true
AcceptEnv:

View file

@ -16,7 +16,7 @@
# For Fedora containers, we need to make sure we have keys for sshd -T below
sshd_verify_hostkeys:
- /etc/ssh/ssh_host_rsa_key
sshd:
sshd_config:
Match:
Condition: "User xusers"
X11Forwarding: true

View file

@ -16,7 +16,7 @@
# For Fedora containers, we need to make sure we have keys for sshd -T below
sshd_verify_hostkeys:
- /etc/ssh/ssh_host_rsa_key
sshd:
sshd_config:
Match:
- Condition: "User xusers"
X11Forwarding: true

View file

@ -19,7 +19,7 @@
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
sshd_config:
Banner: /etc/issue
Ciphers: aes256-ctr
HostKey: /etc/ssh/ssh_host_rsa_key

View file

@ -34,7 +34,7 @@
sshd_config_file: /etc/ssh2/sshd_config
sshd_install_service: true
sshd_manage_selinux: true
sshd:
sshd_config:
Port: 2222
ForceCommand: echo "CONNECTED2"

View file

@ -40,7 +40,7 @@
sshd_config_file: /etc/ssh2/sshd_config.d/04-ansible.conf
sshd_install_service: true
sshd_manage_selinux: true
sshd:
sshd_config:
Port: 2222
ForceCommand: echo "CONNECTED2"

View file

@ -13,7 +13,7 @@
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
sshd_config:
AcceptEnv: LANG
Banner: /etc/issue
Ciphers: aes256-ctr

View file

@ -17,7 +17,7 @@
ansible.builtin.include_role:
name: ansible-sshd
vars:
sshd:
sshd_config:
# Unsupported in new versions, but ignored ?
Protocol: 1
UsePrivilegeSeparation: false

View file

@ -16,7 +16,7 @@
name: ansible-sshd
vars:
sshd_enable: false
sshd:
sshd_config:
AcceptEnv: XDG_*
Banner: /etc/issue
Ciphers: aes256-ctr,aes128-ctr

View file

@ -1,4 +1,5 @@
---
__sshd_config: "{{ sshd_config | default({}) or sshd | default({}) }}"
__sshd_config_file: "/etc/ssh/sshd_config"
__sshd_config_owner: "root"
__sshd_config_group: "root"
@ -54,7 +55,7 @@ __sshd_runtime_directory_mode: "0755"
# drop-in directory is used
__sshd_main_config_file: ~
__sshd_drop_in_dir_mode: '0755'
__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