In our sample network, we will use SSH to set up the connection between Ansible and our Cisco devices. In this setup, Ansible will use SSH in order to establish the connection to our Cisco devices with a view to start managing it. We will use username/password authentication in order to authenticate our Ansible control node with our Cisco devices.
On the Cisco devices, we must ensure that SSH keys are present in order to have a functional SSH server on the Cisco devices. The following code snippet outlines the status of the SSH server on the Cisco device prior to generating the SSH keys:
wan01#show ip SSH
SSH Disabled - version 2.0
%Please create RSA keys to enable SSH (and of atleast 768 bits for SSH v2).
Authentication methods:publickey,keyboard-interactive,password
Authentication Publickey Algorithms:x509v3-SSH-rsa,SSH-rsa
Hostkey Algorithms:x509v3-SSH-rsa,SSH-rsa
Encryption Algorithms:aes128-ctr,aes192-ctr,aes256-ctr
MAC Algorithms:hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96
KEX Algorithms:diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1
Authentication timeout: 120 secs; Authentication retries: 3
Minimum expected Diffie Hellman key size : 2048 bits
IOS Keys in SECSH format(SSH-rsa, base64 encoded): NONE
Once we create the SSH keys, the SSH server on the Cisco device is operational, and is ready to accept an SSH connection from the Ansible control node.
On the Ansible machine, we include all the variables required to establish the SSH connection to the managed devices in the network.yml file. As per our inventory file, the network group includes all the devices within our topology, and so all the attributes that we configure in this file will apply to all the devices in our inventory. The following is a breakdown of the attributes that we included in the file:
- Ansible_connection: This establishes how Ansible connects to the device. In this scenario, we set it to network_cli to indicate that we will use SSH to connect to a network device.
- Ansible_network_os: When using network_cli as the connection plugin to connect to the network device, we must indicate which network OS Ansible will be connecting to, so as to use the correct SSH parameters with the devices. In this scenario, we will set it to ios, since all the devices in our topology are IOS-based devices.
- Ansible_user: This parameter specifies the username that Ansible will use to establish the SSH session with the network device.
- Ansible_password: This parameter specifies the password that Ansible will use to establish the SSH session with the network device.
- Ansible_become: This instructs Ansible to use the enable command to enter privileged mode when configuring or executing show commands on the managed device. We set this to yes in our context, since we will require privileged mode to configure the devices.
- Ansible_become_password: This specifies the enable password to use in order to enter privileged mode on the managed IOS device.
- Ansible_become_method: This option specifies the method to use in order to enter privileged mode. In our scenario, this is the enable command on IOS devices.
In this recipe, I have defined the SSH password and the enable passwords as plain text just for simplicity; however, this is highly discouraged. We should use Ansible-vault to secure the passwords, as outlined in the Ansible Vault recipe in the previous chapter.
On the Cisco devices, we set up the required username and password so that Ansible can open an SSH connection to the managed Cisco IOS devices. We also configure an enable password to be able to enter privileged mode, and to make configuration changes. Once we apply all of these configurations to the devices, we are ready to set up Ansible.
In any SSH connection, when an SSH client (Ansible control node in our case) connects to an SSH server (Cisco devices in our case), the server sends a copy of its public key to the client before the client logs in. This is used to establish the secure channel between the client and the server, and to authenticate the server to the client in order to prevent any man-in-the-middle attacks. So, at the start of a new SSH session involving a new device, we see the following prompt:
$SSH [email protected]
The authenticity of host '172.20.1.18 (172.20.1.18)' can't be established.
RSA key fingerprint is SHA256:KnWOalnENZfPokYYdIG3Ogm9HDnXIwjh/it3cqdiRRQ.
RSA key fingerprint is MD5:af:18:4b:4e:84:19:a6:8d:82:17:51:d5:ee:eb:16:8d.
Are you sure you want to continue connecting (yes/no)?
When the SSH client initiates the SSH connection to the client, the SSH server sends its public key to the client in order to authenticate itself to the client. The client searches for the public key in its local known hosts files (in the ~/.SSH/known_hosts or /etc/SSH/SSH_known_hosts files). In the event that it does not find the public key for this machine in its local known hosts file, it will prompt the user to add this new key to its local database, and this is the prompt that we see when we initiate the SSH connection.
In order to simplify the SSH connection setup between the Ansible control node and its remotely managed hosts, we can disable this host checking. We can do this by telling Ansible to ignore host keys and not to add them to the known hosts files by setting host_key_checking to False in the Ansible.cfg configuration file.
Disabling host key checking is not a best practice, and we are only showing it as it is a lab setup. In the next section, we will outline an alternative method to establish the SSH connection between Ansible and its remote managed devices.