Junos PyEZ attraverso un esempio di ricerca di subnet ipv4 disponibili

Articolo su come lavorare con Junos PyEZ — “microframework Python che consente di gestire e automatizzare i dispositivi che eseguono Junos OS” automatizzazione e gestione, tutto ciò che amiamo. Scrivere lo script descritto in questo articolo ha avuto diversi obiettivi: apprendere Python e automatizzare compiti di raccolta informazioni o modifica della configurazione su dispositivi che eseguono Junos OS. La scelta di questa combinazione Python + Junos PyEZ è stata fatta per la sua bassa barriera all'ingresso nel linguaggio di programmazione Python e la semplicità d'uso della libreria Junos PyEZ, che non richiede conoscenze esperte di Junos OS.

Compito

Audit delle subnet ipv4 libere appartenenti all'azienda. Il criterio per cui una subnet è considerata libera è l'assenza di voci su di essa nelle rotte sullo switch che svolge il ruolo di router eseguendo Junos OS.

Implementazione

Python + Junos PyEZ, anche se c'era la tentazione di farlo tramite paramiko e ssh.exec_command, di conseguenza sarà necessario configurare il protocollo di gestione dei dispositivi di rete netconf sul dispositivo interrogato. Netconf comunica con il dispositivo tramite chiamate di procedura remota (RPC) e utilizza XML, nell'esempio considerato, per fornire le informazioni ricevute.

L'installazione della versione attuale di Junos PyEZ da PyPI si esegue con il seguente comando:

$ pip install junos-eznc

Puoi installarlo anche dalla principale branch del progetto su GitHub con il seguente comando:

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

E un'altra opzione tramite

$ pip install -r requirements.txt 

questo comando installerà le librerie mancanti necessarie per il funzionamento. Nella mia versione requirements.txt ce ne sono solo due, le versioni indicate sono le più recenti al momento della scrittura dello script:

junos-eznc
netaddr

Per impostazione predefinita, lo script prende il nome dell'utente attualmente connesso al sistema, per accedere con un altro nome utente puoi usare la chiave show_route.py -u getpass.getpass prende la password da stdin in modo che la password non rimanga nel sistema. Per connettersi al dispositivo sarà anche necessario inserire su richiesta il suo hostname o indirizzo IP. Tutti i dati necessari per l'autenticazione sul dispositivo sono stati ottenuti.

Junos PyEZ supporta la connessione al dispositivo in esecuzione Junos OS utilizzando console, telnet o netconf tramite ssh. In questo articolo consideriamo l'ultima opzione.

Per connettersi al dispositivo si utilizza la classe Device del modulo jnpr.junos

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

Si richiede informazioni su tutte le rotte conosciute dal router tramite chiamate di procedura remota o invio di chiamate remote, chiunque si senta a proprio agio.

data = dev.rpc.get_route_information()

Comando equivalente su Junos OS

user@router> show route | display xml

Aggiungendo all'ultimo comando rpc, otterremo il tag di richiesta e possiamo confrontarlo con il nome del metodo RPC, in questo modo possiamo scoprire anche altri nomi di nostro interesse. È importante notare che la sintassi del tag di richiesta è diversa dal nome del metodo, sostituendo i trattini con gli underscore.

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

Ho avvolto il resto in un ciclo while, in modo da non eseguire nuovamente la richiesta al router se devo controllare in un'altra subnet tra quelle che il router già conosce. Vale la pena menzionare che il router sul quale sto richiedendo conosce i percorsi solo tramite OSPF, quindi per il router di confine sarebbe meglio modificare leggermente la richiesta, per ridurre i tempi di esecuzione dello script

data = dev.rpc.get_ospf_route_information()

Adesso diamo un'occhiata al contenuto del ciclo while

All'inizio all'utente verrà chiesto di inserire la subnet con la maschera e non più di tre ottetti da questa stessa subnet, necessario per impostare l'intervallo di ricerca. Non mi piace molto questa realizzazione del criterio e dell'intervallo di ricerca, ma finora non ho trovato soluzioni migliori. Successivamente, dalla lista delle subnet route_list utilizzo la variabile contenente non più di tre ottetti per selezionare le subnet di mio interesse

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

Tramite IPNetwork, del modulo netaddr, ottengo le subnet come lista di indirizzi ipv4

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

Utilizzando IPNetwork dalla rete inserita dall'utente con maschera ottengo l'intervallo di indirizzi e formo una lista di tutti gli indirizzi di questo intervallo per confrontarli con l'elenco degli indirizzi occupati.

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

La lista di indirizzi liberi ottenuta viene presentata in forma di subnet

print(netaddr.IPSet(freeip))

Di seguito viene riportato lo script completo, testato su switch utilizzati come router, modelli 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

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster