diff --git a/README.md b/README.md index 7aecbcc..369e9ba 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,36 @@ -# MikrotikBackup_git +# Mikrotik RouterOS backup script -Python skripta, ki naredi backup mikrotikovih naprav in naloži backupe na git strežnik, če se je konfiguracija spremenila. \ No newline at end of file +## Postopek +### Strežnik +Najprej je potrebna priprava strežnika. Skripta bi morala delovati na vseh sistemih na katerih teče python. +Na strežniku mora biti nameščen Python3 ter nekaj knjižnic: paramiko, git, time. Na strežniku mora biti ustvarjen SSH ključ. + +### Mikrotikove naprave +Na Mikrotikovih napravah, za katere želimo narediti varnostno kopijo konfiguracije na Git strežniku, je potrebno ustvariti "skupino" (oz. group) za uporabnika s sledečimi pravicami: ssh, ftp, read, write, sensitive. +Nato je treba ustvariti uporabnika, ki ima dodan prej generiran javni SSH ključ. Tako bo omogočena varna prijava preko protokola SSH na Mikrotikovo napravo brez gesla. +Zagotovljeno mora biti tudi, da ima strežnik dostop do vrat 22 oz. nastavljenih SSH vrat na Mikrotiku. + +### Git Strežnik +Uporabniški račun, preko katerega bodo kopije konfiguracij nalagane na strežnik, mora imeti dodan javni SSH ključ strežnika, ki omogoča varno prijavo brez gesla. +Pripravljen mora biti repozitorij, ki mora biti tudi kloniran na strežnik namenjen varnostnim kopijam. Nujno je, da so znotraj repozitorija pripravljene mape, ki imajo enako ime kot lokacije na seznamu. + +### Priprava skripte + +Za delovanje skripte so potrebne 3 datoteke: +- main.py -> Glavna skripta +- config.py -> Parametri potrebni za delovanje skripte +- devices.csv -> Seznam naprav, ki jih bo strežnik varnostno kopiral + +Ko so naprave vpisane v seznam in so potrebni parametri pripravljeni v datoteki config.py, je potrebno le še pognati skripto oziroma nastaviti avtomatsko izvajanje skripte, na primer enkrat na dan. +Skripta je zasnovana tako, da na Git strežnik nalaga le popravke. Če sprememb ni, skripta ne naloži ničesar. + +Primer datoteke devices.csv + +``` +Location,DeviceName,HostName,Port,User +Nanos,Router,192.168.2.3,22,backupscript +``` + +V tem primeru se torej skripta priklaplja na router na **Nanosu**, ki ima IP **192.168.2.3**, SSH posluša na vratih **22**. Za priklop nanj je uporabljen uporabnik **backupscript**. Kot prej rečeno je nujno, da je tudi ustvarjena mapa **Nanos** oz. mapa z imenom uporabljene lokacije. + +Skripta izvede varnostno kopijo na vseh napravah, ki so vpisane na seznam. \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..191a3a6 --- /dev/null +++ b/config.py @@ -0,0 +1,3 @@ +devicescsv_path = "/path/to/devices.csv" +repository_path= "/path/to/cloned/repository" +key_path = "/path/to/private/ssh/key/.ssh/id_rsa" \ No newline at end of file diff --git a/devices.csv b/devices.csv new file mode 100644 index 0000000..e659b32 --- /dev/null +++ b/devices.csv @@ -0,0 +1 @@ +Location,DeviceName,HostName,Port,User diff --git a/main.py b/main.py new file mode 100644 index 0000000..afce633 --- /dev/null +++ b/main.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +import paramiko +from git import Repo +import csv +import time +from config import * #config variables from config.py + +#Check entries in the devices.csv document and import them into the dictionary +devices = [] #dictionary +with open(devicescsv_path,'r') as devicelist: + list = csv.DictReader(devicelist) + for row in list: + devices.append(row) + +#for each entry do an export and download it +for device in devices: + file_path = repository_path + "/" + device["Location"] + "/" + device["Location"] + "_" + device["DeviceName"] + ".rsc" + # Create an SSH client instance + ssh_client = paramiko.SSHClient() + ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + try: + # Connect to the server + ssh_client.connect(hostname = device["HostName"], port = device["Port"], username = device["User"], pkey = paramiko.RSAKey.from_private_key_file(key_path)) + + except Exception as e: + print(f"An error occurred: {e}") + + else: + print("Connected to " + device["HostName"]) + #Export config + ssh_client.exec_command("export file=" + device["Location"] + "_" + device["DeviceName"] + ".rsc show-sensitive") + print("Export commanded") + time.sleep(10) #Wait for ten seconds to make sure latest export is prepared before download + + #Download Config + ssh_client.open_sftp().get(device["Location"] + "_" + device["DeviceName"] + ".rsc", file_path) + print("File downloaded successfully!") + + finally: + # Close the SSH connection + ssh_client.close() + print("Connection closed") + + # Open exported document, remove date and time of export + with open(file_path, 'r') as file: + lines = file.readlines() + + if lines: # Check if the file is not empty + lines[0] = lines[0][:2] + lines[0][25:] #remove date and time of export + + with open(file_path, 'w') as file: + file.writelines(lines) + +repository = Repo(repository_path) + +if repository.bare: + print("The repository is bare") + exit() + +if repository.is_dirty(untracked_files=True): #Check if there are any differences + print("Changes detected in the repository.") + + repository.git.add(all=True) #Stage all changes + print("Staged all changes.") + + commit_message = time.strftime("%Y.%m.%d %H:%M:%S", time.localtime()) #commit changes + repository.index.commit(commit_message) + print("Committed changes with message:" + commit_message) + + origin = repository.remote(name='origin') #push + origin.push() + print("Pushed changes to the remote repository.") +else: + print("No changes to commit.") \ No newline at end of file