Un articulu nantu à u travagliu cù Junos PyEZ - "Microframework Python chì vi permette di gestisce è automatizà i dispositi chì eseguenu Junos OS" automatizazione è gestione, tuttu ciò chì amemu. A scrittura di u script descrittu in questu articulu hà avutu parechji scopi - imparà Python è automatizà i travaglii per a cullizzioni d'infurmazioni o cambià a cunfigurazione nantu à l'equipaggiu chì esegue Junos OS. L'scelta di sta cumminazione specifica di Python + Junos PyEZ hè stata fatta per via di a bassa barriera per l'ingressu à a lingua di prugrammazione Python è a facilità d'utilizazione di a biblioteca Junos PyEZ, chì ùn hà micca bisognu di cunniscenze esperte di Junos OS.
Objettivu
Audit of free ipv4 subnets appartenenti à a cumpagnia. U criteriu chì una subnet hè libera hè l'absenza di una entrata nantu à questu in e rotte nantu à u switch chì agisce cum'è un router chì esegue Junos OS.
Реализация
Python + Junos PyEZ, ancu s'ellu ci era una tentazione di fà per mezu di paramiko è ssh.exec_command,
L'installazione di a versione attuale di Junos PyEZ da PyPI hè fatta cù u cumandimu seguente:
$ pip install junos-eznc
Pudete ancu installà da u ramu principale di u prugettu in GitHub cù u cumandimu seguente:
$ pip install git+https://github.com/Juniper/py-junos-eznc.git
È una altra opzione via
$ pip install -r requirements.txt
Questu cumandimu installerà e librerie chì mancanu da u sistema è sò necessarii per u funziunamentu. In a mo versione esigenze.txt Ci sò solu dui, l'ultime versioni sò indicati à u mumentu di a scrittura di u script:
junos-eznc
netaddr
U script per difettu piglia u nome di l'utilizatore attuale in u sistema, pudete log in sottu u nome di un altru utilizatore utilizendu a chjave show_route.py -u getpass.getpass piglia a password da stdin perchè a password ùn resta micca. in u sistema. Per cunnette à l'equipaggiu, avete ancu bisognu di inserisce u so hostname o l'indirizzu IP quandu vi dumanda. Tutti i dati necessarii per l'autorizazione in u dispusitivu sò stati ricevuti.
Junos PyEZ supporta a cunnessione à l'equipaggiu chì esegue Junos OS utilizendu a cunsola, telnet o netconf via ssh. L'articulu discute l'ultima opzione.
Per cunnette à l'equipaggiu, utilizate a classa Dispositivu di u modulu jnpr.junos
with jnpr.junos.Device(host=router,
user=args.name,
passwd=password) as dev:
Una dumanda hè fatta per tutte e rotte cunnisciute da u router via una chjama di procedura remota o una chjama di procedura remota, quale hè più cunvene.
data = dev.rpc.get_route_information()
Cumandante simile in Junos OS
user@router> show route | display xml
Agghiuncennu rpc à a fine di u cumandamentu, avemu un tag di dumanda è ponu currisponde à u nome di u metudu RPC, in questu modu pudemu truvà altri nomi d'interessu. Hè nutate chì a sintassi per scrive l'etiqueta di dumanda hè sfarente di u nome di u metudu, vale à dì, duvete rimpiazzà i trattini cù underscore.
user@router> show route | display xml rpc
<rpc-reply >route_list = data.xpath("//rt-destination/text()")
U restu di a parte hè stata impannillata in un ciclu di tempu, per ùn ripetiri a dumanda à u router s'ellu era necessariu di verificà in una altra subnet da quelli chì u router hà digià cunnisciutu. Hè vale à dì chì u router nantu à quale aghju fattu a dumanda cunnosce e rotte solu per OSPF, cusì per un router di punta hè megliu cambià a dumanda un pocu per riduce u tempu di esecuzione di u script.
data = dev.rpc.get_ospf_route_information()
Avà fighjemu u cuntenutu di u ciclu while
À u principiu, l'utilizatore serà dumandatu à entre in una subnet cù una maschera è micca più di trè otteti da a reta di a listessa subnet, questu hè necessariu di stabilisce a gamma di ricerca. Ùn mi piace micca veramente sta implementazione di specificà i criterii è a gamma di ricerca, ma finu à avà ùn aghju micca truvatu una suluzione megliu. In seguitu, da a lista resultanti di subnets route_list, utilizendu una variàbile chì ùn cuntene micca più di trè ottetti, selezziunate i subnets chì m'interessanu.
tmp = re.search(r'^%sS*' % subnet_search, route_list[i])
Per mezu di IPNetwork, u modulu netaddr, riceve subnets in forma di una lista di indirizzi ipv4
range_subnet = netaddr.IPNetwork(tmp.group(0))
Utilizendu IPNetwork, aghju ottene una gamma di indirizzi da una reta di l'utilizatori cù una maschera è generà una lista di tutti l'indirizzi da questa gamma per paragunà cù a lista di l'indirizzi occupati.
for i in set(net_list).difference(set(busyip)):
freeip.append(i)
Puderaghju a lista resultanti di indirizzi gratuiti in forma di subnets
print(netaddr.IPSet(freeip))
Quì sottu hè u script cumpletu, pruvatu nantu à i switches utilizati cum'è router, mudelli 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: www.habr.com