Contenu de la leçon
Il existe de multiples options pour utiliser SSH en Python mais Paramiko est la plus populaire. Paramiko est une bibliothèque de protocole SSHv2 pour Python. Dans cette leçon, je vais vous montrer comment utiliser Paramiko pour vous connecter à un routeur Cisco IOS, exécuter une commande show et nous renvoyer la sortie.
Configuration
Voici la topologie:
J’utiliserai un routeur Cisco IOS exécutant la version IOS 15.7(3)M3 et j’exécuterai le code Python depuis mon ordinateur.
Routeur
Sur le routeur, nous devons activer SSH:
R1(config)#ip domain-name networklessons.localR1(config)#crypto key generate rsa general-keys modulus 1024R1(config)#ip ssh version 2R1(config)#username admin privilege 15 secret adminR1(config)#line vty 0 4R1(config-line)#transport input sshR1(config-line)#login local
J’ai configuré un utilisateur « admin » avec le niveau de privilège 15 afin que nous ayons un accès complet au routeur une fois connecté.
Python
Nous devons installer Paramiko, ce qui est facile avec PIP:
pip install paramiko
Nous sommes maintenant prêts à essayer du code.
Echantillon de code
Dans notre premier exemple, voici ce que nous essayons d’accomplir :
- Connexion au routeur avec authentification par nom d’utilisateur/mot de passe.
- Exécuter la commande
show ip route
. - Rechercher la route par défaut dans la sortie et nous la montrer.
Voici mon code :
import paramikorouter_ip = "172.16.1.100"router_username = "admin"router_password = "admin"ssh = paramiko.SSHClient()# Load SSH host keys.ssh.load_system_host_keys()# Add SSH host key automatically if needed.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())# Connect to router using username/password authentication.ssh.connect(router_ip, username=router_username, password=router_password, look_for_keys=False )# Run command.ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("show ip route")output = ssh_stdout.readlines()# Close connection.ssh.close()# Analyze show ip route outputfor line in output: if "0.0.0.0/0" in line: print("Found default route:") print(line)
Lorsque nous exécutons ce code, voici ce que nous obtenons :
Found default route:S* 0.0.0.0/0 via 172.16.1.254
C’est bien. Nous avons réussi à nous connecter au routeur, à exécuter la show ip route
commande et à rechercher la route par défaut.
Échantillon de code amélioré
Comment pourrions-nous améliorer ce script avec certaines des choses que nous avons apprises ? Par exemple :
- Notre code exécute une seule commande. Que diriez-vous d’utiliser une fonction pour que nous puissions utiliser notre code pour nous connecter à différents appareils et exécuter différentes commandes ?
- Que faire si notre connexion SSH échoue ? Il serait bien de traiter cela avec un bloc try/except. Et si nous essayions de tenter de nous connecter plusieurs fois ?
Voyons ce que nous pouvons faire. Voici mon code amélioré :
import paramikorouter_ip = "172.16.1.100"router_username = "admin"router_password = "admin1"ssh = paramiko.SSHClient()def run_command_on_device(ip_address, username, password, command): """ Connect to a device, run a command, and return the output.""" # Load SSH host keys. ssh.load_system_host_keys() # Add SSH host key when missing. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) total_attempts = 3 for attempt in range(total_attempts): try: print("Attempt to connect: %s" % attempt) # Connect to router using username/password authentication. ssh.connect(router_ip, username=router_username, password=router_password, look_for_keys=False ) # Run command. ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(command) # Read output from command. output = ssh_stdout.readlines() # Close connection. ssh.close() return output except Exception as error_message: print("Unable to connect") print(error_message)# Run functionrouter_output = run_command_on_device(router_ip, router_username, router_password, "show ip route")# Analyze show ip route output# Make sure we didn't receive empty output.if router_output != None: for line in router_output: if "0.0.0.0/0" in line: print("Found default route:") print(line)
Qu’est-ce que j’ai changé ?
- J’ai créé une fonction pour contenir le code utilisé pour se connecter au routeur.
- J’ai ajouté un bloc
try/except
pour la connexion avec plusieurs tentatives. Lorsque la connexion échoue, il affiche la raison. - Une vérification supplémentaire pour voir si la sortie du routeur contient des informations.
Vérification
Exécutons à nouveau notre code pour voir s’il fonctionne.
Mauvais mot de passe
Lorsque vous fournissez un mauvais mot de passe, vous obtenez cette sortie:
Attempt to connect: 0Unable to connectAuthentication failed.Attempt to connect: 1Unable to connectAuthentication failed.Attempt to connect: 2Unable to connectAuthentication failed.
Cela semble bon. Notre code a tenté de se connecter trois fois et a montré la raison pour laquelle il n’a pas pu se connecter.
Hôte indisponible
Lorsque votre hôte est indisponible, vous obtenez cette sortie:
Attempt to connect: 0Unable to connect A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respondAttempt to connect: 1Unable to connect A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respondAttempt to connect: 2Unable to connect A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Encore une fois, trois tentatives de connexion et il montre la raison pour laquelle notre script a échoué.
Conclusion
Vous avez maintenant appris comment vous pouvez vous connecter à un périphérique en utilisant SSH et Python. Bien que cela fonctionne, ce n’est peut-être pas la meilleure solution. Dans cet exemple, j’ai exécuté la commande show ip route
et j’ai recherché la route par défaut. C’est simple, mais que faire si vous voulez analyser les commandes de spectacle qui ont beaucoup d’informations ?
Il est possible d’analyser la sortie des commandes de spectacle comme cela en utilisant des expressions régulières, mais c’est une douleur. Au lieu de cela, si possible, il est préférable d’utiliser une API REST où le périphérique renvoie la sortie au format JSON. L’analyse syntaxique de JSON en Python est beaucoup plus facile.