Korzystając ze strony, wyrażasz zgodę na używanie ciasteczek zgodnie z naszą Polityką prywatności i Warunkami użytkowania.
Zgadzam się
Na Styku SieciNa Styku Sieci
  • Start
  • Routing & Switching
  • Wireless
  • Certyfikacja
  • Wokół sieci
Czytasz: Pierwsze kroki w automatyzacji sieci – Python i pexpect()
Udostępnij
Na Styku SieciNa Styku Sieci
  • Wireless
  • Certyfikacja
  • Routing & Switching
  • Wokół sieci
Szukaj
  • Start
  • Categories
    • Wokół sieci
    • Routing & Switching
    • Wireless
    • Certyfikacja
  • Bookmarks
  • More Foxiz
    • Blog Index
    • Sitemap
Have an existing account? Zaloguj się
Follow US
Routing & Switching

Pierwsze kroki w automatyzacji sieci – Python i pexpect()

Damian Michalak
Damian Michalak 10 grudnia 2018 Komentarze: 9

W poprzednim artykule przybliżyłem wszystkie elementy, które w mojej opinii są potrzebne do zbudowania pełnego zestawu umiejętności NetDevOps’a. Czas przyjrzeć się bliżej poszczególnym technologiom wylistowanym we wspomnianym materiale. W dzisiejszym artykule porozmawiamy o Pythonie oraz przedstawię Ci pierwszy prosty skrypt, który będziesz w stanie wykorzystać w swojej sieci w ciągu zaledwie kilku minut. Zaczynajmy!

W artykule:
👉 Po co w sumie ten Python?👉 Jak się nauczyć Pythona?👉 Czas na pierwszy skrypt – use-case👉 Pisanie skryptu👉 Analiza kodu

👉 Po co w sumie ten Python?

Na wstępie wyjaśnijmy sobie jedną kluczową kwestię – aby być dobrym w automatyzowaniu swojej pracy jako sieciowiec musisz się nauczyć programować chociażby w podstawowym stopniu. Ale nie znaczy to, że koniecznie musisz programować w Pythonie! Jeżeli znasz już jakiś inny język programowania, którego użytkowanie sprawia Ci przyjemność to mam dla Ciebie dobrą wiadomość – istnieje spora szansa, że z powodzeniem będziesz w stanie go wykorzystać do automatyzowania sieci. 

Dlaczego jednak większość sieciowców ma takie ciśnienie na programowanie właśnie w Pythonie? Powody są dwa:

  • Python jest bardzo prostym składniowo językiem i wyróżnia się dobrą czytelnością kodu, co ma duże znaczenie podczas korzystania ze skryptów autorstwa innych osób. Analiza kodu napisanego w C++ przez nieznajomą nam osobę może zająć sporo czasu (zakładając brak komentarzy w kodzie). Python dzięki swojej czytelności trochę nam ułatwia w takich przypadkach zrozumienie kodu,
  • Python jest już z nami dość długo i powstała do niego ogromna liczba zewnętrznych bibliotek, które dają nam do dyspozycji wiele użytecznych funkcji. Sprawia to, że bardzo często kod potrzebny do wykonania pewnego zadania na danym urządzeniu sieciowym już istnieje. Daje to nam przede wszystkim oszczędność czasu i umożliwia korzystanie z już zoptymalizowanych pod kątem działania funkcji. Wiele najlepszych bibliotek do programowania sieciowego jest dostępne właśnie w Pythonie.

Ponadto, jak słusznie zauważył Rafał w komentarzach pod artykułem, kod Pythona jest wykonywany przez interpreter co powoduje, że działa on niezależnie od systemu operacyjnego (nie musi być ponadto kompilowany, w przeciwieństwie do np. C++). W dodatku fakt, że kod jest zapisywany w plikach tekstowych ułatwia jego przenoszenie i późniejszą edycję. 

No dobra, czyli już wiemy, że uczenie się Pythona to nie jakieś tam “widzimisię”. Ale jak się nauczyć Pythona?

Powiązane publikacje

Maszyna stanowa OSPF
Redystrybucja między OSPF a EIGRP [WYZWANIE]
Czym się różnią switche L3 od routerów?
Czym są tunele VPN?
CDP – młotek w skrzynce narzędziowej sieciowca

👉 Jak się nauczyć Pythona?

Od razu przyznaję bez bicia, że nie jestem ekspertem w dziedzinie programowania. Idąc na studia informatyczne miałem intencję zostania programistą, ale życie potoczyło się inaczej (jeśli jesteś ciekawy jak, to opisałem to w osobnym artykule). Zostałem sieciowcem, ale podstawowe umiejętności programistyczne w C++ gdzieś się ostały, co zdecydowanie ułatwia mi naukę pisania w Pythonie. Najważniejsze to zdawać sobie sprawę z tego, że nie musisz być programistyczną Alfą i Omegą. Według mnie wystarczy sam zapał do nauki, umiejętność analitycznego myślenia i doświadczenie w obsługiwaniu Google’a. Ale oczywiście doświadczenie z programowaniem jest zawsze w cenie.

Cała wiedza, którą posiadam odnośnie programowania w Pythonie pochodzi z jednego kursu na Udemy (który mogę zdecydowanie polecić). Jeśli chciałbyś się mu przyjrzeć to do niego linkuję:

Kurs Udemy – Python 3 Network Programming

Poza samym kursem dużo się również idzie nauczyć samodzielnie analizująć znalezione w sieci skrypty. Nie wykluczam, że w przyszłości zgłębię bardziej Pythona i sięgnę po bardziej ustrukturyzowane źródła wiedzy (np. książki) ale póki co nie miałem takiej potrzeby. W tym miejscu mam do Ciebie prośbę – jeżeli znasz inne godne polecenia źródła dzięki którym dobrze się można nauczyć Pythona to podziel się swoją wiedzą w komentarzu pod artykułem. Ja i inni czytelnicy na pewno będą Ci wdzięczni 🙂 Z dodatkowych źródeł możesz zwrócić uwagę np na:

  • Codecamy – polecony przez Rafała Rudewicza
  • Książka “Python dla każdego. Podstawy programowania” – polecona przez Krzysztofa Mroczka

👉 Czas na pierwszy skrypt – use-case

Wiemy już po co nam Python i gdzie się go nauczyć. Przyjrzyjmy się zatem pierwszemu dość prostemu problemowi, który możemy dzięki Pythonowi rozwiązać.

Topologia, na której będzie oparty przykład wygląda następująco:

Sieć jest oczywiście celowo uproszczona żeby nie komplikować niepotrzebnie tematu. Mamy tu do czynienia z płaską siecią LAN spiętą pojedynczym przełącznikiem warstwy trzeciej. Do przełącznika mamy podłączony komputer Admina zaadresowany w dedykowanej sieci dla administratorów – 10.1.0.0/24. Ponadto jest podłączony jeden komputer recepcji zaadresowany w sieci dla użytkowników 10.2.0.0/24. W ostatniej, trzeciej sieci 10.3.0.0/24 mamy zaadresowany Linux Server, na którym będziemy programować, SMTP Server na potrzeby wysyłania maili oraz WLAN Controller (WLC), który zarządza Access Pointami w naszej przykładowej organizacji.

Problem jaki przed nami stoi jest następujący: firmie nie zależy na stworzeniu wyrafinowanego rozwiązania Guest WiFi (które notabene zostało opisane przez Łukasza w dedykowanym artykule). Zamiast tego sieć Wi-Fi dla gości jest zabezpieczona zwykłym 10-znakowym hasłem (czyli użyto zabezpieczenie L2 Security typu PSK – pre-shared key). Naszym przełożonym nie podoba się fakt, że hasło do naszej sieci dla gości bardzo szybko się rozchodzi na portalach war-driving’owych i do naszej sieci dla gości podłączają się ludzie wątpliwej reputacji. Dotychczas więc hasło zmieniano ręcznie co miesiąc za pośrednictwem GUI kontrolera WLC:

Zmiana PSK w ustawieniach SSID na WLC

Jest to oczywiście bardzo proste i mało czasochłonne zadanie, ale jednak… należy o nim co miesiąc pamiętać. Zadanie wręcz idealne do zautomatyzowania.

Dochodzimy tutaj do bardzo istotnego faktu – WLC Cisco 5508, które posiada firma nie posiada API, czyli interfejsu programistycznego, który pozwalałby nam na bardzo wygodną interakcję między skryptem a kontrolerem. Na API przyjdzie jeszcze naszej nauce czas. W naszym scenariuszu natomiast będziemy musieli zastosować znacznie bardziej “łopatologiczne” podejście (wymuszone właśnie brakiem API). Jak będzie miał działać skrypt?

Zadaniem skryptu będzie:

  • zestawienie sesji SSH z kontrolerem,
  • wygenerowanie w sposób losowy nowego hasła,
  • przesłanie do kontrolera komend, które zmienią dotychczasowe hasło sieci Guest Wi-Fi
  • wysłanie do recepcji maila z informacją o nowym haśle

Chcemy aby taki skrypt wykonywał się automatycznie pierwszego dnia każdego miesiąca w nocy, 5 minut po północy. Do roboty!

👉 Pisanie skryptu

Zaczynamy od przygotowania sobie środowiska. Z komputera Admina (10.1.0.10/24) logujemy się za pomocą SSH na nasz Linux Server, który będziemy wykorzystywali do dalszego skryptowania. Logowanie do serwera jest oczywiście należycie zabezpieczone, abyśmy tylko my mieli do niego dostęp.

1. Instalujemy Pythona (yum lub apt-get):

sudo apt-get install python3

2. Tworzymy i przechodzimy do katalogu roboczego dla skryptów:

mkdir /etc/scriptscd /etc/scripts

3. Tworzymy plik skryptu z rozszerzeniem .py, nadajemy mu uprawnienia, które pozwolą jedynie bieżącemu użytkownikowi na jakąkolwiek interakcję z tym plikiem i przechodzimy do edycji (używając nano, nie chcemy się już na wstępie zniechęcić więc unikamy edytora vi 😉 ):

touch guestpass.py
chmod 700 guestpass.py
nano guestpass.py

4. W pliku ze skryptem wklejamy poniższy kod. Podaję go w całości – jeśli chcesz się zapoznać z wyjaśnieniami poszczególnych elementów to opisuję je w dalszej części artykułu:

#!/usr/bin/env python3

import random
import os
import pexpect
import time
import sys
import socket
import subprocess

alphabet = "abcdefghjkmnpqrstuvwxyz"
upperalphabet = alphabet.upper()
pw_len = 10
pwlist = []

for i in range(pw_len//3):
    pwlist.append(alphabet[random.randrange(len(alphabet))])
    pwlist.append(upperalphabet[random.randrange(len(upperalphabet))])
    pwlist.append(str(random.randrange(10)))
for i in range(pw_len-len(pwlist)):
    pwlist.append(alphabet[random.randrange(len(alphabet))])

random.shuffle(pwlist)
pwstring = "".join(pwlist)

ssh = "ssh 10.3.0.33"
newpass = "config wlan security wpa akm psk set-key ascii " + pwstring + "2"

c1=pexpect.spawn(ssh)
c1.delaybeforesend = 2.0
c1.expect("User:")
c1.sendline("admin")
c1.expect("assword:")
c1.sendline("SuperSecureAdminPassword")
c1.expect(">")
c1.sendline("config wlan disable 2")
c1.expect(">")
c1.sendline(newpass)
c1.expect(">")
c1.sendline("config wlan enable 2")
c1.expect(">")
c1.sendline("logoutr")
c1.expect("(y/N)")
c1.sendline("yr")
c1.close()

text_file = open("CurrentGuestPass.txt", "w")
text_file.write("Hello. Please be informed that Guest Wi-Fi password for has changed. New password is: %snnPlease distribute the password to all whom it may concern and remember that in some cases the previous Wi-Fi connection profile must first be removed in order to get a prompt for a new password." % pwstring)
text_file.close()

os.system("mail -s 'IMPORTANT! Guest Wi-Fi password has changed!' reception@acme.com< /etc/scripts/CurrentGuestPass.txt")

👉 Analiza kodu

Przyjrzyjmy się teraz bliżej poszczególnym blokom kodu:

1. Kod zaczyna się od linijki, która wskazuje jakiego interpretera kodu chcemy użyć podczas odpalania programu. Piszemy w Pythonie więc wskazujemy sztywno na Pythona:

#!/usr/bin/env python3

2. Importujemy biblioteki, które będą używane w naszym kodzie. Najważniejsze z nich to random, który będziemy używać do generowania nowego hasła, os do interakcji z powłoką systemową Unixa oraz pexpect do zestawiania połączenia z kontrolerem:

import random
import os
import pexpect
import time
import sys
import socket
import subprocess

3. Definiujemy alfabet, który będzie używany do generowania losowego hasła oraz określamy długość generowanego ciągu znakowego na 10 znaków. Do przechowywania hasła będziemy używali tablicę pwlist:

alphabet = "abcdefghjkmnpqrstuvwxyz"
upperalphabet = alphabet.upper()
pw_len = 10
pwlist = []

4. Pętle for odpowiedzialne za generowanie nowego hasła. Nie będziemy ich tutaj dokładnie opisywali natomiast zachęcam do samodzielnej analizy tych pętli w celu zrozumienia ich mechaniki. Wygenerowane hasło ląduje w zmiennej pwstring:

for i in range(pw_len//3):
pwlist.append(alphabet[random.randrange(len(alphabet))])
pwlist.append(upperalphabet[random.randrange(len(upperalphabet))])
pwlist.append(str(random.randrange(10)))
for i in range(pw_len-len(pwlist)):
pwlist.append(alphabet[random.randrange(len(alphabet))])
random.shuffle(pwlist)
pwstring = "".join(pwlist)

5. Definicja zmiennej ssh zawierającej komendę do połączenia się z kontrolerem:

ssh = "ssh 10.3.0.33"

6. Definicja zmiennej newpass zawierającej komendę CLI dla kontrolera, która zmieni PSK dla wskazanego SSID na wygenerowane przez nas nowe hasło. Zwróć uwagę na to, że musisz znać numer SSID, dla którego zmieniasz hasło. Numer ten możesz sprawdzić w GUI kontrolera Cisco – sekcja WLANs, kolumna WLAN ID:

newpass = "config wlan security wpa akm psk set-key ascii " + pwstring + "2"

7. Wykorzystanie funkcji pexpect() do zestawienia połączenia z kontrolerem. Ustawiamy dwusekundowe opóźnienie dla wysyłania komend aby zrekompensować ewentualne spadki w prędkości połączenia. Zwróć uwagę, że podajemy tutaj clear–textem dane logowania do kontrolera. Dlatego też bardzo istotne jest zapewnienie bezpieczeństwa serwera Linux oraz samego skryptu:

c1=pexpect.spawn(ssh)
c1.delaybeforesend = 2.0
c1.expect("User:")
c1.sendline("admin")
c1.expect("assword:")
c1.sendline("SuperSecureAdminPassword")

8. Tak jak wskazuje sama nazwa biblioteki, pexpect działa na zasadzie oczekiwania na konkretny prompt. Mówimy skryptowi czego ma oczekiwać – jeśli skrypt widzi dany output w ostatniej linijce na zalogowanym urządzeniu to przechodzi dalej wysyłając za pomocą metody sendline następną komendę. Przed zmianą hasła wyłączamy SSID:

c1.expect(">")
c1.sendline("config wlan disable 2")
c1.expect(">")
c1.sendline(newpass)

9. Włączamy SSID z powrotem po zmianie hasła:

c1.expect(">")
c1.sendline("config wlan enable 2")

10. Wylogowujemy się i zamykamy sesję:

c1.expect(">")
c1.sendline("logoutr")
c1.expect("(y/N)")
c1.sendline("yr")
c1.close()

11. Hasło zostało zmienione. Teraz czas zadbać o powiadomienie recepcji o nowym haśle. W tym celu zapisujemy do pliku tekstowego treść wiadomości, którą będziemy wysyłać:

text_file = open("CurrentGuestPass.txt", "w")
text_file.write("Hello. Please be informed that Guest Wi-Fi password for has changed. New password is: %snnPlease distribute the password to all whom it may concern and remember that in some cases the previous Wi-Fi connection profile must first be removed in order to get a prompt for a new password." % pwstring)
text_file.close()

12. Tak przygotowany plik tekstowy następnie wysyłamy przy pomocy bashowej komendy mail. Definiujemy temat wiadomości i odbiorców, a jako treść podajemy zawartość przygotowanego pliku tekstowego:

os.system("mail -s 'IMPORTANT! Guest Wi-Fi password has changed!' reception@acme.com< /etc/scripts/CurrentGuestPass.txt")

Uff, było tego sporo, nieprawdaż? Nie wgłębiłem się w komentarzach powyżej zanadto w to co robią poszczególne linijki. Skupiłem się raczej na tym by opisać poszczególne bloki kodu w taki sposób, abyś zrozumiał przebieg skryptu. W celu pełnego zrozumienia komend powyżej odsyłam do wspomnianego wcześniej kursu i samodzielnej nauki Pythona.

Na koniec został nam jeszcze jeden krok – edycja crontaba w taki sposób, aby skrypt się uruchamiał samodzielnie pierwszego dnia każdego miesiąca o godzinie 00:05:

crontab -e
00 05 * * 1 cd /etc/scripts && /etc/scripts/guestpass.py
:wq!

To by było na tyle! Możesz zapomnieć o ręcznym zmienianiu hasła dla sieci Guest Wi-Fi!

Mamy za sobą napisanie pierwszego skryptu w Pythonie. Jeśli zainteresował Cię ten temat to nie zatrzymuj się i zacznij naukę Pythona już dziś. Umiejętność ta przyda Ci się nie tylko do pisania takich prostych skryptów wykorzystujących pexpect(), ale również przy bardziej wyrafinowanych skryptach wykorzystujących API.

A Ty, jakie materiały poleciłbyś do nauki programowania w Pythonie?

TAGI: Python
Damian Michalak 10 grudnia 2018
Udostępnij ten materiał
Facebook Twitter Whatsapp Whatsapp LinkedIn
Komentarze: 9
  • Rafał Rudewicz pisze:
    11 grudnia 2018 o 11:28

    Python poprzez swoją czytelność i budowę języka bardzo zbliżoną do naszej naturalnej mowy zdecydowanie ułatwia debugowanie oraz późniejszą modyfikację kodu. Muszę tylko zwrocić Ci uwagę, że wskazany przez Ciebie shebang odwołuje się do wersji 2, a nie do 3 jak podałeś podczas instalacji (python3 jest prawidłowo) oraz nie nie zawsze jest taki sam (zależy od dystrybucji).

    Ze swojej strony polecamy codecamy do nauki Pythona.

    Odpowiedz
    • Damian Michalak pisze:
      11 grudnia 2018 o 11:58

      Dzięki Rafał za uważną lekturę, już poprawione 🙂 Błąd wynikający z tego, że skrypt pisałem oryginalnie w Pythonie 2 ^^ O ile się nie mylę najwygodniej byłoby dodać ścieżkę Pythona do $PATH?

      Dopisałem Codecamy do listy w artykule, dzięki!

      Odpowiedz
      • Rafał Rudewicz pisze:
        11 grudnia 2018 o 17:00

        Proszę bardzo, choć nawet najlepszy kurs nie zastąpi samodzielnych projektów. Dla mnie osobiście najlepszą formą nauki była automatyzacja/pisanie skryptów które przyspieszały moją pracę. W końcu najlepszy inżynier to leniwy inżynier 😉
        Co do $path to miami by to sens gdybyś miał pythona zainstalowanego w innym katalogu i bodajże jest zmienna środowiskowa do tego $pythonpath. Można by w sumie też zapisać skrypt z rozszerzeniem pytanie i też powinno działać bez shebang.

        W akapicie o tym dlaczego python, warto również wspomnieć, że jest on wykonywany przez interpreter czyli działa niezależnie od systemu operacyjnego oraz skrypty są zapisywane w formie pliku tekstowego, co znacząco ułatwia ich przenoszenie i późniejsza edycję.

        Odpowiedz
  • Krzysiek Mroczko pisze:
    11 grudnia 2018 o 16:29

    Dziękuje za artykuł. Ja zacząłem się uczyć z książki \”Python dla każdego. Podstawy programowania\” – Michael Dawson i śmiało mogę polecić. Nauka na przykładach, czyli najlepszy dla mnie sposób.

    Odpowiedz
    • Damian Michalak pisze:
      11 grudnia 2018 o 17:18

      Dzięki @krzysiekmroczko:disqus! Dopisane do listy materiałów 🙂

      Odpowiedz
  • Krzysiek Mroczko pisze:
    11 grudnia 2018 o 21:05

    Przepraszam za offtopic, ale natrafiłem ostatnio na książkę \”101 zabezpieczeń przed atakami w sieci komputerowej\”, czy mieliście okazję się z nią zapoznać? Porusza dość ciekawe tematy, jednak jest już dość leciwa (2005 r.) jak na tempo rozwoju sieci i nie wiem czy jest sens ją czytać. A może ktoś poleci coś podobnego?

    Odpowiedz
    • Damian Michalak pisze:
      3 stycznia 2019 o 20:18

      Ja niestety nie miałem okazji się z nią zapoznać

      Odpowiedz
  • Łukasz Sędek pisze:
    9 stycznia 2019 o 16:48

    Dodałbym od siebie tworzenie venv/wirtualnego środowiska pythona. Korzystanie z bibliotek systemowych prędzej czy później kończy się bałaganem. Do tego – automatyzacja to kod. Kod to programowanie. Najlepsza nauka programowania to po prostu pisanie kodu. Jak najwięcej.

    Odpowiedz
  • Marcin Kita pisze:
    3 lipca 2019 o 13:11

    Też nigdy nie byłem fanem programowania, ale nadchodzą takie czasy, że niedługo bez tych skilli będzie ciężko. Ja zaczynalem od LPTHW (Learn Python The Hard Way). Jeśli chodzi o automatyzację CLI to nie ma chyba nic bardziej dojrzałego niż netmiko. Sam większość swoich projektów opieram właśnie o tą bibliotekę. Warto też zapoznać się z NAPALMem, który jest vendor neutral i zawsze dostaniemy z niego ustrukturyzowane dane. Jeśli chodzi o API to wszystko i jeszcze więcej można zrobić za pomocą biblioteki requests.

    Odpowiedz

Dodaj komentarz Anuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Ci się też spodobać

Routing & Switching

Maszyna stanowa OSPF

6 maja 2021
Routing & Switching

Redystrybucja między OSPF a EIGRP [WYZWANIE]

14 stycznia 2020
Routing & Switching

Czym się różnią switche L3 od routerów?

12 września 2019
Routing & Switching

Czym są tunele VPN?

23 czerwca 2019

NA STYKU SIECI

Tworzymy społeczność sieciowców skupioną dookoła rozwiązań oraz certyfikacji firmy Cisco Systems.
Przydatne linki
  • NSS+
  • Tagi
  • Podcast
Nasze projekty
  • Szkoła Sieci

Dołącz do NSSlettera

Informacje o nowych publikacjach oraz dodatkowe treści!

© Na Styku Sieci 2022 - powered by Alvortech

  • Polityka prywatności
  • Warunki użytkowania
  • O nas
  • Kontakt
Witaj ponownie!

Zaloguj się na swoje konto

Zapomniałeś/aś hasło?