Netmiko: Trying both Telnet and SSH on a Cisco IOS Device

Back to Home

Published: 09/09/2017

Scenario:

You have a large estate of Cisco IOS devices implemented over many years under many different network engineers. You want to use a Python script to log into every device on the network and check for something, for example, is NTP authentication being used?

Problem:

Your large estate is mixed telnet access and SSH access, however you want to use the same script to query all devices.

Assumptions:

First of all, we are using the CSV module to read and import data.

#import argv to be able to call the csv file like 'python script.py devices.csv'
from sys import argv
#import csv module to be open to easily open and parse csv files.
import csv
#Import getpass so we can easily mask user input for passwords
import getpass

#here we set what two variables we are going to put in the command line.
#1st is always 'script' and then you can define as many as you want
script, csv_file = argv

#now we want to define an object that contains our parsed csv file.
#we open the file with 'rb' tag (read binary) to ensure we get no funk formatting
reader = csv.DictReader(open(csv_file, 'rb'))

Next, we need a list to be able to loop through, define an empty list and use a short for loop to populate it:

device_list = []

#takes our object we created from the parsed csv and makes a dict from each line
for line in reader:
    device_list.append(line)

Because we used 'csv.DictReader' the object is already parsed and each line would look like a dictionary if you were to print it, however we want to extract each line into a real dictionary.

We now want to get a username and password from the user. We do this by using the "raw_input()" method and by using getpass that we imported earlier.

username = raw_input("Username? ")
password = getpass.getpass("Password? ")
enablepw = getpass.getpass("Enable Password? ")

Now that we have all the required data, we create our loop that will attempt to connect to the device and run commands.

This is the bulk of the script, so it's going to be big. I have done my best to comment each part. This is where we try both SSH and telnet:

#this is the block most of your code will go. This is to loop through every dictionary in the list
for device in device_list:

    #create a heading so if there are multiple devices, you know what the output is for
    print "\n\n----------------------\nDevice: {0} \n----------------------\n".format(device['host'])

    #Use a try, so it doesn't throw an exception and cancel out of the script.
    try:
        #we need to set the various options Netmiko is expecting. 
        #We use the variables we got from the user earlier
        device['device_type'] = 'cisco_ios_ssh'
        device['username'] = username   
        device['password'] = password
        device['secret'] = enablepw
        #This command is when we are attempting to connect. If it fails, it will move on to the except block below
        net_connect = ConnectHandler(**device)
    except:
        #here we are saying "if ssh failed, TRY telnet"
        try:
            #same as before, but using the 'telnet' device type
            device['device_type'] = 'cisco_ios_telnet'
            device['username'] = username
            device['password'] = password
            device['secret'] = enablepw
            net_connect = ConnectHandler(**device)
        except:
            #this is the catch all except, if NOTHING works, tell the user and continue onto the next item in the for loop.
            print "Unable to connect!"
            continue

Once we have successfully connected to the device, we want to go into enable mode, run a show command and look for output.

#breaking out of the "try" block, we now want to take the session into "enable mode" if it is not already
net_connect.enable()

#just printing a blank line. I like formatting the output neatly.
print "\n"

#Now to run a command and do checks on the output.
output = net_connect.send_command("show run | i ntp auth")
#we want to split the output into individual lines and find specific lines.
for line in output.splitlines():
    #if we find the following string in the line, we are going to print the line
    if "ntp authen" in line:
        print "     " + line

Now run the script with the syntax:

python script.py csvfile.csv

I went to run the script to get an example of output. First time round, I mistyped the password by accident which shows it not working.

ashley@Ashley-PC:/mnt/c/workarea$ python telnetandssh.py devices.csv
Username? Ashley
Password?
Enable Password?


----------------------
Device: core_sw
----------------------

Unable to connect!
ashley@Ashley-PC:/mnt/c/workarea$ python telnetandssh.py devices.csv
Username? ashley
Password?
Enable Password?


----------------------
Device: core_sw
----------------------



     ntp authentication-key 1 md5 06120A3258 7
     ntp authenticate

Let me know if this is useful to you! Remember you can change this to how you need it. You could also use the CSV file to define passwords rather than collecting them on script execution. You could extend it to collect more than one set of credentials and make the script try multiple sets of creds.

At the end of the day, these are some pretty nice building blocks to a script. Use them how you want!