Junos PyEZ na příkladu úlohy hledání volných ipv4 podsítí

Článek o práci s Junos PyEZ – „Mikrorámec Pythonu, který vám umožňuje spravovat a automatizovat zařízení se systémem Junos OS“, automatizace a správa, vše, co máme rádi. Psaní skriptu popsaného v tomto článku mělo několik cílů – naučit se Python a automatizovat úlohy pro shromažďování informací nebo změnu konfigurací na zařízení s Junos OS. Volba této specifické kombinace Python + Junos PyEZ byla provedena z důvodu nízké bariéry vstupu do programovacího jazyka Python a snadného použití knihovny Junos PyEZ, která nevyžaduje odborné znalosti Junos OS.

Úkol

Audit bezplatných podsítí ipv4 patřících společnosti. Kritériem, že podsíť je volná, je absence záznamu o ní v trasách na přepínači fungujícím jako router s Junos OS.

uskutečnění

Python + Junos PyEZ, i když bylo pokušení to udělat přes paramiko a ssh.exec_command, V důsledku toho budete muset nakonfigurovat protokol správy sítě zařízení netconf na dotazovaném zařízení. Netconf pracuje s hardwarem prostřednictvím vzdáleného volání procedur RPC a v tomto příkladu používá XML k poskytování informací, které přijímá.

Instalace aktuální verze Junos PyEZ z PyPI se provádí pomocí následujícího příkazu:

$ pip install junos-eznc

Můžete také nainstalovat z hlavní větve projektu na GitHubu pomocí následujícího příkazu:

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

A ještě jedna možnost přes

$ pip install -r requirements.txt 

Tento příkaz nainstaluje knihovny, které v systému chybí a jsou nezbytné pro provoz. V mé verzi požadavky.txt Existují pouze dvě z nich, nejnovější verze jsou uvedeny v době psaní skriptu:

junos-eznc
netaddr

Ve výchozím nastavení skript přebírá jméno aktuálního uživatele v systému, můžete se přihlásit pod jménem jiného uživatele pomocí klíče show_route.py -u getpass.getpass přebírá heslo ze stdin, takže heslo nezůstane v systému. Chcete-li se připojit k zařízení, budete také muset na výzvu zadat název hostitele nebo adresu IP. Všechna data potřebná pro autorizaci na zařízení byla přijata.

Junos PyEZ podporuje připojení k zařízení se systémem Junos OS pomocí konzole, telnetu nebo netconf přes ssh. Článek pojednává o poslední možnosti.

Pro připojení k zařízení použijte třídu Device modulu jnpr.junos

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

Požadavek je proveden pro všechny cesty známé routeru prostřednictvím vzdáleného volání procedury nebo vzdáleného volání procedury, podle toho, co je pohodlnější.

data = dev.rpc.get_route_information()

Podobný příkaz na Junos OS

user@router> show route | display xml

Přidáním rpc na konec příkazu získáme značku požadavku a můžeme ji porovnat s názvem metody RPC, tímto způsobem můžeme zjistit další zajímavá jména. Stojí za zmínku, že syntaxe pro zápis tagu požadavku se liší od názvu metody, konkrétně byste měli nahradit pomlčky podtržítky.

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

Zbytek části byl zabalen do while smyčky, aby se neopakoval požadavek na router, pokud by bylo potřeba odbavit jinou podsíť z těch, o kterých router už ví. Za zmínku stojí, že router, na kterém zadávám požadavek, zná trasy pouze přes OSPF, takže u okrajového routeru je lepší požadavek trochu změnit, aby se zkrátila doba běhu skriptu

data = dev.rpc.get_ospf_route_information()

Nyní se podíváme na obsah cyklu while

Na začátku bude uživatel požádán o zadání podsítě s maskou a maximálně třemi oktety ze sítě stejné podsítě, to je nutné pro nastavení rozsahu vyhledávání. Tato implementace specifikace kritérií a rozsahu vyhledávání se mi moc nelíbí, ale zatím jsem nenašel lepší řešení. Dále z výsledného seznamu podsítí route_list pomocí proměnné obsahující ne více než tři oktety vyberu podsítě, které mě zajímají

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

Prostřednictvím IPNetwork, modulu netaddr, dostávám podsítě ve formě seznamu adres ipv4

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

Pomocí IPNetwork získám rozsah adres z uživatelem zadané sítě s maskou a vygeneruji seznam všech adres z tohoto rozsahu pro porovnání se seznamem obsazených adres.

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

Výsledný seznam volných adres zobrazím ve formě podsítí

print(netaddr.IPSet(freeip))

Níže je kompletní skript, testovaný na přepínačích používaných jako router, modely 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

Zdroj: www.habr.com

Přidat komentář