New LibSSH Connection Plugin for Ansible Network Replaces Paramiko, Adds FIPS Mode Enablement
As Red Hat Ansible Automation Platform expands its footprint with a
growing customer base, security continues to be an important aspect of
organizations' overall strategy. Red Hat regularly reviews and enhances
the foundational codebase to follow better security practices. As part
of this effort, we are introducing
FIPS 140-2
readiness
enablement by means of a newly developed Ansible SSH connection plugin
that uses the
libssh
library.
Ansible Network SSH Connection Basics
Since most network appliances don't support or have limited capability
for the local execution of a third party software, the Ansible network
modules are not copied to the remote host unlike linux hosts; instead,
they run on the control node itself. Hence, Ansible network can't use
the typical Ansible SSH connection plugin that is used with linux host.
Furthermore, due to this behavior, performance of the underlying SSH
subsystem is critical. Not only is the new LibSSH connection plugin
enabling FIPS readiness, but it was also designed to be
more performant than the existing Paramiko SSH subsystem
.
The top level
network_cli
connection
plugin, provided by the ansible.netcommon Collection (specifically
ansible.netcommon.network_cli
), provides an SSH based connection to the
network appliance. It in turn calls the
ansible.builtin.paramiko_ssh
connection plugin that depends on the paramiko python library to
initialize the session between control node and the remote host. After
that, it creates a pseudo terminal (PTY) to send commands from the
control node to the network appliance and receive the responses.
Why Replace Paramiko?
The primary reason to replace the paramiko library is that it doesn't
guarantee FIPS readiness and thus limits the Ansible network capability
to run in environments that mandate FIPS mode to be enabled. Paramiko
also isn't the speediest of connection plugins, so that can also be
enhanced. Therefore, the new
ansible.netcommon.libssh
connection plugin
can now be easily swapped in for paramiko. The
ansible.netcommon
Collection now contains this by default, and can be used for testing
purposes until the codebase becomes more stable (it is currently
Technology Preview
).
Comparing the connection flow to the above, the top level
network_cli
connection plugin that is provided by the
ansible.netcommon
Collection
(specifically
ansible.netcommon.network_cli
) still provides an SSH based
connection to the network appliance. It in turn calls the
ansible.netcommon.libssh
connection plugin that depends on the
ansible-pylibssh
python library
to initialize the session between control node and the remote host. This
python library is essentially a cython wrapper on top of the
libssh C library
. It then creates pseudo terminals
(PTY) over SSH using python.
Switching Ansible Playbooks to use LibSSH
With the
ansible.netcommon
Collection version 1.0.0, a new configuration
parameter within
ansible.netcommon.network_cli
connection plugin was
added, which allows for
ssh_type
be set to either
libssh
or
paramiko
.
If the value of the configuration parameter is set to
libssh
, it will use the
ansible.netcommon.libssh
connection plugin, which in turn uses the
ansible-pylibssh
python library that supports FIPS readiness. If the
value is set to
paramiko
, it will continue to use the default
ansible.builtin.paramiko
connection plugin that relies on the
paramiko
python library.
Again, the default value is set to
paramiko
, but in the future plans are
to change the default to
libssh
.
Installing and Configuring LibSSH
In order to utilize the LibSSH plugin, you must first install the
ansible-pylibssh
python library from PyPI via the following command:
pip install ansible-pylibssh
NOTES:
The current PyPI installation method bundles the correct version of
LibSSH
library and its dependencies as platform-specific
wheels
that don't rely on any OS-level libraries in runtime.
Future plans include creation, publishing, and maintenance of
stand-alone RPM and DEB packages for the ansible-pylibssh
library
that can be installed with well-known Linux package managers. These
will install the required system libssh
version and its dependencies
on the control node. FYI, Red Hat Enterprise Linux 8.1 and later
contains the proper libssh
package version and its dependencies.
The current primary use case for using LibSSH with Ansible is for
connecting to network devices. Connecting to other types of
endpoints (such as Linux) will be officially enabled at a later
date.
Using LibSSH in Ansible Playbooks
Method 1: The ssh_type
configuration parameter can be set to use
libssh
in the active ansible.cfg
file of your project as shown below:
[persistent_connection]
ssh_type = libssh
Method 2: Set the ANSIBLE_NETWORK_CLI_SSH_TYPE
environment variable as shown below:
$export ANSIBLE_NETWORK_CLI_SSH_TYPE=libssh
Method 3: Set the ansible_network_cli_ssh_type
parameter to libssh
within your playbook at the play level (as shown in below example).
NOTE: This setting can be made at the individual task level, but only if
the connection to the remote network device is not already established.
That is, if the first task uses paramiko
, then all subsequent tasks in
the play must use paramiko
even if libssh
is specified in any subsequent
tasks.
Troubleshooting LibSSH Connections
To quickly verify the libssh transport is set correctly, you can run the
below playbook using the ansible-playbook
command line with verbose flag
(-vvvv) added. Before running, ensure the inventory file is set correctly.
This example playbook uses the cisco.ios
Collection and must first be
installed from Ansible Galaxy or Ansible Automation Platform on your
Ansible control node.
- hosts: "changeme"
gather_facts: no
connection: ansible.netcommon.network_cli
vars:
ansible_network_os: cisco.ios.ios
ansible_user: "changeme"
ansible_password: "changeme"
ansible_network_cli_ssh_type: libssh
tasks:
- name: run show version command
ansible.netcommon.cli_command:
command: show version
- name: run show interface command
ansible.netcommon.cli_command:
command: show interfaces
https://gist.github.com/ganeshrn/78149adca85c809b69ed1b5f5262844c
In the output verbose logs, you should see the line "ssh type is set to libssh" displayed on the console, which confirms the configuration is
set correctly.
Next Steps and Resources
Start testing your Ansible network playbooks by setting the
configuration to use the ansible-pylibssh library.
Help with performance profiling of your existing playbook of
ansible-pylibssh library with respect to paramiko library.
Get involved with the ansible-pylibssh project
(https://github.com/ansible/pylibssh)