Pierwsze kroki w automatyzacji sieci – Python i pexpect()

Damian Michalak
Damian Michalak 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!

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?

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 można się również nauczyć samodzielnie analizując 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ążkę „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/scripts
cd /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.

#!/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")
Komentarze: 9
Otrzymuj powiadomienia z tej dyskusji
Powiadom mnie o
guest

9 - Ilość komentarzy
Sortuj wg najlepszych
Sortuj wg najnowszych Sortuj wg najstarszych
Inline Feedbacks
View all comments
Rafał Rudewicz
Rafał Rudewicz
5 lat temu

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.

Rafał Rudewicz
Rafał Rudewicz
5 lat temu
Odpowiedź do  Damian Michalak

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ę.

Krzysiek Mroczko
Krzysiek Mroczko
5 lat temu

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.

Krzysiek Mroczko
Krzysiek Mroczko
5 lat temu

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?

Łukasz Sędek
Łukasz Sędek
5 lat temu

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.

Marcin Kita
Marcin Kita
4 lat temu

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.