Netzwerk Backup & Versionierung mit GIT

Irgendwann stellt sich jeder Admin die Frage wie er denn seine Konfigurationen der Netzwerkkomponenten sichern soll. Eine weitere Anforderung ist die Dokumentation der Änderungen der Netzwerkkomponenten, die Versionierung. Beide Anforderungen sollen möglichst automatisiert und sicher umgesetzt werden.

GIT

Für die Versionierung setzen wir GITEA ein, ein freies, selbst gehostetes "Versionierungssystem". Wir gehen davon aus das die MySQL Datenbank bereits installiert und einsatzfähig ist.

mysql -u root -ppassword
create database gitea;
grant all on gitea.* to 'gitea'@'localhost' identified by 'gitea';
flush privileges;
exit;

Anlegen eines GIT Users, die Erstellung von Verzeichnissen, sowie die Rechtevergabe auf diesen.

groupadd gitea
useradd gitea --system --shell /bin/bash -m -d /home/gitea -g gitea
mkdir -p /var/lib/gitea/{custom,data,indexers,public,log}
chown gitea:gitea /var/lib/gitea/{data,indexers,log}
chmod 750 /var/lib/gitea/{data,indexers,log}
mkdir /etc/gitea
chown root:gitea /etc/gitea
chmod 770 /etc/gitea
cd /home/gitea
wget -O gitea https://dl.gitea.com/gitea/1.19.0/gitea-1.19.0-linux-amd64
chmod +x gitea
mv gitea /usr/local/bin/gitea

vi /etc/systemd/system/gitea.service

[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=mysqld.service

[Service]
LimitMEMLOCK=infinity
LimitNOFILE=65535
RestartSec=2s
Type=simple
User=gitea
Group=gitea
WorkingDirectory=/var/lib/gitea/
ExecStart=/usr/local/bin/gitea web -c /etc/gitea/app.ini
Restart=always
Environment=USER=gitea HOME=/home/gitea GITEA_WORK_DIR=/var/lib/gitea
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable gitea
systemctl start gitea

Nun die Konfiguration unter der URL http://IP-ADDRESS:3000 abschließen. Die im Konfigurationsdialog erfolgten Änderungen könnt ihr jederzeit in der Datei /etc/gitea/app.ini anpassen. Nach Änderungen in dieser Datei ist der Dienst gitea mit systemctl restart gitea neu zu starten.

GIT verlangt beim Commit Authentifizierungsangaben. Damit wir unsere Konfigurationssicherung automatisch ablaufen lassen können, müssen wir den GIT Account in einer Datei hinterlegen. Diese liegt dann im Home Directory (nicht root) des Nutzers, der den GIT Job am Ende ausführen muss.

~/.git-credentials

http://USERNAME:PASSWORD@IP-ADDRESS

Nun noch folgenden Befehl ausführen um die angelegten Credentials zu verwenden.

git config --global credential.helper store

Wir rufen nun die Weboberfläche unseres GIT Systems auf http://IP-ADDRESS:3000 und melden uns mit unserem Nutzer an. Als nächstes erstellen wir ein neues Repository.

Erstellung GIT Repository "Netzwerkkonfiguration"

Als nächstes müssen wir müssen wir auf unserem System einen Backup Ordner definieren, wo wir künftig unsere Konfigurationen ablegen wollen.

mkdir /backup
chown gitea:gitea -R /backup

Jetzt klonen wir unser zuvor angelegtes GIT Repository.

git clone http://IP-ADDRESS:3000/Netzwerkkonfiguration.git .

In dem Pfad /backup/Netzwerkkonfiguration werden alle gesicherten Konfigurationen abgelegt und von dort aus nach GIT gepusht.

push.sh

git add switch1.confg
git commit -m "Konfigurationssicherung" switch1.confg

Ansible

Für das Backup Scripting eignet sich perfekt Ansible. Für ältere Switche, die noch kein SSH anbieten und demzufolge nur per Telnet zu erreichen sind, verwende ich folgendes Playbook:

backup_telnet.yml

---
- name: Backup Netzwerkkomponenten via Telnet
  hosts: telnet
  gather_facts: no

  tasks:

  - name: Touch Files fuer TFTP
    ansible.builtin.file:
      path: /var/lib/tftpboot/{{ inventory_hostname }}.confg
      state: touch
      mode: u=rwx,g=rwx,o=rwx

  - name: Setze Besitzer und Dateirechte
    ansible.builtin.file:
      path: /var/lib/tftpboot/{{ inventory_hostname }}.confg
      owner: nobody
      group: nobody
      mode: '0777'

  - name: Backup devices via Telnet and TFTP
    ansible.netcommon.telnet:
      user: ADMIN-USERNAME
      password: ADMIN-PASSWORD
      login_prompt: "Username: "
      prompts:
      - "[>#?]"
      command:
         - "enable\nADMIN-PASSWORD"
         - copy running-config tftp://TFTP-SERVER-IP/{{ inventory_hostname }}.confg
         - TFTP-SERVER-IP
         - "{{ inventory_hostname }}.confg"

  - name: Copy Konfigurationen ins Webdirectory
    copy:
      src: /var/lib/tftpboot/{{ inventory_hostname }}.confg
      dest: /var/www/html/konfigurationen/{{ inventory_hostname }}/{{ inventory_hostname }}.confg
      owner: apache
      group: apache
      mode: '0755'

Für das Backup von Fortinet FortiGate Produkten verwende ich folgendes Python Script(Access-Token muss auf der FortiGate erst noch erstellt werden):

import requests

api_url = 'https://IP-ADDRESS-FG/api/v2/monitor/system/config/backup?scope=global&access_token=ACCESS-TOKEN'

requests.packages.urllib3.disable_warnings()

data = requests.get(api_url, verify=False)

with open('/configs/fortigate.cfg', 'wb') as f:
    for line in data:
        f.write(line)

print(data.text)