Junos PyEZ usando o exemplo da tarefa de buscar subredes ipv4 gratuítas

Un artigo sobre o traballo con Junos PyEZ: "microframework de Python que che permite xestionar e automatizar dispositivos que executan Junos OS", automatización e xestión, todo o que nos encanta. Escribir o script descrito neste artigo tiña varios obxectivos: aprender Python e automatizar tarefas para recoller información ou cambiar as configuracións dos equipos que executaban Junos OS. A elección desta combinación específica de Python + Junos PyEZ realizouse debido á baixa barreira de entrada á linguaxe de programación Python e á facilidade de uso da biblioteca Junos PyEZ, que non require coñecementos expertos sobre Junos OS.

Tarefa

Auditoría de subredes ipv4 gratuítas pertencentes á empresa. O criterio de que unha subrede sexa gratuíta é a ausencia dunha entrada sobre ela nas rutas do switch que actúa como un enrutador que executa Junos OS.

Implantación

Python + Junos PyEZ, aínda que houbo a tentación de facelo a través de paramiko e ssh.exec_command, Como resultado, terá que configurar o protocolo de xestión de rede do dispositivo netconf no equipo que se está a sondear. Netconf traballa con hardware a través da chamada de procedemento remoto RPC e usa XML, neste exemplo, para proporcionar a información que recibe.

A instalación da versión actual de Junos PyEZ desde PyPI faise co seguinte comando:

$ pip install junos-eznc

Tamén podes instalar desde a rama principal do proxecto en GitHub co seguinte comando:

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

E unha opción máis vía

$ pip install -r requirements.txt 

Este comando instalará as bibliotecas que faltan no sistema e son necesarias para o seu funcionamento. Na miña versión requisitos.txt Só hai dous deles, as últimas versións están indicadas no momento de escribir o guión:

junos-eznc
netaddr

Por defecto, o script toma o nome do usuario actual no sistema; pode iniciar sesión co nome doutro usuario usando a chave show_route.py -u getpass.getpass acepta o contrasinal de stdin polo que o contrasinal non permanecer no sistema. Para conectarse ao equipo, tamén terá que introducir o seu nome de host ou enderezo IP cando se lle solicite. Recibíronse todos os datos necesarios para a autorización no dispositivo.

Junos PyEZ admite a conexión a equipos que executan Junos OS mediante a consola, telnet ou netconf a través de ssh. O artigo discute esta última opción.

Para conectarse ao equipo, use a clase Dispositivo do módulo jnpr.junos

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

Realízase unha solicitude para todas as rutas coñecidas polo enrutador mediante chamada de procedemento remoto ou chamada de procedemento remoto, o que resulte máis conveniente.

data = dev.rpc.get_route_information()

Comando similar en Junos OS

user@router> show route | display xml

Engadindo rpc ao final do comando, obtemos unha etiqueta de solicitude e podemos asociala co nome do método RPC, deste xeito podemos descubrir outros nomes de interese. Paga a pena notar que a sintaxe para escribir a etiqueta de solicitude é diferente do nome do método, é dicir, debería substituír os guións por guións baixos.

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

O resto da parte envolveuse nun bucle while, para non repetir a solicitude ao router se fose necesario comprobar noutra subrede das que o router xa coñece. Cómpre mencionar que o enrutador no que fago a solicitude coñece rutas só a través de OSPF, polo que para un enrutador de borde é mellor cambiar un pouco a solicitude para reducir o tempo de execución do script.

data = dev.rpc.get_ospf_route_information()

Agora vexamos o contido do bucle while

Ao principio, pediráselle ao usuario que introduza unha subrede cunha máscara e non máis de tres octetos da rede da mesma subrede, isto é necesario para establecer o rango de busca. Non me gusta moito esta implementación de especificar os criterios e o intervalo de busca, pero ata agora non atopei unha solución mellor. A continuación, a partir da lista resultante de subredes route_list, usando unha variable que non conteña máis de tres octetos, selecciono as subredes que me interesan

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

A través de IPNetwork, o módulo netaddr, recibo subredes en forma de lista de enderezos ipv4

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

Usando IPNetwork, obteño un rango de enderezos dunha rede introducida polo usuario cunha máscara e xero unha lista de todos os enderezos deste rango para comparalos coa lista de enderezos ocupados.

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

Amoso ​​a lista resultante de enderezos libres en forma de subredes

print(netaddr.IPSet(freeip))

Abaixo está o script completo, probado en interruptores usados ​​como enrutador, modelos 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: www.habr.com

Engadir un comentario