Chapter 23. Configuring secure communication by using the ssh and sshd RHEL system roles
As an administrator, you can use the sshd
system role to configure SSH servers and the ssh
system role to configure SSH clients consistently on any number of RHEL systems at the same time using the Ansible Core package.
23.1. Variables of the ssh
Server system role
In an sshd
system role playbook, you can define the parameters for the SSH configuration file according to your preferences and limitations.
If you do not configure these variables, the system role produces an sshd_config
file that matches the RHEL defaults.
In all cases, Booleans correctly render as yes
and no
in sshd
configuration. You can define multi-line configuration items using lists. For example:
sshd_ListenAddress: - 0.0.0.0 - '::'
renders as:
ListenAddress 0.0.0.0 ListenAddress ::
Variables for the sshd
system role
sshd_enable
-
If set to
false
, the role is completely disabled. Defaults totrue
. sshd_skip_defaults
-
If set to
true
, the system role does not apply default values. Instead, you specify the complete set of configuration defaults by using either thesshd
dictionary orsshd_<OptionName>
variables. Defaults tofalse
. sshd_manage_service
-
If set to
false
, the service is not managed, which means it is not enabled on boot and does not start or reload. Defaults totrue
except when running inside a container or AIX, because the Ansible service module does not currently supportenabled
for AIX. sshd_allow_reload
-
If set to
false
,sshd
does not reload after a change of configuration. This can help with troubleshooting. To apply the changed configuration, reloadsshd
manually. Defaults to the same value assshd_manage_service
except on AIX, wheresshd_manage_service
defaults tofalse
butsshd_allow_reload
defaults totrue
. sshd_install_service
If set to
true
, the role installs service files for thesshd
service. This overrides files provided in the operating system. Do not set totrue
unless you are configuring a second instance and you also change thesshd_service
variable. Defaults tofalse
.The role uses the files pointed by the following variables as templates:
sshd_service_template_service (default: templates/sshd.service.j2) sshd_service_template_at_service (default: templates/sshd@.service.j2) sshd_service_template_socket (default: templates/sshd.socket.j2)
sshd_service
-
This variable changes the
sshd
service name, which is useful for configuring a secondsshd
service instance. sshd
A dictionary that contains configuration. For example:
sshd: Compression: yes ListenAddress: - 0.0.0.0
The
sshd_config(5)
lists all options for thesshd
dictionary.sshd_<OptionName>
You can define options by using simple variables consisting of the
sshd_
prefix and the option name instead of a dictionary. The simple variables override values in thesshd
dictionary. For example:sshd_Compression: no
The
sshd_config(5)
lists all options forsshd
.sshd_manage_firewall
Set this variable to
true
if you are using a different port than the default port22
. When set totrue
, thesshd
role uses thefirewall
role to automatically manage port access.NoteThe
sshd_manage_firewall
variable can only add ports. It cannot remove ports. To remove ports, use thefirewall
system role directly. For more information about managing ports by using thefirewall
system role, see Configuring ports by using system roles.sshd_manage_selinux
Set this variable to
true
if you are using a different port than the default port22
. When set totrue
, thesshd
role uses theselinux
role to automatically manage port access.NoteThe
sshd_manage_selinux
variable can only add ports. It cannot remove ports. To remove ports, use theselinux
system role directly.sshd_match
andsshd_match_1
tosshd_match_9
-
A list of dictionaries or just a dictionary for a Match section. Note that these variables do not override match blocks as defined in the
sshd
dictionary. All of the sources will be reflected in the resulting configuration file. sshd_backup
-
When set to
false
, the originalsshd_config
file is not backed up. Default istrue
.
Secondary variables for the sshd
system role
You can use these variables to override the defaults that correspond to each supported platform.
sshd_packages
- You can override the default list of installed packages using this variable.
sshd_config_owner
,sshd_config_group
, andsshd_config_mode
-
You can set the ownership and permissions for the
openssh
configuration file that this role produces using these variables. sshd_config_file
-
The path where this role saves the
openssh
server configuration produced. sshd_config_namespace
The default value of this variable is null, which means that the role defines the entire content of the configuration file including system defaults. Alternatively, 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
variable is ignored and no system defaults are used in this case.When this variable is set, the role places the configuration that you specify to configuration snippets in an existing configuration file under the given namespace. If your scenario requires applying the role several times, you need to select a different namespace for each application.
NoteLimitations of the
openssh
configuration file still apply. For example, only the first option specified in a configuration file is effective for most of the configuration options.Technically, the role places snippets in "Match all" blocks, unless they contain other match blocks, to ensure they are applied regardless of the previous match blocks in the existing configuration file. This allows configuring any non-conflicting options from different roles invocations.
sshd_binary
-
The path to the
sshd
executable ofopenssh
. sshd_service
-
The name of the
sshd
service. By default, this variable contains the name of thesshd
service that the target platform uses. You can also use it to set the name of the customsshd
service when the role uses thesshd_install_service
variable. sshd_verify_hostkeys
-
Defaults to
auto
. When set toauto
, this lists all host keys that are present in the produced configuration file, and generates any paths that are not present. Additionally, permissions and file owners are set to default values. This is useful if the role is used in the deployment stage to verify the service is able to start on the first attempt. To disable this check, set this variable to an empty list[]
. sshd_hostkey_owner
,sshd_hostkey_group
,sshd_hostkey_mode
-
Use these variables to set the ownership and permissions for the host keys from
sshd_verify_hostkeys
. sshd_sysconfig
-
On systems based on RHEL 8 and earlier versions, this variable configures additional details of the
sshd
service. If set totrue
, this role manages also the/etc/sysconfig/sshd
configuration file based on thesshd_sysconfig_override_crypto_policy
andsshd_sysconfig_use_strong_rng
variables. Defaults tofalse
. sshd_sysconfig_override_crypto_policy
In RHEL 8, setting it to
true
allows overriding the system-wide cryptographic policy by using the following configuration options in thesshd
dictionary or in thesshd_<OptionName>
format:-
Ciphers
-
MACs
-
GSSAPIKexAlgorithms
-
GSSAPIKeyExchange
(FIPS-only) -
KexAlgorithms
-
HostKeyAlgorithms
-
PubkeyAcceptedKeyTypes
CASignatureAlgorithms
Defaults to
false
.In RHEL 9, this variable has no effect. Instead, you can override system-wide cryptographic policies by using the following configuration options in the
sshd
dictionary or in thesshd_<OptionName>
format:-
Ciphers
-
MACs
-
GSSAPIKexAlgorithms
-
GSSAPIKeyExchange
(FIPS-only) -
KexAlgorithms
-
HostKeyAlgorithms
-
PubkeyAcceptedAlgorithms
-
HostbasedAcceptedAlgorithms
-
CASignatureAlgorithms
RequiredRSASize
If you enter these options into custom configuration files in the drop-in directory defined in the
sshd_config_file
variable, use a file name that lexicographically precedes the/etc/ssh/sshd_config.d/50-redhat.conf
file that includes the cryptographic policies.
-
sshd_sysconfig_use_strong_rng
-
On systems based on RHEL 8 and earlier versions, this variable can force
sshd
to reseed theopenssl
random number generator with the number of bytes given as the argument. The default is0
, which disables this functionality. Do not turn this on if the system does not have a hardware random number generator.
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.sshd/README.md
file -
/usr/share/doc/rhel-system-roles/sshd/
directory
23.2. Configuring OpenSSH servers by using the sshd
system role
You can use the sshd
system role to configure multiple SSH servers by running an Ansible playbook.
You can use the sshd
system role with other system roles that change SSH and SSHD configuration, for example the Identity Management RHEL system roles. To prevent the configuration from being overwritten, make sure that the sshd
role uses namespaces (RHEL 8 and earlier versions) or a drop-in directory (RHEL 9).
Prerequisites
- You have prepared the control node and the managed nodes.
- You are logged in to the control node as a user who can run playbooks on the managed nodes.
-
The account you use to connect to the managed nodes has
sudo
permissions on them.
Procedure
Create a playbook file, for example
~/playbook.yml
, with the following content:--- - name: SSH server configuration hosts: managed-node-01.example.com tasks: - name: Configure sshd to prevent root and password login except from particular subnet ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd: PermitRootLogin: no PasswordAuthentication: no Match: - Condition: "Address 192.0.2.0/24" PermitRootLogin: yes PasswordAuthentication: yes
The playbook configures the managed node as an SSH server configured so that:
-
password and
root
user login is disabled -
password and
root
user login is enabled only from the subnet192.0.2.0/24
-
password and
Validate the playbook syntax:
$ ansible-playbook --syntax-check ~/playbook.yml
Note that this command only validates the syntax and does not protect against a wrong but valid configuration.
Run the playbook:
$ ansible-playbook ~/playbook.yml
Verification
Log in to the SSH server:
$ ssh <username>@<ssh_server>
Verify the contents of the
sshd_config
file on the SSH server:$ cat /etc/ssh/sshd_config.d/00-ansible_system_role.conf # # Ansible managed # PasswordAuthentication no PermitRootLogin no Match Address 192.0.2.0/24 PasswordAuthentication yes PermitRootLogin yes
Check that you can connect to the server as root from the
192.0.2.0/24
subnet:Determine your IP address:
$ hostname -I 192.0.2.1
If the IP address is within the
192.0.2.1
-192.0.2.254
range, you can connect to the server.Connect to the server as
root
:$ ssh root@<ssh_server>
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.sshd/README.md
file -
/usr/share/doc/rhel-system-roles/sshd/
directory
23.3. Using the sshd
system role for non-exclusive configuration
Normally, applying the sshd
system role overwrites the entire configuration. This may be problematic if you have previously adjusted the configuration, for example, with a different system role or playbook. To apply the sshd
system role for only selected configuration options while keeping other options in place, you can use the non-exclusive configuration.
You can apply a non-exclusive configuration:
- In RHEL 8 and earlier by using a configuration snippet.
-
In RHEL 9 and later by using files in a drop-in directory. The default configuration file is already placed in the drop-in directory as
/etc/ssh/sshd_config.d/00-ansible_system_role.conf
.
Prerequisites
- You have prepared the control node and the managed nodes.
- You are logged in to the control node as a user who can run playbooks on the managed nodes.
-
The account you use to connect to the managed nodes has
sudo
permissions on them.
Procedure
Create a playbook file, for example
~/playbook.yml
, with the following content:For managed nodes that run RHEL 8 or earlier:
--- - name: Non-exclusive sshd configuration hosts: managed-node-01.example.com tasks: - name: <Configure SSHD to accept some useful environment variables> ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_config_namespace: <my-application> sshd: # Environment variables to accept AcceptEnv: LANG LS_COLORS EDITOR
For managed nodes that run RHEL 9 or later:
- name: Non-exclusive sshd configuration hosts: managed-node-01.example.com tasks: - name: <Configure sshd to accept some useful environment variables> ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_config_file: /etc/ssh/sshd_config.d/<42-my-application>.conf sshd: # Environment variables to accept AcceptEnv: LANG LS_COLORS EDITOR
In the
sshd_config_file
variable, define the.conf
file into which thesshd
system role writes the configuration options. Use a two-digit prefix, for example42-
to specify the order in which the configuration files will be applied.
Validate the playbook syntax:
$ ansible-playbook --syntax-check ~/playbook.yml
Note that this command only validates the syntax and does not protect against a wrong but valid configuration.
Run the playbook:
$ ansible-playbook ~/playbook.yml
Verification
Verify the configuration on the SSH server:
For managed nodes that run RHEL 8 or earlier:
# cat /etc/ssh/sshd_config.d/42-my-application.conf # Ansible managed # AcceptEnv LANG LS_COLORS EDITOR
For managed nodes that run RHEL 9 or later:
# cat /etc/ssh/sshd_config ... # BEGIN sshd system role managed block: namespace <my-application> Match all AcceptEnv LANG LS_COLORS EDITOR # END sshd system role managed block: namespace <my-application>
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.sshd/README.md
file -
/usr/share/doc/rhel-system-roles/sshd/
directory
23.4. Overriding the system-wide cryptographic policy on an SSH server by using system roles
You can override the system-wide cryptographic policy on an SSH server by using the sshd
RHEL system role.
Prerequisites
- You have prepared the control node and the managed nodes.
- You are logged in to the control node as a user who can run playbooks on the managed nodes.
-
The account you use to connect to the managed nodes has
sudo
permissions on them.
Procedure
Create a playbook file, for example
~/playbook.yml
, with the following content:- name: Overriding the system-wide cryptographic policy hosts: managed-node-01.example.com roles: - rhel_system_roles.sshd vars: sshd_sysconfig: true sshd_sysconfig_override_crypto_policy: true sshd_KexAlgorithms: ecdh-sha2-nistp521 sshd_Ciphers: aes256-ctr sshd_MACs: hmac-sha2-512-etm@openssh.com sshd_HostKeyAlgorithms: rsa-sha2-512,rsa-sha2-256
-
sshd_KexAlgorithms
:: You can choose key exchange algorithms, for example,ecdh-sha2-nistp256
,ecdh-sha2-nistp384
,ecdh-sha2-nistp521
,diffie-hellman-group14-sha1
, ordiffie-hellman-group-exchange-sha256
. -
sshd_Ciphers
:: You can choose ciphers, for example,aes128-ctr
,aes192-ctr
, oraes256-ctr
. -
sshd_MACs
:: You can choose MACs, for example,hmac-sha2-256
,hmac-sha2-512
, orhmac-sha1
. -
sshd_HostKeyAlgorithms
:: You can choose a public key algorithm, for example,ecdsa-sha2-nistp256
,ecdsa-sha2-nistp384
,ecdsa-sha2-nistp521
,ssh-rsa
, orssh-dss
.
On RHEL 9 managed nodes, the system role writes the configuration into the
/etc/ssh/sshd_config.d/00-ansible_system_role.conf
file, where cryptographic options are applied automatically. You can change the file by using thesshd_config_file
variable. However, to ensure the configuration is effective, use a file name that lexicographicaly preceeds the/etc/ssh/sshd_config.d/50-redhat.conf
file, which includes the configured crypto policies.On RHEL 8 managed nodes, you must enable override by setting the
sshd_sysconfig_override_crypto_policy
andsshd_sysconfig
variables totrue
.-
Validate the playbook syntax:
$ ansible-playbook --syntax-check ~/playbook.yml
Note that this command only validates the syntax and does not protect against a wrong but valid configuration.
Run the playbook:
$ ansible-playbook ~/playbook.yml
Verification
You can verify the success of the procedure by using the verbose SSH connection and check the defined variables in the following output:
$ ssh -vvv <ssh_server> ... debug2: peer server KEXINIT proposal debug2: KEX algorithms: ecdh-sha2-nistp521 debug2: host key algorithms: rsa-sha2-512,rsa-sha2-256 debug2: ciphers ctos: aes256-ctr debug2: ciphers stoc: aes256-ctr debug2: MACs ctos: hmac-sha2-512-etm@openssh.com debug2: MACs stoc: hmac-sha2-512-etm@openssh.com ...
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.sshd/README.md
file -
/usr/share/doc/rhel-system-roles/sshd/
directory
23.5. Variables of the ssh
system role
In an ssh
system role playbook, you can define the parameters for the client SSH configuration file according to your preferences and limitations.
If you do not configure these variables, the system role produces a global ssh_config
file that matches the RHEL defaults.
In all cases, booleans correctly render as yes
or no
in ssh
configuration. You can define multi-line configuration items using lists. For example:
LocalForward: - 22 localhost:2222 - 403 localhost:4003
renders as:
LocalForward 22 localhost:2222 LocalForward 403 localhost:4003
The configuration options are case sensitive.
Variables for the ssh
system role
ssh_user
-
You can define an existing user name for which the system role modifies user-specific configuration. The user-specific configuration is saved in
~/.ssh/config
of the given user. The default value is null, which modifies global configuration for all users. ssh_skip_defaults
-
Defaults to
auto
. If set toauto
, the system role writes the system-wide configuration file/etc/ssh/ssh_config
and keeps the RHEL defaults defined there. Creating a drop-in configuration file, for example by defining thessh_drop_in_name
variable, automatically disables thessh_skip_defaults
variable. ssh_drop_in_name
Defines the name for the drop-in configuration file, which is placed in the system-wide drop-in directory. The name is used in the template
/etc/ssh/ssh_config.d/{ssh_drop_in_name}.conf
to reference the configuration file to be modified. If the system does not support drop-in directory, the default value is null. If the system supports drop-in directories, the default value is00-ansible
.WarningIf the system does not support drop-in directories, setting this option will make the play fail.
The suggested format is
NN-name
, whereNN
is a two-digit number used for ordering the configuration files andname
is any descriptive name for the content or the owner of the file.ssh
- A dict that contains configuration options and their respective values.
ssh_OptionName
-
You can define options by using simple variables consisting of the
ssh_
prefix and the option name instead of a dict. The simple variables override values in thessh
dict. ssh_additional_packages
-
This role automatically installs the
openssh
andopenssh-clients
packages, which are needed for the most common use cases. If you need to install additional packages, for example,openssh-keysign
for host-based authentication, you can specify them in this variable. ssh_config_file
The path to which the role saves the configuration file produced. Default value:
-
If the system has a drop-in directory, the default value is defined by the template
/etc/ssh/ssh_config.d/{ssh_drop_in_name}.conf
. -
If the system does not have a drop-in directory, the default value is
/etc/ssh/ssh_config
. -
if the
ssh_user
variable is defined, the default value is~/.ssh/config
.
-
If the system has a drop-in directory, the default value is defined by the template
ssh_config_owner
,ssh_config_group
,ssh_config_mode
-
The owner, group and modes of the created configuration file. By default, the owner of the file is
root:root
, and the mode is0644
. Ifssh_user
is defined, the mode is0600
, and the owner and group are derived from the user name specified in thessh_user
variable.
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.ssh/README.md
file -
/usr/share/doc/rhel-system-roles/ssh/
directory
23.6. Configuring OpenSSH clients by using the ssh
system role
You can use the ssh
system role to configure multiple SSH clients by running an Ansible playbook.
You can use the ssh
system role with other system roles that change SSH and SSHD configuration, for example the Identity Management RHEL system roles. To prevent the configuration from being overwritten, make sure that the ssh
role uses a drop-in directory (default in RHEL 8 and later).
Prerequisites
- You have prepared the control node and the managed nodes.
- You are logged in to the control node as a user who can run playbooks on the managed nodes.
-
The account you use to connect to the managed nodes has
sudo
permissions on them.
Procedure
Create a playbook file, for example
~/playbook.yml
, with the following content:--- - name: SSH client configuration hosts: managed-node-01.example.com tasks: - name: "Configure ssh clients" ansible.builtin.include_role: name: rhel-system-roles.ssh vars: ssh_user: root ssh: Compression: true GSSAPIAuthentication: no ControlMaster: auto ControlPath: ~/.ssh/.cm%C Host: - Condition: example Hostname: server.example.com User: user1 ssh_ForwardX11: no
This playbook configures the
root
user’s SSH client preferences on the managed nodes with the following configurations:- Compression is enabled.
-
ControlMaster multiplexing is set to
auto
. -
The
example
alias for connecting to theserver.example.com
host isuser1
. -
The
example
host alias is created, which represents a connection to theserver.example.com
host the with theuser1
user name. - X11 forwarding is disabled.
Validate the playbook syntax:
$ ansible-playbook --syntax-check ~/playbook.yml
Note that this command only validates the syntax and does not protect against a wrong but valid configuration.
Run the playbook:
$ ansible-playbook ~/playbook.yml
Verification
Verify that the managed node has the correct configuration by displaying the SSH configuration file:
# cat ~root/.ssh/config # Ansible managed Compression yes ControlMaster auto ControlPath ~/.ssh/.cm%C ForwardX11 no GSSAPIAuthentication no Host example Hostname example.com User user1
Additional resources
-
/usr/share/ansible/roles/rhel-system-roles.ssh/README.md
file -
/usr/share/doc/rhel-system-roles/ssh/
directory