W kolejnym wpisie z cyklu zajmiemy się sprawdzeniem daty ostatniego backupu. Potrzebuję sprawdzić, czy spełniony jest pierwszy z moich warunków pozwalający na odtworzenie Cisco ISE z backupu. Jest to dostęp do kopii zapasowej, która została wykonana nie wcześniej niż wczoraj. Jest to warunek, które sam ustaliłem, gdyż równie dobrze mógłbym sprawdzać, czy mam dostęp do jakiegokolwiek backupu i wykorzystać najnowszy z dostępnych. Spójrz w jaki sposób zaimplementowałem sprawdzenie daty backupu, z którego możliwe będzie odtworzenie później konfiguracji Cisco ISE.
Spis treści
- Część I: Opis projektu
- Część II: Przygotowanie środowiska Jenkins i Ansible
- Część III: Sprawdzamy datę ostatniego backupu
- Część IV: Sprawdzamy ważność licencji trial na Cisco ISE
- Część V: Zatrzymujemy ISE i wyłączamy maszynę wirtualną
- Część VI: Zero Touch Provisioning
- Część VII: Odtworzenie konfiguracji z kopii zapasowej
Wykonanie kopii zapasowej konfiguracji Cisco ISE
Kopie zapasowe konfiguracji wykonuję codziennie na zasób FTP. W przypadku Cisco ISE najpierw musimy skonfigurować repozytorium. Repozytorium w Cisco ISE odnosi się do centralnego miejsca przechowywania danych i plików. ISE wykorzystuje je do różnych celów, w tym aktualizacji oprogramowania, rozszerzeń funkcjonalności, backupów, integracji z innymi usługami itp. Repozytoria mogą być konfigurowane do przechowywania różnego rodzaju danych, w zależności od potrzeb organizacji. Repozytorium może być skonfigurowane z wykorzystywaniem różnych protokołów transferu plików, takich jak FTP, SFTP, TFTP, czy SCP. Umożliwia to elastyczne zarządzanie zasobami z różnych źródeł i lokalizacji. Ja wybrałem FTP, a konfiguracja repozytorium przedstawia się następująco:
Następnie definiujemy cykliczne zadanie wykonania kopii zapasowej konfiguracji podając jako miejsce docelowe utworzone repozytorium. Logi z wykonania kopii zapasowej znajdziemy w Administration -> Backup & Restore.
W tym samym miejscu podejrzymy też listę dostępnych kopii zapasowych. Alternatywnie możemy zalogować się na serwer FTP i wyświetlić listę plików. Pamiętajmy, że nazwa zadania cyklicznego będzie zawierać się w nazwie pliku z kopią zapasową.
Sprawdzenie daty ostatniego backupu
Jak już na wstępie wspomniałem pierwszym z warunków do wykonania odtworzenia maszyny wirtualnej Cisco ISE jest dostęp do kopii zapasowej konfiguracji nie starszej niż jeden dzień. Sprawdzenie to wykonuję za pomocą playbooka Ansible. Proces rozpoczyna się od zastosowania polecenia shell, które wykorzystuje curl
do pobrania listy plików z serwera zdalnego, używając do tego celu danych uwierzytelniających i adresu URL FTP. Wynik tego zadania jest rejestrujemy jako zmienną faktu.
-rwxrwxrwx 1 userftp users 185449752 Mar 10 20:43 ise-lab-CFG10-240310-2130.tar.gpg -rwxrwxrwx 1 userftp users 185110943 Mar 11 20:44 ise-lab-CFG10-240311-2130.tar.gpg -rwxrwxrwx 1 userftp users 185632860 Mar 12 20:45 ise-lab-CFG10-240312-2130.tar.gpg -rwxrwxrwx 1 userftp users 186080543 Mar 13 20:44 ise-lab-CFG10-240313-2130.tar.gpg -rwxrwxrwx 1 userftp users 186135275 Mar 14 20:44 ise-lab-CFG10-240314-2130.tar.gpg
Następnie, z wyniku który zarejestrowaliśmy, wydobywamy linie rozpoczynające się od konkretnej frazy (“ise-lab-CFG10”) i przekształcamy je w listę. W ten sposób tworzymy nowy fakt o nazwie file_lines. Kolejne zadanie polega na ekstrakcji nazw plików wraz z datami z tej listy, co jest realizujemy poprzez zastosowanie wyrażeń regularnych. Po manipulacji ciągami znaków, skrypt identyfikuje najnowszy plik na podstawie ostatniej pozycji w przefiltrowanej i posortowanej liście, jednocześnie dostosowując format daty poprzez usunięcie podwójnych spacji. Dodatkowo, z najnowszego pliku wyciągamy datę jego utworzenia, co umożliwia dalsze działania porównawcze.
Kluczowym momentem jest sprawdzenie, czy data ostatniego backupu odpowiada dzisiejszej dacie lub dacie wczorajszej. Jeśli warunek nie jest spełniony, to playbook zakończy działanie błędem. Poinformuje nas też o tym, że ostatni backup nie pochodzi z żądanego okresu. Porównywanie daty jest rozbiłem osobno na porównanie miesiąca i dnia. Dlaczego takie podejście? W Alpine Linux daty z pierwszych dni miesiąca się źle parsowały razem nazwą miesiąca, ponieważ przerwa między miesiącem a numerem dnia była o jedną spację dłuższa. Dlatego wartości te porównuję osobno.
Pełen playbook Ansible przedstawia się następująco:
--- - name: Check latest backup date hosts: localhost connection: local gather_facts: no tasks: - name: List files on remote server shell: cmd: "curl --silent --user {{ ftp_username }}:{{ ftp_password }} {{ ftp_url }}" register: output - name: Extract lines starting with ise-lab-CFG10 set_fact: file_lines: "{{ output.stdout.split('\n') | select('match', '^.* ise-lab-CFG10.*$') | list }}" - name: Extract filenames and dates set_fact: files_with_date: "{{ file_lines | map('regex_replace', '.* ([A-Za-z]{3} +\\d+ \\d+:\\d+) (ise-lab-CFG10-.*)', '\\1 \\2') | list }}" - name: Get the most recent file set_fact: most_recent_file_orig: "{{ files_with_date | last }}" - name: Remove double spaces in date if exists set_fact: most_recent_file: "{{ most_recent_file_orig | replace(' ',' ') }}" - name: Extract date set_fact: last_backup_date: "{{ most_recent_file.split(' ')[0:2] | join(' ') }}" - name: Check if latest backup is today fail: msg: "Last backup is not from today or yesterday" when: (last_backup_date != current_date) and (last_backup_date != yesterday_date)
Zakończenie playbooka błędem w ostatnim zadaniu spowoduje, że cały pipeline Jenkins się zatrzyma.
Konfiguracja pipeline Jenkins
W poniższym fragmencie Jenkinsfile, definiujemy etap pipeline o nazwie ‘Check latest backup on FTP server’. Realizuje on proces weryfikacji najnowszej kopii zapasowej na serwerze FTP. Proces ten składa się z kilku kluczowych kroków wykonanych w środowisku Jenkinsa, każdy z nich pełniący specyficzną rolę w celu osiągnięcia wymaganego rezultatu.
Na początku, w sekcji environment, definiujemy zmienne środowiskowe ftp_username i ftp_password, do których przypiszemy wartości z zaszyfrowanych poświadczeń Jenkinsa. Te zmienne zawierają nazwę użytkownika i hasło do serwera FTP, umożliwiając bezpieczne połączenie. Wartości te przekazuję w bezpieczny sposób jako parametr wykonania pipeline. Bezpieczeństwo przechowywania danych jak i przekazywania ich do wykonywanego playbooka zapewnia Jenkins.
Następnie, w sekcji steps, proces rozpoczyna się od pierwszego bloku script, który wykonuje polecenie shell (sh), aby pobrać bieżącą datę w formacie ‘miesiąc dzień’ (np. ‘Mar 15’). Wynik tego polecenia jest przypisujemy do zmiennej środowiskowej date_current po usunięciu zbędnych spacji na końcach. Drugi blok script działa podobnie do pierwszego, jednak tym razem pobiera datę dnia poprzedniego, również w formacie ‘miesiąc dzień’, używając opcji –date=”1 day ago”. Wynik jest zapisywany do zmiennej środowiskowej date_yesterday.
Ostatni krok w tym etapie polega na wywołaniu playbooka Ansible, check-last-backup-date.yaml, z wykorzystaniem modułu ansiblePlaybook. Do wykonania tego playbooka używane są specyficzne zmienne: ścieżka do playbooka, lokalny plik inventory (określony jako ‘inventory-localhost’), oraz zestaw dodatkowych zmiennych (extraVars). Te dodatkowe zmienne zawierają URL serwera FTP (ftp_url), poświadczenia użytkownika FTP (ftp_username, ftp_password) oraz obliczone daty (current_date, yesterday_date), które są przekazywane do playbooka.
stage('Check latest backup on FTP server') { environment { ftp_username = credentials('ftp_username') ftp_password = credentials('ftp_password') } steps { script { env.date_current = sh ( script: 'date "+%b %e"', returnStdout: true ).trim() } script { env.date_yesterday = sh ( script: 'date --date="1 day ago" "+%b %e"', returnStdout: true ).trim() } ansiblePlaybook( playbook: 'check-last-backup-date.yaml', inventory: 'inventory-localhost', extraVars: [ ftp_url: params.ftp_url, ftp_username: env.ftp_username, ftp_password: env.ftp_password, current_date: env.date_current, yesterday_date: env.date_yesterday, ] ) } }
Jeżeli wykonanie playbooka zwróci błąd to wykonywanie pipeline zostanie przerwane. Nie ma znaczenia czy będzie to błąd zdefiniowany przeze mnie w ostatnim zadaniu playbooka czy inny błąd jego wykonania.