Junos PyEZ utilisant l'exemple de la tâche de recherche de sous-réseaux ipv4 gratuits

Un article sur l'utilisation de Junos PyEZ - « Microframework Python qui vous permet de gérer et d'automatiser les appareils exécutant Junos OS », l'automatisation et la gestion, tout ce que nous aimons. L'écriture du script décrit dans cet article avait plusieurs objectifs : apprendre Python et automatiser les tâches de collecte d'informations ou de modification des configurations sur les équipements exécutant Junos OS. Le choix de cette combinaison spécifique Python + Junos PyEZ a été fait en raison de la faible barrière à l'entrée dans le langage de programmation Python et de la facilité d'utilisation de la bibliothèque Junos PyEZ, qui ne nécessite pas de connaissance experte de Junos OS.

Tâche

Audit des sous-réseaux ipv4 gratuits appartenant à l'entreprise. Le critère selon lequel un sous-réseau est libre est l'absence d'entrée le concernant dans les routes du commutateur agissant comme un routeur exécutant Junos OS.

exécution

Python + Junos PyEZ, même s'il y avait une tentation de le faire via paramiko et ssh.exec_command, Par conséquent, vous devrez configurer le protocole de gestion réseau du périphérique netconf sur l'équipement interrogé. Netconf fonctionne avec le matériel via un appel de procédure distant RPC et utilise XML, dans cet exemple, pour fournir les informations qu'il reçoit.

L'installation de la version actuelle de Junos PyEZ depuis PyPI se fait avec la commande suivante :

$ pip install junos-eznc

Vous pouvez également installer depuis la branche principale du projet sur GitHub avec la commande suivante :

$ pip install git+https://github.com/Juniper/py-junos-eznc.git

Et une autre option via

$ pip install -r requirements.txt 

Cette commande installera les bibliothèques manquantes dans le système et nécessaires au fonctionnement. Dans ma version conditions.txt Il n'en existe que deux, les dernières versions sont indiquées au moment de la rédaction du script :

junos-eznc
netaddr

Par défaut, le script prend le nom de l'utilisateur actuel dans le système ; vous pouvez vous connecter sous le nom d'un autre utilisateur en utilisant la touche show_route.py -u getpass.getpass prend le mot de passe de stdin afin que le mot de passe ne reste pas dans le système. Pour vous connecter à l'équipement, vous devrez également saisir son nom d'hôte ou son adresse IP lorsque vous y êtes invité. Toutes les données nécessaires à l'autorisation sur l'appareil ont été reçues.

Junos PyEZ prend en charge la connexion à un équipement exécutant Junos OS à l'aide de la console, telnet ou netconf via ssh. L'article traite de cette dernière option.

Pour vous connecter à un équipement, utilisez la classe Device du module jnpr.junos

with jnpr.junos.Device(host=router,
                           user=args.name,
                           passwd=password) as dev:

Une demande est effectuée pour toutes les routes connues du routeur via un appel de procédure à distance ou un appel de procédure à distance, selon ce qui convient le mieux.

data = dev.rpc.get_route_information()

Commande similaire sur Junos OS

user@router> show route | display xml

En ajoutant rpc à la fin de la commande, nous obtenons une balise de requête et pouvons la faire correspondre avec le nom de la méthode RPC, de cette manière nous pouvons découvrir d'autres noms intéressants. Il convient de noter que la syntaxe d'écriture de la balise de requête est différente du nom de la méthode, à savoir que vous devez remplacer les traits d'union par des traits de soulignement.

user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")

Le reste de la partie a été enveloppé dans une boucle while, afin de ne pas répéter la demande au routeur s'il était nécessaire d'enregistrer un autre sous-réseau parmi ceux que le routeur connaît déjà. Il est à noter que le routeur sur lequel je fais la requête connaît les routes uniquement via OSPF, donc pour un routeur Edge, il est préférable de modifier un peu la requête pour réduire le temps d'exécution du script.

data = dev.rpc.get_ospf_route_information()

Regardons maintenant le contenu de la boucle while

Au début, il sera demandé à l'utilisateur de saisir un sous-réseau avec un masque et pas plus de trois octets du réseau du même sous-réseau, cela est nécessaire pour définir la plage de recherche. Je n'aime pas vraiment cette implémentation consistant à spécifier les critères et la plage de recherche, mais jusqu'à présent, je n'ai pas trouvé de meilleure solution. Ensuite, à partir de la liste de sous-réseaux résultante, route_list, à l'aide d'une variable ne contenant pas plus de trois octets, je sélectionne les sous-réseaux qui m'intéressent.

tmp = re.search(r'^%sS*' % subnet_search, route_list[i])

Grâce à IPNetwork, le module netaddr, je reçois les sous-réseaux sous forme de liste d'adresses ipv4

range_subnet = netaddr.IPNetwork(tmp.group(0))

En utilisant IPNetwork, j'obtiens une plage d'adresses d'un réseau saisi par l'utilisateur avec un masque et je génère une liste de toutes les adresses de cette plage pour comparaison avec la liste des adresses occupées.

for i in set(net_list).difference(set(busyip)):
        freeip.append(i)

J'affiche la liste résultante des adresses libres sous forme de sous-réseaux

print(netaddr.IPSet(freeip))

Ci-dessous le script complet, testé sur des switchs utilisés comme routeur, modèles ex4550, ex4600


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import getpass
import netaddr
import re
import sys

import jnpr.junos

parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user',
                    action='store',
                    dest='name',
                    help='Enter login from tacacs if it differs from the '
                         'username in the system.')
args = parser.parse_args()

if not args.name:
    args.name = getpass.getuser()    # Return the “login name” of the user.
router = input("Full routers name: ")
password = getpass.getpass("Password: ")

try:
    # Authenticates to a device running Junos, for get information about routs
    # into xml format and selects by tag.
    route_list = []
    with jnpr.junos.Device(host=router,
                           user=args.name,
                           passwd=password) as dev:
        data = dev.rpc.get_route_information()
    route_list = data.xpath("//rt-destination/text()")
except (jnpr.junos.exception.ConnectRefusedError,
        jnpr.junos.exception.ConnectUnknownHostError) as err:
    print("Equipment name or password wrong.")
    sys.exit(1)

while True:
    subnet = input("Net with mask: ")
    subnet_search = input("Input no more three octet: ")
    # Gets a list of busy IP addresses from the received subnets.
    busyip = []
    for i in range(len(route_list)):
        tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
        if tmp:
            range_subnet = netaddr.IPNetwork(tmp.group(0))
            for ip in range_subnet:
                busyip.append("%s" % ip)
    range_subnet = netaddr.IPNetwork(subnet)
    # Gets list ip adresses from subnetworks lists.
    net_list = []
    for ip in range_subnet:
        net_list.append("%s" % ip)
    # Сomparing lists.
    freeip = []
    for i in set(net_list).difference(set(busyip)):
        freeip.append(i)
    print(netaddr.IPSet(freeip))

    request = input("To run request again enter yes or y, "
                    "press 'enter', complete request: ")
    if request in ("yes", "y"):
        continue
    else:
        print('Bye')
        break

Source: habr.com

Ajouter un commentaire