Junos PyEZ na príklade úlohy vyhľadávania voľných podsietí ipv4

Článok o práci s Junos PyEZ – „Mikrorámec Pythonu, ktorý vám umožňuje spravovať a automatizovať zariadenia so systémom Junos OS“, automatizáciu a správu, všetko, čo máme radi. Napísanie skriptu opísaného v tomto článku malo niekoľko cieľov – naučiť sa Python a automatizovať úlohy na zhromažďovanie informácií alebo zmenu konfigurácií na zariadeniach so systémom Junos OS. Voľba tejto špecifickej kombinácie Python + Junos PyEZ bola urobená z dôvodu nízkej bariéry vstupu do programovacieho jazyka Python a jednoduchosti používania knižnice Junos PyEZ, ktorá nevyžaduje odborné znalosti Junos OS.

Úloha

Audit bezplatných podsietí ipv4 patriacich spoločnosti. Kritériom, že podsieť je voľná, je absencia záznamu o nej v trasách na prepínači, ktorý funguje ako smerovač so systémom Junos OS.

Реализация

Python + Junos PyEZ, aj keď tu bolo pokušenie urobiť to cez paramiko a ssh.exec_command, V dôsledku toho budete musieť nakonfigurovať protokol správy siete zariadenia netconf na zariadení, ktoré je predmetom dopytu. Netconf pracuje s hardvérom prostredníctvom vzdialeného volania procedúr RPC a v tomto príklade používa XML na poskytovanie informácií, ktoré prijíma.

Inštalácia aktuálnej verzie Junos PyEZ z PyPI sa vykonáva pomocou nasledujúceho príkazu:

$ pip install junos-eznc

Môžete tiež nainštalovať z hlavnej vetvy projektu na GitHub pomocou nasledujúceho príkazu:

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

A ešte jedna možnosť cez

$ pip install -r requirements.txt 

Tento príkaz nainštaluje knižnice, ktoré v systéme chýbajú a sú potrebné na prevádzku. V mojej verzii request.txt Existujú iba dve z nich, najnovšie verzie sú uvedené v čase písania skriptu:

junos-eznc
netaddr

Skript štandardne preberá meno aktuálneho používateľa v systéme, pomocou klávesu show_route.py -u sa môžete prihlásiť pod menom iného používateľa getpass.getpass preberá heslo z stdin, takže heslo nezostane v systéme. Ak sa chcete pripojiť k zariadeniu, po zobrazení výzvy budete musieť zadať aj názov hostiteľa alebo adresu IP. Všetky údaje potrebné na autorizáciu na zariadení boli prijaté.

Junos PyEZ podporuje pripojenie k zariadeniu so systémom Junos OS pomocou konzoly, telnetu alebo netconf cez ssh. Článok sa zaoberá druhou možnosťou.

Na pripojenie k zariadeniu použite triedu Device modulu jnpr.junos

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

Požiadavka sa odošle pre všetky trasy známe smerovaču prostredníctvom vzdialeného volania procedúry alebo vzdialeného volania procedúry, podľa toho, čo je pohodlnejšie.

data = dev.rpc.get_route_information()

Podobný príkaz na Junos OS

user@router> show route | display xml

Pridaním rpc na koniec príkazu získame značku request a môžeme ju spárovať s názvom metódy RPC, týmto spôsobom môžeme zistiť ďalšie zaujímavé mená. Stojí za zmienku, že syntax na písanie značky požiadavky sa líši od názvu metódy, konkrétne by ste mali nahradiť spojovníky podčiarkovníkmi.

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

Zvyšok časti bol zabalený do while slučky, aby sa neopakovala požiadavka smerovaču, ak by bolo potrebné skontrolovať inú podsieť z tých, o ktorých už router vie. Stojí za zmienku, že smerovač, na ktorom robím požiadavku, pozná trasy iba cez OSPF, takže pre okrajový smerovač je lepšie požiadavku trochu zmeniť, aby sa skrátil čas spustenia skriptu

data = dev.rpc.get_ospf_route_information()

Teraz sa pozrime na obsah cyklu while

Na začiatku bude používateľ vyzvaný, aby zadal podsieť s maskou a nie viac ako tri oktety zo siete rovnakej podsiete, je potrebné nastaviť rozsah vyhľadávania. Táto implementácia špecifikovania kritérií a rozsahu vyhľadávania sa mi veľmi nepáči, ale zatiaľ som nenašiel lepšie riešenie. Ďalej z výsledného zoznamu podsietí route_list pomocou premennej, ktorá neobsahuje viac ako tri oktety, vyberiem podsiete, ktoré ma zaujímajú

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

Prostredníctvom IPNetwork, modulu netaddr, dostávam podsiete vo forme zoznamu adries ipv4

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

Pomocou IPNetwork získam rozsah adries z užívateľom zadanej siete s maskou a vygenerujem zoznam všetkých adries z tohto rozsahu pre porovnanie so zoznamom obsadených adries.

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

Výsledný zoznam voľných adries zobrazím vo forme podsietí

print(netaddr.IPSet(freeip))

Nižšie je uvedený úplný skript, testovaný na prepínačoch používaných ako 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: hab.com

Pridať komentár