Junos PyEZ am Beispiel einer Aufgabe zur Suche nach freien IPv4-Subnetzen.

Artikel über die Arbeit mit Junos PyEZ – "Python-Mikroframework, das es Ihnen ermöglicht, Geräte mit Junos OS zu verwalten und zu automatisieren" – Automatisierung und Verwaltung, genau wie wir es mögen. Das Schreiben des in diesem Artikel beschriebenen Skripts verfolgte mehrere Ziele – das Erlernen von Python und die Automatisierung von Aufgaben zur Informationssammlung oder zur Änderung der Konfiguration auf Geräten, die von Junos OS betrieben werden. Die Wahl dieser Kombination aus Python + Junos PyEZ wurde aufgrund der niedrigen Einstiegshürde in die Programmiersprache Python und der Benutzerfreundlichkeit der Bibliothek Junos PyEZ getroffen, die keine Expertenkenntnisse in Junos OS erfordert.

Ziel

Überprüfung freier IPv4-Subnetze, die dem Unternehmen gehören. Das Kriterium dafür, dass ein Subnetz frei ist, ist das Fehlen eines Eintrags dazu in den Routen auf dem Switch, der als Router unter Junos OS fungiert.

Implementierung

Python + Junos PyEZ, obwohl die Versuchung bestand, es über paramiko und ssh.exec_command zu machen, wird es notwendig sein, auf dem abgefragten Gerät das Netzwerkmanagementprotokoll netconf einzurichten. Netconf arbeitet mit der Hardware über Remote Procedure Call (RPC) und verwendet XML, um im betrachteten Beispiel die erhaltenen Informationen bereitzustellen.

Installation der aktuellen Version von Junos PyEZ aus PyPI erfolgt mit dem folgenden Befehl:

$ pip install junos-eznc

Die Installation kann auch aus dem Hauptzweig des Projekts auf GitHub mit folgendem Befehl erfolgen:

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

Eine weitere Möglichkeit ist über

$ pip install -r requirements.txt 

Dieser Befehl installiert alle fehlenden Bibliotheken, die für den Betrieb erforderlich sind. In meiner Version requirements.txt gibt es insgesamt zwei, die aktuellen Versionen sind zum Zeitpunkt der Erstellung des Skripts angegeben:

junos-eznc
netaddr

Das Skript verwendet standardmäßig den Namen des aktuellen Benutzers im System. Um sich unter einem anderen Benutzernamen anzumelden, kann der Schlüssel show_route.py -u verwendet werden; getpass.getpass nimmt das Passwort von stdin entgegen, sodass das Passwort im System nicht verbleibt. Um sich mit der Hardware zu verbinden, müssen außerdem der Hostname oder die IP-Adresse eingegeben werden, wenn danach gefragt wird. Alle erforderlichen Daten für die Authentifizierung am Gerät sind erhalten.

Junos PyEZ unterstützt die Verbindung zu Geräten, die mit Junos OS betrieben werden, über die Konsole, Telnet oder NETCONF über SSH. In diesem Artikel wird die letzte Variante betrachtet.

Für die Verbindung zur Hardware wird die Klasse Device des Moduls jnpr.junos verwendet.

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

Es wird eine Anfrage zu allen bekannten Routen des Routers über einen Remote Procedure Call durchgeführt, je nach Vorliebe entweder als Prozeduraufruf oder Remote Procedure Call.

data = dev.rpc.get_route_information()

Der entsprechende Befehl auf Junos OS

user@router> show route | display xml

Indem wir am Ende des Befehls rpc hinzufügen, erhalten wir das Anfrage-Tag und können es mit dem Namen der RPC-Methode abgleichen. Auf diese Weise können wir auch andere interessante Namen herausfinden. Zu beachten ist, dass die Schreibweise des Anfrage-Tags von dem Namen der Methode abweicht; die Bindestriche müssen durch Unterstriche ersetzt werden.

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

Den Rest habe ich in eine while-Schleife gepackt, um die Anfrage an den Router nicht erneut durchzuführen, falls ich in einem anderen Subnetz prüfen möchte, von den Informationen, die der Router bereits kennt. Es ist erwähnenswert, dass der Router, auf den ich zugreife, nur Routen über OSPF kennt, daher wäre es besser, die Anfrage für den Border Router leicht zu ändern, um die Laufzeit des Skripts zu verkürzen.

data = dev.rpc.get_ospf_route_information()

Jetzt schauen wir uns den Inhalt der while-Schleife an.

Zunächst wird der Benutzer aufgefordert, ein Subnetz mit einer Maske und nicht mehr als drei Oktetten aus dem Bereich dieses Subnetzes einzugeben, um den Suchbereich festzulegen. Ich bin mit dieser Umsetzung der Kriterien- und Suchbereichsdefinition nicht ganz zufrieden, aber bis jetzt habe ich keine bessere Lösung gefunden. Anschließend wähle ich aus der erhaltenen Liste von Subnetzen `route_list` die für mich interessierenden Subnetze aus, wobei ich die Variable mit nicht mehr als drei Oktetten verwende.

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

Über `IPNetwork` aus dem Modul `netaddr` erhalte ich die Subnetze in Form einer Liste von IPv4-Adressen.

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

Mit `IPNetwork` aus dem vom Benutzer eingegebenen Netzwerk mit Maske erhalte ich den Bereich der Adressen und erstelle eine Liste aller Adressen aus diesem Bereich, um sie mit der Liste der belegten Adressen zu vergleichen.

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

Die erhaltene Liste der freien Adressen gebe ich in Form von Subnetzen aus.

print(netaddr.IPSet(freeip))

Hier ist das vollständige Skript, das auf Switches getestet wurde, die als Router verwendet werden, Modelle ex4550 und 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

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster