Python SSH

This topic is to discuss the following lesson:

Hi Rene

Fantastic script.
It works on my homelab and on GNS3 too, do you know how make more commands in a single session?

Thanks

Hello Giovanni

In order to implement more commands in a single session, you simply input them in a similar manner in the # Run command. section of the script.

I hope this has been helpful!

Laz

1 Like

Hello Giovanni,

This lesson is part of a Python course which I’m currently working on, it’s almost finished. In the course I explain everything, so you’ll know how to write an example like this yourself.

As Lazaros explained, you can add multiple commands at the bottom of the script:

# Run function
router_output = run_command_on_device(router_ip, router_username, router_password, "show ip route")

Rene

So it doesn’t seem to work.

It works using more channels like this …

import paramiko
import cmd
import time
import sys

buff = ''
resp = ''

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.99.10', username='test', password='test')
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

#run command
chan = ssh.invoke_shell()

# turn off paging
chan.send('terminal length 0\n')
time.sleep(1)
resp = chan.recv(9999)      # recv(nbytes)
                            #Receive data from the channel. The return value is a string representing the data received. 
                            # The maximum amount of data to be received at once is specified by nbytes. 
                            # If a string of length zero is returned, the channel stream has closed.

output = resp.decode('ascii').split(',')

print (''.join(output))

# Display output of first command
chan.send('sh ip int br')
chan.send('\n')
time.sleep(1)
resp = chan.recv(9999)
output = resp.decode('ascii').split(',')
print (''.join(output))

# Display output of second command
chan.send('sh ver')
chan.send('\n')
time.sleep(1)
resp = chan.recv(9999)
output = resp.decode('ascii').split(',')
print (''.join(output))

#closer
ssh.close()

https://evilttl.com/wiki/Execute-MULTIPLE-commands-with-Python

Hi.
I’m try to make a script to automate some tasks with Fortigate Fw.
When I try the connection , python sollevate this exception.

>>> ssh.connect("192.168.1.99",
	    22,
            username="admin", 
            password=None,
            look_for_keys=False )
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    ssh.connect("192.168.1.99",
  File "C:\...\Python38-32\lib\site-packages\paramiko\client.py", line 435, in connect
    self._auth(
  File "C:\...\Python38-32\lib\site-packages\paramiko\client.py", line 765, in _auth
    raise SSHException("No authentication methods available")
paramiko.ssh_exception.SSHException: No authentication methods available

I discovered that issue exist with no password for ‘admin’ user, for example if I set a password on the device, i have no error during the connection

The appliance has no password.

Thanks

Hello Giovanni

It looks like it’s an issue with your attempt to connect using SSH with Paramiko with no password. Apparently, this doesn’t work. I suggest you take a look at this thread from GitHub that further discusses this issue, as the specific problem, as well:

I hope this has been helpful!

Laz

Thank you for your reply,

I solved in this way.

`ssh.connect(fw_dict["FGT60E"]["mgt_ip"], username=fw_dict["FGT60E"]["usr"], password="",port=22,allow_agent=False,look_for_keys=False)`

Where fw_dict is a dictionary built from a json file, I don’t know why , but i’m not able to specify an empty password (“”) with the same dictionary (fw_dict[“FGT60E”][“psw”]), when I try it , python give me this errors about authentication methods.

But also I’ve discovered another interest things about paramiko…exist a difference between exec_command and send command, infact the last one not work on configuration mode, but is useful only for multiple show in a single ssh session.

https://stackoverflow.com/questions/55762006/what-is-the-difference-between-exec-command-and-send-with-invoke-shell-on-para

Hi Rene,

I’m working on it and I’m doing what you told me.

But it not work because each time paramiko needs a new connection and so I lose the access of the configuration mode obtained with the previous command.

Hello Giovanni

Great to hear that the problem was solved. Thanks so much for sharing your solution!

Laz

Hi,
I not really solved.

I think that paramiko is not a scalable solution to make powerful script because is limited at one session at time… I’ve read about netmiko that is an improvement of paramiko library.

Hello Giovanni

Sorry about that, I was referring to your post where you shared how you “solved” the issue, but I understand that it has not yet been resolved. Let me try to help you out here.

Paramiko which you are using is a general SSH library and has a particular way in which it implements commands. With Cisco IOS, when you’re using the exec_command, it only allows a single command, and then exits, and requires you to login again. As stated in the following link:

You need to run the .invoke_shell() method to execute multiple commands.

When using Paramiko you will always need to work around these kinds of issues when connecting to Cisco IOS devices. And what might work for one vendor may not work for another. You may also find differences in the way IOS devices and ASA devices handle Paramiko.

It may be worth trying a different library. In particular, @ReneMolenaar recommends using Netmiko which you can find here:

Netmiko is based on Paramiko but the developer Kirk Byers has already done the work to ensure that it works well with a range of network devices, including Cisco devices.

I hope this has been helpful!

Laz

1 Like

Yes and yes , Yesterday I’ve tried this library and all works properly…this is magic and very powerful…I think about devops path as new target of Cisco certification… simply is awesome

Thank you

1 Like

Hello Rene/Laz,
I have zero knowledge about programming and that is why all of my questions may sound stupid to you. However, I am really interested to learn python scripting and eventually be able to use it to automate tasks in production network. I have been kind of going through all the python lessons and I am having really hard time to put all the puzzles together. Lessons that just talk about the python language itself, I kind of get them, but when scripting gets into device configuration, I kind of get lost. Having said that please help me to understand the below questions:

  1. As far as my understanding goes, Python platform itself is used to write code, but it does not have the capability to communicate with networking devices and that is why software like Netmiko and Paramiko come into play. Can I consider Netmiko or Paramiko as medium to execute scripts in networking devices?
  2. Does every tool like Netmiko or Paramiko have its own commands which are used in combination with python scripts? The reason why I am asking is that I see different scripts are being used for the same task based upon the platform (Nemiko or Paramiko).
  3. I see for Paramiko, these commands are always being used. What are they for?
    import paramiko
    from getpass import getpass
    import time
    I have the same question as well for Netmiko and here are the commands:
    from netmiko import ConnectHandler
    from getpass import getpass

Thank you so much as usual.
Best Regards,
Azm

Hello Azm

There is no such thing as a stupid question. Questions are how we learn, and that is the very purpose of this forum, so feel free to fire away!!

For the most part yes. Netmiko and Paramiko are actually SSH libraries that are specifically designed to allow you to easily use the python language to connect to network devices via the SSH protocol. It is kind of the interface between the python script and the SSH connectivity of a device.

As software libraries, both Netmiko and Paramiko offer python a series of functions. These functions are pre-programmed entities that do particular tasks. This saves you from programming the low-level details of SSH connectivity every time you simply want to connect. In programmers terms, these functionalities are “abstracted” into specific functions. For example, the following function named SSHClient() exists within the paramiko library and is called upon like so:

conn = paramiko.SSHClient()

This, along with other configured parameters, is used to simply connect to the device using SSH. Because these libraries are different, their functions and the syntax used to actually call them (programmer’s jargon for the command used to execute a function) are also different. Their differences though go beyond just different syntax. Paramiko is said to be more “low-level” meaning it requires more programming on your part to do what you want to do, while Netmiko helps to hide many programming details providing greater abstraction of the communication with networking equipment. Actually, Netmiko uses Paramiko for its low-level SSH connectivity, and simply adds more functionality for higher-level requirements, automating more of the connectivity process, and hiding these details behind the preconfigured libraries.

All of these commands, for both paramiko and netmiko are used to import particular libraries that contain the functions that will be subsequently used. For example, take a look at this code:

01) #!/usr/bin/env python3
02) import sys
03) from time import sleep
04) import paramiko
05) router="192.168.1.108"
06)  
07) # Create an ssh connection and set terminal length 0
08) conn = paramiko.SSHClient()
09) conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
10) conn.connect(router, username="tester", password="foobar")
11) router_conn = conn.invoke_shell()
12) print('Successfully connected to %s' % router)
13) router_conn.send('terminal length 0\n')
14) sleep(1)        # Wait for the cmd to be sent and processed
15)  
16) # Send the command and wait for it to execute
17) router_conn.send("show arp\n")
18) sleep(2)
19)  
20) # Read the output, decode into UTF-8 (ASCII) text, and print
21) print(router_conn.recv(5000).decode("utf-8"))

The first five lines import the libraries needed from paramiko and define the IP address of the router to which you are to connect. The subsequent calls of paramiko.SSHClient() and paramiko.AutoAddPolicy() and other commands you see, are found within the libraries that have been imported. In particular, the sleep function has been specifically added beyond the basic functions provided by paramiko.

Similarly the netmiko commands import particular functions from specific modules to be used later in the programming.

You can find more info about these module and function calls at the following links:

Don’t feel overwhelmed as this is still the beginning for you. You will get your head around these topics and the way things work simply by continuing what you’re doing: studying and reading, and learning…

I hope this has been helpful!

Laz

Hello Laz,
Thanks a lot for your reply. A few more questions:

  1. What do these 2 commands do. It looks like without running both of these commands, Netmiko is not establishing any ssh session.
    from netmiko import ConnectHandler
    from getpass import getpass
    However, I have watched some videos in youtube and some folks are only using from netmiko import ConnectHandler and they are still able to establish a ssh session. What is the standard command to fire up Netmiko?

  2. I have saved a script in a .py file as shown below and I was under the impression that once I click the file, it will execute the code automatically, but unfortunately, it’s not doing anything.

image

Even I have tried to run this file from IDLE Python shell and it’s giving me some error.

image

Is there any way I can run a long script at once as opposed to typing one line at a time?

  1. Is there any way I can establish ssh sessions from Netmiko to multiple cisco router and execute the same set of commands simultaneously? If so, please provide a sample script.

Thanks a lot.

Best Regards,
Azm

Hi Azm,

Let’s see if I can help you out. First of all, I understand the confusion…I ran into the same issues when I learned Python for the first time.

I would advise becoming very familiar with “basic” python scripts first. It’s so much easier when you only have to deal with your own code instead of third party libraries.

Try creating a module on your own first that you import, that might help to understand things.

Having said that, let’s take a look.

With these import lines, we import the “ConnectHandler” function from the netmiko library and the “getpass” function from the getpass library. Here’s an explanation with the differences between importing an entire module vs importing a function of a module:

Now the big question is, what is the “ConnectHandler” function from netmiko? Looking at the examples:

It seems that this is a function that establishes the connection through SSH. If you really wanted to know, you could dive into the netmiko code. Searching for “def ConnectHandler” I find this:

Looking at the code, we can see that the ConnectHandler function calls another function (ssh_dispatcher). Now you could dive into netmiko further and further, you shouldn’t. This will be a rabbit hole with no end. The goal of using a library like netmiko is to abstract away the complexity of connecting with SSH, making it possible to connect to a device with only a few lines of code in your own script.

What about the getpass function? Let’s check the documentation:

https://docs.python.org/2/library/getpass.html

Their documentation explains it well:

The getpass module provides two functions:

getpass.getpass([prompt[, stream]])

Prompt the user for a password without echoing. The user is prompted using the string prompt, which defaults to 'Password: '. On Unix, the prompt is written to the file-like object stream. stream defaults to the controlling terminal (/dev/tty) or if that is unavailable to sys.stderr (this argument is ignored on Windows).

So when you see this in Python code, people use it so that when a user types the password, it doesn’t show up on your screen.

When you use any third-party libraries, I would always suggest checking the documentation. Popular libraries have good documentation with examples and explanations. Youtube videos can be useful but you still want to know what you are doing in your own code.

There are two ways to execute Python code, there’s a detailed explanation here:

  1. You type Python code in the Interpreter which you recognize with the >>> symbols.
  2. You run Python scripts from the command-line with “python .py”

The interpreter is useful when you want to test something quickly, otherwise, it’s so much easier to write a .py file and execute it.

This example of netmiko is a good start:

They execute this code for a single network device. You could use a Python for loop to execute this for multiple devices:

I hope this helps!

Rene

Hello Rene,
Now it makes sense to me. I was trying to execute the below script on two routers in GNS3, but interestingly, the script is configuring only 10.10.10.100 router and doing nothing to the other router. Would you please let me know if anything is incorrect in the script?

image

Also, I have noticed one thing. As you see in the script, different texts are in different colors. Why is that?

Thanks a lot.

Best Regards,
Azm

Hi Azm,

Take a look at your for loop. The line(s) that are indented belong to your for loop. In this case, that’s only the net_connect = ConnectHandler(**device) line.

This is what happens:

  • In the first iteration of your for loop, it sets the variable “device” to the “cisco1” variable, then executes net_connect = ConnectHandler(**device). That’s it.
  • In the second iteration of your for loop, it sets the variable “device” to the cisco2" variable, then executes net_connect = ConnectHandler(**device). That’s it.

Now your script continues, while “device” is set to the information from the “cisco2” variable.

What you should do, is move those last 4 lines so they belong to your for loop.

If you ever run into issues like this, there are two things you can do to troubleshoot it:

  • Add some print commands with things like “Executing commands %s on device %s” % (config_commands, device). This helps to see what your program is doing.

OR

  • Use a debugger. This is so much easier, you can pause your code at any moment and see what the value(s) of the variables are at the breakpoint. Here is an example how to do this:

This is what most IDEs do. They highlight things to make it easier to read. In this case, strings are green, functions are purple, the loop is in orange :slight_smile:

I hope this helps!

Rene

Hi

i want make practise with python script example connect to ssh on router
i have problem i have mac pc and he cant’ connect to gns3 how i can resolve it ?
there are other method to logon on Devices with python ?
thanks