Ansible and telnet: when not, but really want

Telnet is a obviously a very insecure protocol, completely insecure in fact, and we strongly want to discourage usage. We would likely refuse the pull request, to be honest - it is just asking for a world of hurt should MITM possibilities arise.- Michael DeHaan, creator of Ansible I
absolutely agree. Um, what should I do when I have 20 thousand legacy switches that reboot / freeze due to SSH connection, and part of the equipment does not support it at all?
I ask for cat.
UPD: the guide is deprecated because in version 2.5 they released a separate telnet module
docs.ansible.com/ansible/latest/modules/telnet_module.html
Ansible Features
Ssh
At the moment (release 2.3.0), Ansible uses 3 types of connections:
- Ssh
- Local
- Docker
In fact, SSH consists of 2 types and is distinguished by the use of transport - ssh and paramiko. The latter was used by default before version Ansible 1.3, modern distributions use the smart parameter (i.e. OpenSSH), significantly speeding up SSH using multiplexing (Control Master function). For compatibility with legacy equipment, it is better to use paramiko, setting the key
–c paramiko
when working with modules / playbooks. Important: for password authentication, not key authentication, sshpass is used instead of ssh.
Install the package if necessary.
sudo apt-get install sshpass
For RHEL-based systems you need to enable EPEL
yum --enablerepo=epel install sshpass
For SSH, there is an excellent raw module that sends one command to the required number of hosts and displays output from all hosts. For Telnet, we will have to use a playbook that has similar functionality.
Telnet
To work with Telnet, we are forced to use the local connection type . This means that playbook commands will be executed directly on the Ansible host (Python, heh, are unlikely to be installed on remote switches).
To do this, install:
sudo apt-get install telnet
or
yum install telnet
You will also need pexpect , which is available through the pip add-on manager . Pip is installed along with Ansible, so just run:
pip install pexpect
Environment preparation is complete.
Inventory setup
We will use the standard file / etc / ansible / hosts
[test_cluster]
192.168.0.[10:25]
So, our switches are part of the test_cluster entity, they have IP addresses from 192.168.0.10 through 192.168.0.25. It is assumed that a single account with administrator rights is configured on them, telnet access is allowed.
Create our playbook in .yml format
---
- hosts: test_cluster
gather_facts: false
connection: local
tasks:
- name: telnet,login and execute command
ignore_errors: true
expect:
command: telnet "{{ inventory_hostname }}"
responses:
(?i)username: "admin"
(?i)password: "12345"
(?i)#: "{{COMMAND}}\r\nlogout\r\nexit\r\nquit"
echo: yes
register: telnet_output
- name: Debug output
debug: var=telnet_output.stdout_lines
Let's go in order:
hosts: test_cluster
Hosts to which you are connecting
gather_facts: false
Normally does not work with network equipment, you need to disable
connection: local
Pexpect is only on the Ansible host.
tasks:
Getting started with modules
ignore_errors: true
It is not known what will happen in the output - due to the limited functionality of the expect module, the result may be FAILED. It is recommended to disable.
command: telnet "{{ inventory_hostname }}"
It runs on the Ansible host and connects to all remote hosts.
responses:
(?i)
means case is ignored. Before
:
we indicate what we expect, after what we answer. #
- we verify that authentication is successful, we are in privileged mode; we respond with a combination of a command variable with exit from the terminal (logout / exit / quit) Working with expect requires a thorough knowledge of the CLI of the remote host, the presence of python regular expression skills. For example, adding a line
#: "save"
would be pointless because matching will occur only on the first condition#: "{{COMMAND}}\r\nlogout\r\nexit\r\nquit"
register: telnet_output
We collect the output, put it in the telnet_output variable.
Debug
returns us the output in a convenient way. We start the playbook with the necessary command:
ansible-playbook raw_telnet.yml -e '{"COMMAND":"show stp"}'
Execution Result:
"Command: show stp",
"",
"",
"",
"STP Bridge Global Settings",
"",
"---------------------------",
"",
"STP Status : Enabled",
"",
"STP Version : RSTP",
"",
"Max Age : 20 ",
"",
"Hello Time : 2 ",
"",
"Forward Delay : 15 ",
"",
"Max Hops : 20 ",
"",
"TX Hold Count : 3 ",
"",
"Forwarding BPDU : Enabled",
If desired, almost everything can be replaced with variables and not edit the playbook at all. Of course, storing passwords in clear text is also unsafe, for this Vaults exist in Ansible.
REFERENCES:
→ Original documentation
→ Ansible basics
→ Ansible + UPD networks
: the guide is deprecated because in version 2.5 they released a separate module telnet
docs.ansible.com/ansible/latest/modules/telnet_module.html