Red Hat Training

A Red Hat training course is available for RHEL 8

Chapter 2. Configuring secure communication with the ssh 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 by using Red Hat Ansible Automation Platform.

2.1. ssh Server System Role variables

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 to true.
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 the sshd dictionary or sshd_<OptionName> variables. Defaults to false.
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 to true except when running inside a container or AIX, because the Ansible service module does not currently support enabled 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, reload sshd manually. Defaults to the same value as sshd_manage_service except on AIX, where sshd_manage_service defaults to false but sshd_allow_reload defaults to true.
sshd_install_service

If set to true, the role installs service files for the sshd service. This overrides files provided in the operating system. Do not set to true unless you are configuring a second instance and you also change the sshd_service variable. Defaults to false.

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 second sshd 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 the sshd 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 the sshd dictionary. For example:

sshd_Compression: no

The sshd_config(5) lists all options for sshd.

sshd_manage_firewall

Set this variable to true if you are using a different port than the default port 22. When set to true, the sshd role uses the firewall role to automatically manage port access.

Note

The sshd_manage_firewall variable can only add ports. It cannot remove ports. To remove ports, use the firewall System Role directly. For more information about managing ports by using the firewall 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 port 22. When set to true, the sshd role uses the selinux role to automatically manage port access.

Note

The sshd_manage_selinux variable can only add ports. It cannot remove ports. To remove ports, use the selinux System Role directly.

sshd_match and sshd_match_1 to sshd_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 original sshd_config file is not backed up. Default is true.

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, and sshd_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.

Note

Limitations 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 of openssh.
sshd_service
The name of the sshd service. By default, this variable contains the name of the sshd service that the target platform uses. You can also use it to set the name of the custom sshd service when the role uses the sshd_install_service variable.
sshd_verify_hostkeys
Defaults to auto. When set to auto, 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 to true, this role manages also the /etc/sysconfig/sshd configuration file based on the sshd_sysconfig_override_crypto_policy and sshd_sysconfig_use_strong_rng variables. Defaults to false.
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 the sshd dictionary or in the sshd_<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 the sshd_<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 the openssl random number generator with the number of bytes given as the argument. The default is 0, which disables this functionality. Do not turn this on if the system does not have a hardware random number generator.

2.2. Configuring OpenSSH servers using the sshd System Role

You can use the sshd System Role to configure multiple SSH servers by running an Ansible playbook.

Note

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.
  • The managed nodes or groups of managed nodes on which you want to run this playbook are listed in the Ansible inventory file.

Procedure

  1. Copy the example playbook for the sshd System Role:

    # cp /usr/share/doc/rhel-system-roles/sshd/example-root-login-playbook.yml ~/sshd-playbook.yml
  2. Open the copied playbook by using a text editor, for example:

    # vim ~/sshd-playbook.yml
    
    ---
    - hosts: all
      tasks:
      - name: Configure sshd to prevent root and password login except from particular subnet
        include_role:
          name: rhel-system-roles.sshd
        vars:
          sshd:
            # root login and password login is enabled only from a particular subnet
            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 subnet 192.0.2.0/24

    You can modify the variables according to your preferences. For more details, see sshd System Role variables.

  3. Validate the playbook syntax:

    # ansible-playbook --syntax-check ~/sshd-playbook.yml

    Note that this command only validates the syntax and does not protect against a wrong but valid configuration.

  4. Run the playbook:

    # ansible-playbook ~/sshd-playbook.yml
    
    ...
    
    PLAY RECAP
    **************************************************
    
    localhost : ok=12 changed=2 unreachable=0 failed=0
    skipped=10 rescued=0 ignored=0

Verification

  1. Log in to the SSH server:

    $ ssh user1@10.1.1.1

    Where:

    • user1 is a user on the SSH server.
    • 10.1.1.1 is the IP address of the SSH server.
  2. Check the contents of the sshd_config file on the SSH server:

    $ cat /etc/ssh/sshd_config
    …
    PasswordAuthentication no
    PermitRootLogin no
    …
    Match Address 192.0.2.0/24
      PasswordAuthentication yes
      PermitRootLogin yes
    …
  3. Check that you can connect to the server as root from the 192.0.2.0/24 subnet:

    1. 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.

    2. Connect to the server as root:

      $ ssh root@10.1.1.1

Additional resources

  • /usr/share/doc/rhel-system-roles/sshd/README.md file.
  • ansible-playbook(1) man page.

2.3. ssh System Role variables

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
Note

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 to auto, 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 the ssh_drop_in_name variable, automatically disables the ssh_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 is 00-ansible.

Warning

If the system does not support drop-in directories, setting this option will make the play fail.

The suggested format is NN-name, where NN is a two-digit number used for ordering the configuration files and name 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 the ssh dict.
ssh_additional_packages
This role automatically installs the openssh and openssh-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.
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 is 0644. If ssh_user is defined, the mode is 0600, and the owner and group are derived from the user name specified in the ssh_user variable.

2.4. Configuring OpenSSH clients using the ssh System Role

You can use the ssh System Role to configure multiple SSH clients by running an Ansible playbook.

Note

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 from RHEL 8).

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.
  • The managed nodes or groups of managed nodes on which you want to run this playbook are listed in the Ansible inventory file.

Procedure

  1. Create a playbook file, for example ~/ssh-clients-playbook.yml, with the following content:

    ---
    - hosts: all
      tasks:
      - name: "Configure ssh clients"
        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: 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 the <example.com> host is <user1>.
    • The <example> host alias is created, which represents a connection to the <example.com> host the with the <user1> user name.
    • X11 forwarding is disabled.

    Optionally, you can modify these variables according to your preferences. For more details, see ssh System Role variables.

  2. Validate the playbook syntax:

    # ansible-playbook --syntax-check ~/ssh-clients-playbook.yml

    Note that this command only validates the syntax and does not protect against a wrong but valid configuration.

  3. Run the playbook:

    # ansible-playbook ~/ssh-clients-playbook.yml

Verification

  • Verify that the managed node has the correct configuration by opening the SSH configuration file in a text editor, for example:

    # vi ~root/.ssh/config

    After application of the example playbook shown above, the configuration file should have the following content:

    # Ansible managed
    Compression yes
    ControlMaster auto
    ControlPath ~/.ssh/.cm%C
    ForwardX11 no
    GSSAPIAuthentication no
    Host example
      Hostname example.com
      User user1

2.5. 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.

In RHEL 8 and earlier, you can apply the non-exclusive configuration with a configuration snippet.

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.
  • The managed nodes or groups of managed nodes on which you want to run this playbook are listed in the Ansible inventory file.
  • A playbook for a different RHEL System Role.

Procedure

  1. Add a configuration snippet with the sshd_config_namespace variable to the playbook:

    ---
    - hosts: all
      tasks:
      - name: <Configure SSHD to accept some useful environment variables>
        include_role:
          name: rhel-system-roles.sshd
        vars:
          sshd_config_namespace: <my-application>
          sshd:
            # Environment variables to accept
            AcceptEnv:
              LANG
              LS_COLORS
              EDITOR

    When you apply the playbook to the inventory, the role adds the following snippet, if not already present, to the /etc/ssh/sshd_config file:

    # 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>

Verification

  • Optional: Verify playbook syntax.

    # ansible-playbook --syntax-check <playbook.yml>

Additional resources

  • /usr/share/doc/rhel-system-roles/sshd/README.md file.
  • ansible-playbook(1) man page.