Lese-Ansicht

Demonstration von Ansible Lint am Beispiel einer Ansible Collection

In diesem Beitrag erkläre ich kurz, was Ansible Lint ist und demonstriere dessen Anwendung am Beispiel meiner Ansible Collection tronde/nextcloud.

Er richtet sich primär an Personen, die mit Ansible Lint noch nicht vertraut sind. Linting-Profis werden vermutlich keine neuen Erkenntnisse gewinnen.

Was ist Ansible Lint und wofür ist es gut?

Lint (englisch für „Fussel“) ist eine Software zur statischen Code-Analyse. Davon abgeleitet hat sich das Verb linten (englisch to lint) für das Durchführen der statischen Code-Analyse etabliert.

https://de.wikipedia.org/wiki/Lint_(Programmierwerkzeug)

Dem obigen Zitat und der Projektdokumentation folgend, ist Ansible Lint dementsprechend ein Werkzeug zur statischen Code-Analyse von Ansible Playbooks, Roles und Collections. Mit der Anwendung dieses Werkzeugs auf die eigenen Ansible-Inhalte kann sichergestellt werden, dass diese gängigen Konventionen und Standards entsprechen.

Wie wird Ansible Lint installiert?

Die Dokumentation beschreibt verschiedene Installationsverfahren. Ich habe ansible-lint als Bestandteil der Ansible Development Tools (ADT) installiert. Dies ist ein Werkzeugkasten mit weiteren Programmen wie z.B. `ansible-core` und Ansible Molecule, welche ich für die Entwicklung meiner Ansible Collection nutze.

Auf meiner Fedora Workstation habe ich die ADT wie folgt installiert:

~]$ mkdir venv
~]$ cd venv
venv]$ ]$ python -m venv adt
venv]$ source adt/bin/activate
(adt) venv]$ pip install pip --upgrade
Requirement already satisfied: pip in ./adt/lib64/python3.12/site-packages (23.3.2)
Collecting pip
  Using cached pip-24.2-py3-none-any.whl.metadata (3.6 kB)
Using cached pip-24.2-py3-none-any.whl (1.8 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 23.3.2
    Uninstalling pip-23.3.2:
      Successfully uninstalled pip-23.3.2
Successfully installed pip-24.2
(adt) venv]$  pip install ansible-dev-tools
Collecting ansible-dev-tools
  Using cached ansible_dev_tools-24.7.2-py3-none-any.whl.metadata (11 kB)
… Ausgabe gekürzt
(adt) venv]$ adt --version
ansible-builder                          3.1.0
ansible-core                             2.17.3
ansible-creator                          24.7.1
ansible-dev-environment                  24.7.0
ansible-dev-tools                        24.7.2
ansible-lint                             24.7.0
ansible-navigator                        24.8.0
ansible-sign                             0.1.1
molecule                                 24.8.0
pytest-ansible                           24.8.0
tox-ansible                              24.8.0

Ansible Lint liefert eine ganze Reihe von Profilen mit, welche Autoren unterstützen, die Code-Qualität schrittweise zu verbessern. Der Befehl ansible-lint --list-profiles gibt die verfügbaren Profile mit einer Beschreibung aus.

Ich werde im Folgenden mit dem Profil shared arbeiten, welches für Autoren gedacht ist, die ihre Collection auf https://galaxy.ansible.com veröffentlichen möchten.

Eine Collection linten

Bevor es zur Sache geht, wechsel ich in das Projektverzeichnis meiner Ansible Collection und erstelle einen neuen Branch, mit dem Befehl git checkout -b lint. Die in meinem Repo vorhandene Datei .ansible-lint-ignore lösche ich, da ich im folgenden alle Fehler und Regelverstöße sehen möchte. Zu Beginn stellt sich mein Arbeitsverzeichnis wie folgt dar:

(adt) nextcloud]$ git status
On branch lint
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	deleted:    .ansible-lint-ignore

no changes added to commit (use "git add" and/or "git commit -a")

Das Programm ansible-lint besitzt mit der Option --fix die Fähigkeit, Fehler automatisch zu korrigieren und auch YAML-Dateien neu zu formatieren. Der folgende Code-Block umfasst die gekürzte Ausgabe, wenn das Kommando ansible-lint --profile=shared --fix im Arbeitsverzeichnis ausgeführt wird.

(adt) nextcloud]$ ansible-lint --profile=shared --fix
WARNING  Listing 37 violation(s) that are fatal
galaxy[no-changelog]: No changelog found. Please add a changelog file. Refer to the galaxy.md file for more info.
galaxy.yml:1

var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex. (NC_HTML) (vars: NC_HTML)
roles/backup_restore_nextcloud/defaults/main.yml:4

…

risky-file-permissions: File permissions unset or incorrect.
roles/backup_restore_nextcloud/tasks/main.yml:18 Task/Handler: Copy backup files to container host

no-changed-when: Commands should not change things if nothing needs doing.
roles/backup_restore_nextcloud/tasks/main.yml:40 Task/Handler: Import tarball contents into an existing podman volume

no-changed-when: Commands should not change things if nothing needs doing.
roles/backup_restore_nextcloud/tasks/main.yml:54 Task/Handler: Export podman volumes to tarballs

var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex. (MYSQL_DATABASE) (vars: MYSQL_DATABASE)
roles/deploy_nextcloud_with_mariadb_pod/defaults/main.yml:13

…

Read documentation for instructions on how to ignore specific rule violations.

Modified 6 files.
                     Rule Violation Summary                      
 count tag                    profile rule associated tags       
    33 var-naming[pattern]    basic   idiom                      
     1 risky-file-permissions safety  unpredictability           
     1 galaxy[no-changelog]   shared  metadata                   
     2 no-changed-when        shared  command-shell, idempotency 

Failed: 37 failure(s), 0 warning(s) on 25 files. Profile 'shared' was required, but 'min' profile passed.

Obige Ausgabe:

  • Benennt Funde mit Pfadangabe und Zeilennummer
  • Führt 37 Fehler auf, inkl. der Regeln, die nicht eingehalten werden; Beispiele
    • galaxy[no-changelog]: No changelog found. Please add a changelog file. Refer to the galaxy.md file for more info.
    • risky-file-permissions: File permissions unset or incorrect.
    • no-changed-when: Commands should not change things if nothing needs doing.
    • var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex.
  • Informiert, dass ansible-lint Änderungen an 6 Dateien vorgenommen hat

Mit git diff verschaffe ich mir einen Überblick, welche Änderungen ansible-lint vorgenommen hat. Dies sind in meinem Fall:

  • Quoting von Strings
  • Einrückung von Kommentaren

Als Nächstes sehe ich mir die übrigen Fehler der Reihe nach an. Die Dokumentation beinhaltet eine Übersicht mit Beschreibungen der einzelnen Regeln. Dies ist nützlich, wenn der kurze Text in der Ausgabe von ansible-lint nicht ausreichend ist.

galaxy[no-changelog]: No changelog found. Please add a changelog file.

Unter Galaxy: Changelog Details finden sich Hinweise, wie dieser Fehler zu beheben ist. Ich erstelle die leere Datei CHANGELOG.md im Wurzelverzeichnis meiner Collection und der Fehler ist abgestellt.

Natürlich werde ich diese Datei zukünftig nutzen, um die wichtigsten Änderungen zu dokumentieren. ;-)

risky-file-permissions: File permissions unset or incorrect.

Auch hier habe ich kurz in der Dokumentation unter risky-file-permissions nachgesehen. Den Fehler habe ich abgestellt, indem ich den Parameter mode: 0600 zum Task hinzugefügt habe.

Dies war ein Flüchtigkeitsfehler, wie er häufig passieren kann, wenn man seinen Code nicht konsequent überprüft. Ohne den Dateimode explizit zu setzen, kann dies zu unvorhersehbaren bzw. überraschenden Verhalten führen.

no-changed-when: Commands should not change things if nothing needs doing.

An zwei Stellen bin ich leider nicht herumgekommen, das ansible.builtin.command Modul zu verwenden, da kein natives Modul für diese Aufgabe existiert. Betrachtet man sich die beiden Tasks fällt auf, dass diese jedes Mal Daten verarbeiten werden. Sie sind nicht idempotent. Im Ergebnis können sie erfolgreich sein oder fehlschlagen, aber sie werden immer Daten verarbeiten und dadurch ändern.

 41     - name: Import tarball contents into an existing podman volume
 42       ansible.builtin.command:
 43         cmd: |
 44           podman volume import
 45           {{ item }} {{ backup_restore_nextcloud_import_path }}/{{ item }}.tar
 46       loop:
 47         - "{{ NC_HTML }}"
 48         - "{{ NC_APPS }}"
 49         - "{{ NC_CONFIG }}"
 50         - "{{ NC_DATA }}"
 51         - "{{ MYSQL_DATA }}"
 52            
 53 # I need to use the command module as the volume module lacks the functionality
 54 # to export podman volumes.
 55 - name: Export podman volumes to tarballs
 56   ansible.builtin.command:
 57     cmd: podman volume export {{ item }} --output {{ backup_restore_nextcloud_export_path }}/{{ item }}.tar
 58   loop:    
 59     - "{{ NC_HTML }}"
 60     - "{{ NC_APPS }}"
 61     - "{{ NC_CONFIG }}"
 62     - "{{ NC_DATA }}"
 63     - "{{ MYSQL_DATA }}"
 64   tags:    
 65     - never
 66     - backup

Um herauszufinden, wie ich ansible-lint zufriedenstellen kann, schaue ich wieder in der Doku unter no-changed-when nach. Nach der dortigen Beschreibung ist mein Fehler, dass ich den Rückgabewert des Kommandos nicht behandel. Daher registriere ich nun eine Variable je Task, die die Task-Ausgabe aufnimmt und prüfe den Rückgabewert. Ist der Rückgabewert gleich 0 wird der Task-Status auf changed gesetzt, ist der Rückgabewert ungleich 0 wird der Status entsprechend auf failed gesetzt. Das ganze sieht nun wie folgt aus:

 41     - name: Import tarball contents into an existing podman volume
 42       ansible.builtin.command:
 43         cmd: |
 44           podman volume import
 45           {{ item }} {{ backup_restore_nextcloud_import_path }}/{{ item }}.tar
 46       register: __import_tar_output
 47       changed_when: __import_tar_output.rc == 0
 48       failed_when: __import_tar_output.rc != 0
 49       loop:
 50         - "{{ NC_HTML }}"
 51         - "{{ NC_APPS }}"
 52         - "{{ NC_CONFIG }}"
 53         - "{{ NC_DATA }}"
 54         - "{{ MYSQL_DATA }}"
 55  
 56 # I need to use the command module as the volume module lacks the functionality
 57 # to export podman volumes.
 58 - name: Export podman volumes to tarballs
 59   ansible.builtin.command:
 60     cmd: podman volume export {{ item }} --output {{ backup_restore_nextcloud_export_path }}/{{ item }}.tar
 61   register: __import_tar_output
 62   changed_when: __import_tar_output.rc == 0
 63   failed_when: __import_tar_output.rc != 0
 64   loop:
 65     - "{{ NC_HTML }}"
 66     - "{{ NC_APPS }}"
 67     - "{{ NC_CONFIG }}"
 68     - "{{ NC_DATA }}"
 69     - "{{ MYSQL_DATA }}"
 70   tags:
 71     - never
 72     - backup

Collection-intern verwendete Variablen leite ich mit zwei Unterstrichen (‚_‘) ein, um mir zu verdeutlichen, dass diese nicht durch den Nutzer gesetzt werden und daher auch nicht im README.md oder defaults/main.yml dokumentiert sind.

var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex.

Hier brauche ich nicht weiter nachzuschlagen. Ich verstoße gegen diese Regel, da ich meine Variablen-Namen großgeschrieben habe. Die Ausgabe von ansible-lint zeigt dies deutlich:

var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex. (NC_HTML) (vars: NC_HTML)
roles/backup_restore_nextcloud/defaults/main.yml:4

Diese Meldungen lassen sich mit folgendem Bash-Einzeiler abstellen:

$ for text in $(cut -d':' -f 1 roles/deploy_nextcloud_with_mariadb_pod/defaults/main.yml | grep -v '^$\|^#\|---'); do find roles -type f -iname "*.yml" | xargs sed -i -e "s/$text/\L&/g"; done

Aus verschiedenen Gründen hebe ich mir die Überarbeitung für später auf und nutze die Meldung, um zu demonstrieren, wie man ansible-lint dazu bringt, bestimmte Fehler zu ignorieren.

Um Regeln für ausgewählte Dateien zu ignorieren, spezifiziert man den jeweiligen Dateinamen und den Namen der Regel in der Datei .ansible-lint-ignore, welche im Wurzelverzeichnis der Collection erstellt wird:

nextcloud]$ cat .ansible-lint-ignore 
roles/deploy_nextcloud_with_mariadb_pod/defaults/main.yml var-naming[pattern]
roles/backup_restore_nextcloud/defaults/main.yml var-naming[pattern]

Zweiter Durchgang mit ansible-lint

Damit habe ich alle Probleme, die im ersten Durchlauf von ansible-lint gefunden wurden, adressiert. Ein zweiter Durchlauf zeigt das Ergebnis meiner Arbeit:

(adt) nextcloud]$ ansible-lint --profile=shared
WARNING  Listing 33 violation(s) marked as ignored, likely already known
var-naming[pattern]: Variables names should match ^[a-z_][a-z0-9_]*$ regex. (NC_HTML) (vars: NC_HTML) (warning) # ignored
roles/backup_restore_nextcloud/defaults/main.yml:4

…Ausgabe gekürzt

WARNING  Listing 1 violation(s) that are fatal
yaml[octal-values]: Forbidden implicit octal value "0600"
roles/backup_restore_nextcloud/tasks/main.yml:22

Read documentation for instructions on how to ignore specific rule violations.

                Rule Violation Summary                 
 count tag                profile rule associated tags 
     1 yaml[octal-values] basic   formatting, yaml     

Failed: 1 failure(s), 33 warning(s) on 27 files. Profile 'shared' was required, but 'min' profile passed.

Die ignorierten Regelverstöße werden als Warnung weiterhin ausgegeben, nehmen jedoch keinen Einfluss auf die abschließende Bewertung. Dafür habe ich einen neuen Fehler (yaml[octal-values]) eingebaut. Nach dem aktuellen Regelwerk erfordern oktale Werte ein explizites Quoting, um als Strings verarbeitet zu werden.

Nachdem ich das Problem mit mode: '0600' behoben habe, endet ein weiterer Lauf von ansible-lint schlussendlich mit:

Passed: 0 failure(s), 33 warning(s) on 27 files. Profile 'shared' was required, but 'production' profile passed.

Damit erfüllt meine Collection aktuell sogar die Anforderungen des nächst höheren Profils production; allerdings nur, weil ich einige Regeln bewusst ignoriere. Daher ist aktuell noch nicht sichergestellt, dass meine Collection tatsächlich bei einem Import auf Ansible Galaxy akzeptiert wird.

Zusammenfassung

  • Ansible Lint ist ein Werkzeug zur statischen Analyse von Ansible Playbooks, Roles und Collections
  • Das Werkzeug unterstützt Autoren dabei, gängige Konventionen und Standards einzuhalten und die Qualität des eigenen Codes auf einem Mindest-Niveau zu halten
  • Ansible Lint bietet mehrere Profile für verschiedene Anwendungsfälle
  • Regeln können bei Bedarf ignoriert werden, was zwar das Ergebnis des Linting beeinflusst, die Qualität jedoch nicht steigert
  • Linting sollte fester Bestandteil des eigenen Entwicklungsworkflows sein und stets nach Änderungen durchgeführt werden

Ich persönlich führe ansible-lint gern in einem eigenständigen Schritt aus. Es besteht jedoch auch die Möglichkeit, dies in den verwendeten Editor, die genutzte IDE oder Molecule zu integrieren und bei Änderungen automatisch laufen zu lassen.

Ich freue mich, wenn euch dieser Artikel gefallen hat.

Quellen und weiterführende Links

  •  

IronOS: TS101 mit einem Bootlogo versehen

Der TS101 lässt sich, wie auch der Pinecil v2, mit einem eigenen Bootlogo versehen. Beim TS101 muss das Logo der IronOS Firmwaredatei hinzugefügt werden # Arch Linux sudo pacman -S python-pillow python-intelhex git #...

  •  

Meine zweite Ansible Collection

Dies ist ein Erfahrungsbericht zur Migration meiner Ansible-Rolle „Nextcloud im Container“ in eine Ansible Collection. Er umfasst die Migration der bestehenden Rolle und die Ergänzung der neuen Collection um eine weitere Rolle, welche sich um die Aufgaben Backup und Restore kümmert.

Wer es ganz eilig hat, kann direkt zur Zusammenfassung springen. Allen anderen wünsche ich viel Spaß bei der Lektüre.

Für grundlegende Informationen zu Ansible Collections siehe:

Randnotiz: Dass ihr zu meiner ersten Ansible Collection hier im Blog nicht fündig werdet, liegt darin begründet, dass meine Arbeit daran eingeschlafen ist.

Die Entwicklung der hier beschriebenen Collection könnt ihr auf Codeberg.org verfolgen. Die Repo-URL lautet: https://codeberg.org/Tronde/nextcloud

Motivation

Für mein Wochenendprojekt „Nextcloud im Container“ habe ich eine Ansible-Rolle entwickelt und auf Github veröffentlicht, die dem Zweck dient, Nextcloud mit einer MariaDB in einer rootless Podman-Umgebung zu installieren.

Wie ihr in Teil 5 der Artikel-Serie nachlesen könnt, war ich mit der Lösung für Backup und Restore nicht ganz zufrieden. Ich möchte dieses Thema erneut angehen und mithilfe einer Ansible-Rolle lösen.

Backup und Restore beschreiben jedoch andere Anwendungsfälle als die Bereitstellung, weswegen ich den dafür notwendigen Quelltext nicht mit in die bestehende Rolle pressen möchte. Da Backup und Restore für mich jedoch zum Betrieb dazugehören, möchte ich alle Ansible-Rollen, die ich zum Betrieb meines Nextcloud-Setups benötige, in einer Collection zusammenfassen.

Migration der bestehenden Rolle in eine Collection

Ich orientiere mich hierzu an der englischsprachigen Dokumentation „Migrating a role to a collection“. Da ich bereits einen Galaxy Namespace besitze, nutze ich diesen auch für die Erstellung der Collection. Der folgende Codeblock zeigt die verwendeten Befehle.

]$ ansible-galaxy collection init tronde.nextcloud
- Collection tronde.nextcloud was created successfully

]$ mkdir tronde/nextcloud/roles/deploy_nextcloud_with_mariadb_pod && rsync -a ../roles/ansible_role_deploy_nextcloud_with_mariadb_pod/ tronde/nextcloud/roles/deploy_nextcloud_with_mariadb_pod/

]$ tree -L 3 tronde/nextcloud/
tronde/nextcloud/
├── docs
├── galaxy.yml
├── meta
│   └── runtime.yml
├── plugins
│   └── README.md
├── README.md
└── roles
    └── deploy_nextcloud_with_mariadb_pod
        ├── defaults
        ├── meta
        ├── README.md
        ├── tasks
        ├── tests
        └── vars

]$ rm -rf tronde/nextcloud/roles/deploy_nextcloud_with_mariadb_pod/.git

Im letzten Schritt entferne ich das .git-Verzeichnis, da ich die Collection als Ganzes in einem Repository verwalten möchte, statt alle Rollen einzeln zu versionieren und dann in die Collection einzufügen.

Anschließend aktualisiere ich die Dateien galaxy.yml und README.md. In der Rolle habe ich ein Playbook zum Testen verwendet, welches im Pfad deploy_nextcloud_with_mariadb_pod/tests/test.yml liegt. Um konform mit der Struktur einer Ansible Collection zu sein, erstelle ich im Wurzelverzeichnis meiner Collection das Verzeichnis playbooks und kopiere das Test-Playbook hier hinein:

]$ tree playbooks/
playbooks/
└── deploy_nextcloud_with_mariadb_pod.yml

An dieser Stelle halte ich zunächst inne und überlege mir, welche Tools ich noch benötige, um meine Collection entwickeln und testen zu können.

Ansible Development Tools

Ansible Development Tools (ADT) ist ein Projekt mit dem Ziel, einen Werkzeugkasten mit allen wichtigen Werkzeugen zur Entwicklung von Ansible Content zu bieten. Genau so etwas habe ich gesucht. Das probiere ich gleich aus.

Um mir mein System nicht zu verhunzen, installiere ich die ADT in ein Python Virtual Environment und lasse mir anzeigen, welche Werkzeuge ADT mitbringt:

]$ python -m venv adt
]$ . adt/bin/activate
(adt) ]$ pip install --upgrade pip
(adt) ]$ pip install ansible-dev-tools
(adt) ]$ pip install molecule-podman
(adt) ]$ adt --version
ansible-builder                          3.1.0
ansible-core                             2.17.1
ansible-creator                          24.7.0
ansible-dev-environment                  24.7.0
ansible-dev-tools                        24.7.1
ansible-lint                             24.7.0
ansible-navigator                        24.7.0
ansible-sign                             0.1.1
molecule                                 24.7.0
pytest-ansible                           24.7.0
tox-ansible                              24.7.0

Bei molecule-podman handelt es sich um einen Molecule-Treiber, welcher benötigt wird um Molecule-Tests in Podman-Containern ausführen zu können. Ich habe dieses Paket mitinstalliert, da ich mir vorstellen kann, dies in naher Zukunft zu nutzen.

ansible-lint

Ansible Lint ist das erste Werkzeug aus der ADT-Sammlung, welches ich verwende, um den Quelltext meiner Collection zu prüfen. Dazu wird das Kommando einfach im Wurzelverzeichnis der Collection ausgeführt. Anschließend können die gefundenen Fehler behoben werden.

Da es den Rahmen dieses Artikels sprengen würde, werde ich dem Thema einen eigenen Text widmen.

molecule

Ansible Molecule eignet sich zum Testen von Ansible-Rollen und Collections. Ich nutze meine Ansible Collection, um mich mit diesem Werkzeug vertraut zu machen.

Zwar gibt es auch hier erst eine Lernkurve, doch wird mir eine durchdachte Test-Konfiguration bei der weiteren Entwicklung sicher zugutekommen. Ich orientiere mich zu Beginn am Ansible Molecule Getting Started Guide.

Zu Beginn möchte ich meine in die Collection migrierte Rolle testen. Dazu bearbeite ich die Datei tronde/nextcloud/extensions/molecule/default/converge.yml. Sie enthält schließlich folgenden Inhalt:

extensions]$ cat molecule/default/converge.yml 
---
- name: Converge
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Test collection role deploy_nextcloud_with_mariadb_pod
      ansible.builtin.import_role:
        name: tronde.nextcloud.deploy_nextcloud_with_mariadb_pod

Und mit folgendem Befehl teste ich, ob meine Nextcloud-Instanz erfolgreich deployt wird:

extensions]$ molecule converge
…
PLAY RECAP *********************************************************************
localhost                  : ok=10   changed=9    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

extensions]$ podman ps
CONTAINER ID  IMAGE                                    COMMAND               CREATED             STATUS             PORTS                    NAMES
48438d1bd884  quay.io/centos/centos:stream8            bash -c while tru...  7 minutes ago       Up 7 minutes                                instance
104c525a6b50  localhost/podman-pause:5.1.1-1717459200                        About a minute ago  Up About a minute  127.0.0.1:40671->80/tcp  e34ddf4d4203-infra
f27842b12d56  docker.io/library/mariadb:10.11.2        mariadbd              About a minute ago  Up About a minute  127.0.0.1:40671->80/tcp  nc_mariadb
9ee391a57fbd  docker.io/library/nextcloud:25-apache    apache2-foregroun...  13 seconds ago      Up 13 seconds      127.0.0.1:40671->80/tcp  nextcloud

Das Ergebnis ist positiv und kann durch Aufruf von http://127.0.0.1:40671 im Webbrowser überprüft werden. Ein Login mit den Default-Werten aus tronde/nextcloud/roles/deploy_nextcloud_with_mariadb_pod/defaults/main.yml bestätigt das erfolgreiche Deployment.

Es handelt sich hierbei noch nicht um ein adäquates Test-Setup; doch für den Moment ist es ausreichend. Ich werde mich noch weiter einarbeiten müssen, um das Test-Setup verbessern zu können. Vermutlich wird auch dazu dann ein weiterer Artikel folgen.

Falls sich jemand wundert, es ist durchaus Absicht, dass die Nextcloud nur via 127.0.0.1 und per HTTP erreichbar ist. Ich betreibe diese hinter einem Reverse-Proxy. Details können in Nextcloud im Container — Teil 3: Mit Reverse-Proxy nachgelesen werden.

Backup und Restore für die Nextcloud

Um die Konfiguration und die in der Nextcloud gespeicherten Daten sichern und wiederherstellen zu können, werde ich eine Offline-Sicherung der verwendeten Podman Volumes durchführen. Der Ablauf für die Sicherung sieht wie folgt aus:

  1. Den Pod ˋnc_podˋ inkl. aller darin enthaltenen Container stoppen
  2. Alle zum Setup gehörenden Podman Volumes in Tarballs exportieren
  3. Diese Tarballs vom managed Node auf den Control Node sichern
  4. Den ˋnc_podˋ wieder starten

Die Wiederherstellung läuft sinngemäß andersherum ab:

  1. Die Tarballs werden vom Control Node auf den Managed Node kopiert
  2. Der Pod ˋnc_podˋ inkl. aller darin enthaltenen Container wird gestoppt
  3. Die Podman Volumes aus Schritt 1 werden importiert
  4. Der nc_pod wird wieder gestartet
  5. Die zur Wiederherstellung auf den Managed Node kopierten Tarballs werden wieder entfernt

Um diese neue Rolle der Collection hinzuzufügen, navigiere ich in das Rollenverzeichnis tronde/nextcloud/roles/ und erstelle dort das Grundgerüst für die Rolle: ansible-galaxy role init backup_nextcloud

Die Struktur sieht bei mir wie folgt aus, wobei nicht benötigte Verzeichnisse noch nicht entfernt wurden:

ansible_collections]$ tree -L 2 tronde/nextcloud/roles/backup_restore_nextcloud/
tronde/nextcloud/roles/backup_restore_nextcloud/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

9 directories, 8 files

Den aktuellen Entwicklungsstand könnt ihr unter dieser URL einsehen: https://codeberg.org/Tronde/nextcloud/src/branch/main/roles/backup_restore_nextcloud

Das dortige README.md enthält wie bei dedizierten Rollen die Dokumentation zu dieser Rolle. Um doppelte Texte zu vermeiden, verweise ich im Collection-README auf die jeweiligen README-Dateien in den einzelnen Rollen.

Getestet wird diese Rolle ebenfalls mit Molecule. Zu den Tests mit Molecule werde ich noch mehr schreiben, sobald ich dies etwas verfeinert habe.

Fallen mir noch weitere Anwendungsfälle ein, können diese nun einfach als weitere Rollen der Collection hinzugefügt werden.

Ansible-Variablen definieren

Jede Rolle in dieser Collection ist für sich alleine nutzbar. Somit definiert jede Rolle die Eingangs-Variablen in der defaults/main.yml der jeweiligen Rolle.

Bei der Entwicklung achte ich darauf, dass Variablen, die z.B. den Namen eines Podman Volumes enthalten, in allen Rollen gleich geschrieben werden. Damit ist es möglich, diese Variablen an anderer Stelle zu definieren und in den verschiedenen Rollen nutzbar zu machen. So können an individuelle Deployments angepasste Variablen in Playbooks, group_vars, host_vars, etc. definiert werden.

Wo Variablen definiert werden können und welche Präzedenz diese besitzen, kann in der offiziellen Doku nachgelesen werden: Variable precedence: Where should I put a variable?

Zusammenfassung

Eine Ansible-Rolle ohne Plug-ins in eine Ansible Collection zu überführen, ist mit dem kurzen Abschnitt aus der Dokumentation schnell erledigt.

Weitere Rollen können der Collection hinzugefügt werden, indem man sie im Verzeichnis roles der Collection-Verzeichnisstruktur wie gewohnt mit ansible-galaxy role init <Rollenname> erstellt und mit Leben füllt. Sorgfalt ist und bleibt bei der Benennung von Variablen und deren Präzedenz geboten, um nicht wahnsinnig zu werden. Dies ist nicht wirklich schwierig, doch muss ich fast jedes Mal in der Dokumentation nachschlagen, um sicher zu sein.

Die Ansible Development Tools (ADT) sind eine praktische Sammlung von Werkzeugen zur Entwicklung von Rollen und Collections für Ansible. Für mich sind aktuell Ansible Lint und Ansible Molecule die wichtigsten Werkzeuge aus dieser Sammlung. Wobei gerade die Dokumentation von Molecule auf dem Weg zu meinem Ziel, nämlich meine Collections in verschiedenen rootless Podman Containern mit nested Podman und Ansible zu testen, leider viele Fragen offen lässt. Grundsätzlich lassen sich Testpläne damit realisieren und vereinfachen mein bisheriges Testsetup bestehend aus diversen Skripts und virtuellen Maschinen. Und sie bieten Stoff für weitere Einträge in diesem Blog.

Die weitere Entwicklung meiner Nextcloud Collection findet auf Codeberg statt. Ihr findet sie dort unter der URL: https://codeberg.org/Tronde/nextcloud

  •  

In 2024 wurde ein Lenovo T570 für Debian Cinnamon beschafft

Vor einigen Wochen habe ich um Empfehlungen für Laptop-Hardware, eine Linux-Distribution und eine Desktopumgebung gebeten. Für die vielen Rückmeldungen, die ich erhalten habe, an dieser Stelle vielen Dank.

Heute möchte ich euch wissen lassen, welche Kombination es geworden ist.

Die Hardware

Ich habe mich für ein wiederaufbereitetes Lenovo T570 entschieden, welches für günstige 240 Euro im Onlinehandel verfügbar war. Da war dann auch noch für 30 Euro ein Schutzbrief drin, der Flüssigkeiten und Stürze abdeckt.

Mit dem Intel Core-i5 der 6. Generation, 8 GB RAM und einer 256 GB SSD bietet dieses Gerät mehr als ausreichend Leistung.

Das Gerät weist einige Gebrauchsspuren auf. Den Preis empfinde ich dennoch günstig, da Geräte dieser Klasse nicht unter 1.000 Euro Neupreis zu bekommen sind. Viel wichtiger jedoch ist, dass der Nutzer sich ebenfalls über das Gerät freut.

Linux-Distribution und Desktopumgebung

Wer die Wahl hat, hat die Qual. Um mir einen ersten Eindruck zu verschaffen, habe ich mir einen USB-Stick mit Ventoy und einer Auswahl an verschiedenen Linux-Distributionen erstellt. So konnte ich die verschiedenen Live-Systeme booten und prüfen, ob alles funktioniert und wie es sich in der Oberfläche navigieren lässt.

Schlussendlich habe ich mich für Debian Cinnamon entschieden. Dies machte nach dem ersten kurzen Test insgesamt den besten Eindruck. Firefox, Thunderbird, Bookmarks, Desktop-Verknüpfungen und Zoom-Client waren schnell eingerichtet und das Gerät bereit zur Übergabe.

Die Übergabe ist erfolgt

Mit der Übergabe gab es eine kurze Einweisung in das Gerät:

  • Wo schließt man das Netzteil an
  • Wo schaltet man das Gerät ein
  • Wie meldet man sich an
  • Wo findet man die Programme inkl. Tests aller wichtigen Dienste
  • Druck eines Anhangs aus Thunderbird
  • Wie fährt man das Gerät herunter

So reibungslos hat das bisher noch nie geklappt. Die Nutzungserfahrung ist positiv. Wir freuen uns.

  •  

Was läuft auf dem Home Server?

Ende 2021 bin ich von einem Raspberry Pi 4 mit 4 GB auf einen Intel NUC7PJYH mit Proxmox VE umgestiegen. Hauptgrund damals war, dass bei mir das Upgrade von Raspberry Pi OS 10 auf...

  •  

Immich v1.109: „Unlicensed“ Meldung entfernen

Mit der Veröffentlichung von Immich v1.109.0 haben die Entwickler optionale Lizenzen angekündigt. Man bekommt nun unten links angezeigt, dass man eine unlizenzierte Version einsetzt, sofern man keine Lizenz gekauft hat. Nachfolgend beide Lizenzoptionen und...

  •  

Firefox: Wetter auf der Startseite anzeigen lassen

Seit Firefox 127 kann man sich das Wetter auf der Startseite anzeigen lassen. Startet euren Firefox, gebt in der Adresszeile about:config ein und bestätigt die Warnung. Sucht nach browser.newtabpage.activity-stream.system.showWeather und stellt den Wert mit...

  •  

Suche Empfehlungen für Hardware und Linux-Distribution

Liebe Leser*innen,
heute seid ihr gefragt. Denn ich möchte von euch wissen, welchen Laptop und welche Linux-Distribution, ihr für ältere, nicht EDV-affine Menschen und Windows-Umsteiger empfehlen könnt.

Hardware

Der Laptop soll über folgende Merkmale verfügen:

  • Größe: 15-17 Zoll
  • Webcam
  • Mikrofon und Lautsprecher
    • für Videokonferenzen
    • zum Schauen von Videos in sozialen Netzwerken
  • Linux- und Windows-Unterstützung

Die Unterstützung von Linux und Windows ist sehr wichtig. Sollte der Feldversuch mit Linux scheitern, möchte auf der gleichen Hardware ein aktuelles Windows-Betriebssystem installieren können.

Mir schwebt etwas in der Richtung der Lenovo IdeaPad oder ein ThinkPad der L-Serie vor, ich bin jedoch auf eure Empfehlungen gespannt.

Desktop-Umgebung

Ich suche nach einer Desktop-Umgebung, die folgende Merkmale bietet:

  • Ein Startmenü, welches sich in der unteren linken Ecke befindet
  • Erstellungen von Anwendungsstartern und Verknüpfungen auf der Desktopoberfläche

Dies sind Muss-Kriterien, die unbedingt erfüllt sein müssen. Ich möchte, dass die Desktopoberfläche diese Eigenschaften in der Standardkonfiguration erfüllt und ich diese nicht erst konfigurieren oder drölfzig Plug-ins installieren muss, um diesen Zustand zu erreichen.

Software

Die wichtigsten Anwendungen sind:

  • Thunderbird für E-Mail
  • Aktuelle Webbrowser (Chrome/Firefox) für den Rest
    • Facebook
    • YouTube
    • Zoom, MS Teams, Webex und wie sie alle heißen
  • Ein PDF-Anzeigeprogramm
  • Libre/Open Office zum Lesen von MS Office-Dokumenten

Linux-Distribution

Die Linux-Distribution muss die oben genannten Anforderungen an die Desktop-Umgebung und die Software erfüllen und dabei stabil allerdings nicht steinalt sein.

Ich möchte nicht vor jeder Videokonferenz mit den Audio-Einstellungen kämpfen müssen, um deutlich zu machen, wo meine Priorität liegt.

Kandidaten, die ich mir ansehen möchte, sind:

Was könnt ihr mir empfehlen? Bitte nutzt die Kommentare und verlinkt, wo möglich zu den Projekten, die ihr empfehlt.

  •  

Wie ich die Chemnitzer Linux-Tage 2024 erlebt habe

Dies ist mein Erfahrungsbericht der Chemnitzer Linux-Tage 2024. Es war mal wieder eine sehr schöne Veranstaltung.

Die Anreise

Im vergangenen Jahr hatte mich die Deutsche Bahn in Chemnitz sitzengelassen und ich musste mit einem kurzfristig angemieteten Leihwagen heimfahren.

Da die Deutsche Bahn und die Gewerkschaft Deutscher Lokomotivführer sich noch immer nicht auf einen neuen Tarifvertrag einigen können und ich mich nicht erneut über eine schlechte Verbindung ärgern wollte, bin ich dieses Jahr mit dem eigenen Pkw gefahren.

Am Freitag um 13:30 Uhr ging die Reise los. Mit viel Verkehr, Baustellen und Stau waren ich etwa 4,5 Stunden später im Hotel, wo ich direkt über Stoeps gestolpert bin.

Wir spazierten vom Residenz Hotel Chemnitz zum Veranstaltungsgebäude, um uns anzumelden und unsere Badges zu empfangen. Damit ersparten wir uns das Warten in der Schlange am Samstagmorgen.

Am Hörsaalgebäude traf ich schon erste vertraute Gesichter, wie z.B. Andreas, welcher fleißig beim Aufbau geholfen hat. Hier haben wir uns auch mit Michael von der Aspicon GmbH getroffen, mit dem ich für Sonntag einen Vortrag geplant hatte. Wir sind gemeinsam in die Stadt gegangen, um uns bei Speis und Trank kennenzulernen und den Abend zu verplaudern.

Der Samstag

Um 07:00 Uhr begann ich den Tag mit dem Frühstück. So war der erste Hunger bereits gestillt, als der Frühstücksraum sich zu füllen begann. Bekannte Gesichter und nerdige T-Shirts verrieten, dass es sich bei sehr vielen der Gäste um Besucher der Chemnitzer Linux-Tage handelte.

Die 20 Minuten zum Veranstaltungsort wurden auch diesmal wieder zu Fuß zurückgelegt. Und der erste Konferenztag konnte beginnen.

Um 10:00 Uhr war ich an der Reihe und durfte in einem rappelvollen Raum V6 meinen „::1“-Vortrag halten. An dieser Stelle euch allen nochmal vielen Dank für eure Teilnahme. Ich hoffe, ihr hattet so viel Spaß wie ich und konntet ein paar neue Eindrücke gewinnen.

Es hat mich gefreut, auch nach dem Vortrag noch einige Fragen beantworten zu können und über IPv6 zu fachsimpeln. Ganz nebenbei konnte ich auch noch die Frage eines Red Hat-Kunden beantworten. Darüber freute sich dieser sehr, bleibt ihm der Support eine zufriedenstellende Antwort doch seit langer Zeit schuldig. Es ist halt stets eine gute Erfahrung, einen TAM zu treffen.

Die Chemnitzer Linux-Tage gibt es übrigens schon seit 25 Jahren. Da eine Veranstaltung aufgrund der Pandemie ausfallen musste, findet die 25. Veranstaltung allerdings erst im nächsten Jahr am 22. und 23. März statt.

20-jähriges Jubiläum feiert in diesem Jahr Ubuntu, weshalb der Community-Stand dieses Jahr besonders schön geschmückt war und toddy mehrfach mit Luftschlangen gefesselt wurde.

Ich genieße die Zeit unter gleichgesinnten Nerds oder wie Stoeps es ausdrückte: „Endlich wieder unter normalen Menschen“. Mich hat es dieses Jahr sehr gefreut, auch viele jüngere Gesichter zu sehen. So sehr ich mich freue, auch die gleichen alten Nasen immer wiederzutreffen ist es doch schön, dass die Gemeinschaft nicht einfach alt wird, sondern auch junge Menschen mit Interesse, Motivation und Freude an Open Source nachwachsen.

Da die Hörsäle hier bei den Vorträgen meist aus allen Nähten platzen, hatte ich mich im Vorfeld als Sessionleitung für die drei Vorträge

  1. Never ever break userspace – was das in der Praxis bedeutet von Wolfram Sang
  2. DIY Verified Boot in 2024 von Marco Felsch und
  3. VirtualBox Meets KVM von Julian Stecklina

gemeldet. So war mir ein guter Platz im Raum sicher. Ich danke den drei Referenten für ihre interessanten Vorträge.

Am Abend waren alle Aussteller, Helfer und Referenten zum gemütlichen Beisammensein in die Mensa eingeladen, welche schräg gegenüber dem Veranstaltungsgebäude liegt. Hier gab es ein reichhaltiges Angebot an warmem und kaltem Essen sowie eine Auswahl verschiedenster Getränke. Vielleicht ist es in der Zukunft möglich, die Getränke zu kühlen. Dann wird das Bier nicht so schnell warm und schmeckt länger gut.

Ich schätze es sehr, mich auf Konferenzen mit alten und neuen Bekannten auszutauschen, zu fachsimpeln und ganz allgemein angeregte Gespräche zu führen. Das musikalische Rahmenprogramm traf auch in diesem Jahr nicht meinen Geschmack. Ich würde mir etwas Hintergrundberieselung wünschen, um sich gut unterhalten zu können. Doch sind Geschmäcker verschieden und ich erkenne durchaus an, was das Organisations-Team der Chemnitzer Linux-Tage hier Jahr für Jahr auf die Beine stellt. Euch allen vielen Dank für euren unermüdlichen Einsatz.

Der Sonntag

Nach einem frühen Frühstück und Check-out ging es heute mit dem Auto zum Veranstaltungsgelände. Noch vor dem zweiten Kaffee wurden hier die Folien für den nächsten Vortrag nochmal geprüft. Um 10:00 Uhr war es wieder soweit. Diesmal durfte ich zusammen mit Michael den Vortrag „Mit Ansible Collections & Workflows gegen das Playbook-Chaos“ halten.

@Michael: „Es hat mir gut gefallen, mit dir einen Vortrag zu halten. Das können wir gerne wiederholen.“

Beim Mittagessen habe ich dann auch noch Christian getroffen. Für ihn waren es die ersten Chemnitzer Linux-Tage und auch ihm haben sie sehr gut gefallen.

Und wie immer war die Zeit auch viel zu schnell wieder vorbei. So habe ich Henning zwar kurz gesehen, doch für mehr als ein kurzes „Hi und Tschüss, bis zum nächsten Mal“ reichte es diesmal leider nicht.

Die Heimreise

Auch die schönsten Chemnitzer Linux-Tage gehen vorbei. Doch im Auto sitzend freute ich mich auch schon darauf, meine Familie wiederzusehen. Die Straße war frei und nach nur 3 Stunden 20 Minuten war ich wieder daheim. Zum Vergleich, mit der Bahn wäre ich je nach Verbindung erst nach 5,5-6,5 Stunden daheim gewesen, wenn alles nach Plan fährt.

So konnte ich mehr Zeit vor Ort verbringen und war rechtzeitig daheim, um noch etwas Zeit mit meinem Sohn zu verbringen, bevor dieser ins Bett ging.

Fazit

Es war schön. Ich hoffe, ihr seid alle wieder gut heimgekommen und behaltet auch diese Chemnitzer Linux-Tage in guter Erinnerung.

Weitere Berichte über die CLT 2024

  •  

Mit einem Dualstack-Reverse-Proxy Internet-Protokolle verbinden

Mit einem Dualstack-Proxy Internet-Protokolle verbinden beschrieb eine Möglichkeit, um von Hosts, welche ausschließlich über IPv6-Adressen verfügen, auf Ziele zugreifen zu können, die ausschließlich über IPv4-Adressen verfügen. In diesem Beitrag betrachte ich die andere Richtung.

Zu diesem Beitrag motiviert hat mich der Kommentar von Matthias. Er schreibt, dass er für den bei einem Cloud-Provider gehosteten Jenkins Build Server IPv4 deaktivieren wollte, um Kosten zu sparen. Dies war jedoch nicht möglich, da Kollegen aus einem Co-Workingspace nur mit IPv4 angebunden sind und den Zugriff verloren hätten.

Doch wie kann man nun ein IPv6-Netzwerk für ausschließlich IPv4-fähige Clients erreichbar machen, ohne für jeden Host eine IPv4-Adresse zu buchen? Dazu möchte ich euch anhand eines einfachen Beispiels eine mögliche Lösung präsentieren.

Vorkenntnisse

Um diesem Text folgen zu können, ist ein grundsätzliches Verständnis von DNS, dessen Resource Records (RR) und des HTTP-Host-Header-Felds erforderlich. Die Kenntnis der verlinkten Wikipedia-Artikel sollte hierfür ausreichend sein.

Umgebung

Zu diesem Proof of Concept gehören:

  • Ein Dualstack-Reverse-Proxy-Server (HAProxy) mit den DNS-RR:
    • haproxy.example.com. IN A 203.0.113.1
    • haproxy.example.com IN AAAA 2001:DB8::1
  • Zwei HTTP-Backend-Server mit den DNS-RR:
    • www1.example.com IN AAAA 2001:DB8::2
    • www2.example.com IN AAAA 2001:DB8::3
  • Zwei DNS-RR:
    • www1.example.com IN A 203.0.113.1
    • www2.example.com IN A 203.0.113.1
  • Ein Client mit einer IPv4-Adresse

Ich habe mich für HAProxy als Reverse-Proxy-Server entschieden, da dieser in allen Linux- und BSD-Distributionen verfügbar sein sollte und mir die HAProxy Maps gefallen, welche ich hier ebenfalls vorstellen möchte.

Der Versuchsaufbau kann wie folgt skizziert werden:

Ein Dualstack-Reverse-Proxy-Server (B) verbindet IPv4-Clients mit IPv6-Backend-Servern

HAProxy-Konfiguration

Für dieses Minimal-Beispiel besteht die HAProxy-Konfiguration aus zwei Dateien, der HAProxy Map hosts.map und der Konfigurationsdatei poc.cfg.

~]$ cat /etc/haproxy/conf.d/hosts.map 
www1.example.com	serversa
www2.example.com	serversb

Eine HAProxy Map besteht aus zwei Spalten. In der ersten Spalte stehen die FQDNs, welche vom HTTP-Client aufgerufen werden können. In der zweiten Spalte steht der Name des Backends aus der HAProxy-Konfiguration, welcher bestimmt, an welche Backend-Server eine eingehende Anfrage weitergeleitet wird. In obigem Beispiel werden Anfragen nach www1.example.com an das Backend serversa und Anfragen nach www2.example.com an das Backend serversb weitergeleitet.

Die HAProxy Maps lassen sich unabhängig von der HAProxy-Konfigurations-Datei pflegen und bereitstellen. Map-Dateien werden in ein Elastic Binary Tree-Format geladen, so dass ein Wert aus einer Map-Datei mit Millionen von Elementen ohne spürbare Leistungseinbußen nachgeschlagen werden kann.

Die HAProxy-Konfigurations-Datei poc.cfg für dieses Minimal-Beispiel ist ähnlich simpel:

~]$ cat /etc/haproxy/conf.d/poc.cfg 
frontend fe_main
	bind :80
	use_backend %[req.hdr(host),lower,map(/etc/haproxy/conf.d/hosts.map)]

backend serversa
	server server1 2001:DB8::1:80
backend serversb
	server server1 2001:DB8::2:80

In der ersten Zeile wird ein Frontend mit Namen fe_main definiert. Zeile 2 bindet Port 80 für den entsprechenden Prozess und Zeile 3 bestimmt, welches Backend für eingehende HTTP-Anfragen zu nutzen ist. Dazu wird der HTTP-Host-Header ausgewertet, falls notwendig, in Kleinbuchstaben umgewandelt. Mithilfe der Datei hosts.map wird nun ermittelt, welches Backend zu verwenden ist.

Die weiteren Zeilen definieren zwei Backends bestehend aus jeweils einem Server, welcher auf Port 80 Anfragen entgegennimmt. In diesem Beispiel sind nur Server mit IPv6-Adressen eingetragen. IPv4-Adressen sind selbstverständlich auch zulässig und beide Versionen können in einem Backend auch gemischt auftreten.

Kann eine HTTP-Anfrage nicht über die hosts.map aufgelöst werden, läuft die Anfrage in diesem Beispiel in einen Fehler. Für diesen Fall kann ein Standard-Backend definiert werden. Siehe hierzu den englischsprachigen Artikel Introduction to HAProxy Maps von Chad Lavoie.

Der Kommunikationsablauf im Überblick und im Detail

Der Kommunikationsablauf im Überblick

Von einem IPv4-Client aus benutze ich curl, um die Seite www1.example.com abzurufen:

~]$ curl -4 -v http://www1.example.com
* processing: http://www1.example.com
*   Trying 203.0.113.1:80...
* Connected to www1.example.com (203.0.113.1) port 80
> GET / HTTP/1.1
> Host: www1.example.com
> User-Agent: curl/8.2.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< server: nginx/1.20.1
< date: Sat, 06 Jan 2024 18:44:22 GMT
< content-type: text/html
< content-length: 5909
< last-modified: Mon, 09 Aug 2021 11:43:42 GMT
< etag: "611114ee-1715"
< accept-ranges: bytes
< 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
	<head>
		<title>Test Page for the HTTP Server on Red Hat Enterprise Linux</title>

Der FQDN www1.example.com wird mit der IPv4-Adresse 203.0.113.1 aufgelöst, welche dem Host haproxy.example.com gehört. Bei der Zeile Host: www1.example.com handelt es sich um den HTTP-Host-Header, welchen der HAProxy benötigt, um das richtige Backend auszuwählen.

Es ist zu sehen, dass wir eine Antwort von einem NGINX-HTTP-Server erhalten. Der HTML-Quelltext wurde gekürzt.

Damit ist es gelungen, von einem IPv4-Client eine Ressource abzurufen, die von einem IPv6-Server bereitgestellt wird.

Im Access-Log des Backend-Servers mit der IPv6-Adresse 2001:DB8::2 sieht man:

2001:DB8::1 - - [06/Jan/2024:19:44:22 +0100] "GET / HTTP/1.1" 200 5909 "-" "curl/8.2.1" "192.0.2.1"

Die Anfrage erreicht den Backend-Server von der IPv6-Adresse des haproxy.example.com (2001:DB8::1). Die am Ende der Zeile zu sehende IPv4-Adresse (192.0.2.1) gehört dem IPv4-Client, von dem ich die Anfrage gesendet habe.

Gedanken zur Skalierung

In diesem Beispiel sind die Server www1.example.com und www2.example.com über ihre IPv6-Adressen direkt erreichbar. Nur die Client-Anfragen von IPv4-Clients laufen über den Reverse-Proxy. Wenn man es wünscht, kann man selbstverständlich sämtliche Anfragen (von IPv4- und IPv6-Clients) über den Reverse-Proxy laufen lassen.

In kleinen Umgebungen kann man einen Reverse-Proxy wie HAProxy zusammen mit Squid (vgl. Artikel Mit einem Dualstack-Proxy Internet-Protokolle verbinden) auf einem Host laufen lassen. Selbstverständlich kann man sie auch auf separate Hosts verteilen.

Hochverfügbarkeit lässt sich auch hier mit keepalived nachrüsten:

Abschließende Gedanken

Die Internet-Protokolle IPv4 und IPv6 werden wohl noch eine ganze Zeit gemeinsam das Internet bestimmen und parallel existieren. Ich bin mir sogar sicher, dass ich das Ende von IPv4 nicht mehr miterleben werde. Dualstack-(Reverse)-Proxy-Server stellen eine solide und robuste Lösung dar, um beide Welten miteinander zu verbinden.

Sicher bleiben noch ausreichend Herausforderungen übrig. Ich denke da nur an Firewalls, Loadbalancer, NAT und Routing. Und es werden sich auch Fälle finden lassen, in denen Proxyserver nicht infrage kommen. Doch mit diesen Herausforderungen beschäftige ich mich dann in anderen Artikeln.

Quellen und weiterführende Links

  •  

Zeichen setzen – auf den Chemnitzer Linux-Tagen 2024

In drei Wochen beginnen die Chemnitzer Linux-Tage 2024 mit dem diesjährigen Motto „Zeichen setzen“. Am 16. und 17. März erwartet euch im Hörsaalgebäude an der Richenhainer Straße 90 ein vielfältiges Programm an Vorträgen und Workshops. Hier finden sich Vorträge für interessierte Neueinsteiger wie für alte Hasen.

So geht es am Samstag im Einsteigerforum beispielsweise um die Digitalisierung analoger Fotos, das Erstellen von Urlaubsvideos mit der Software OpenShot oder die Verschlüsselung von E-Mails. In der Rubrik „Schule“ gibt Arto Teräs einen Einblick in den Einsatz der Open-Source-Lösung Puavo an finnischen und deutschen Schulen. Zusätzlich stehen Vorträge aus den Bereichen Finanzen, Medien, Datensicherheit, KI oder Netzwerk auf dem Programm. Am Sonntag gibt das Organisationsteam der Chemnitzer Linux-Tage mit „make CLT“ Einblicke in die Planung und Strukturen der Veranstaltung selbst. In der Rubrik „Soft Skills” wird es um die Schätzung von Aufwänden oder notwendige Fähigkeiten von Software-Entwicklern gehen.

Eintrittskarten können online im Vorverkauf und an der Tageskasse erworben werden. Kinder bis 12 Jahren haben freien Eintritt.

Während viele Besucher bereits Stammgäste sind, werden auch neue Gesichter herzlich willkommen. Lasst euch gern von der hier herrschenden Atmosphäre voller Begeisterung für freie Software und Technik anstecken und begeistern.

Ich selbst freue mich, am Samstag um 10:00 Uhr in V6 den Vortrag mit dem obskuren Namen ::1 beisteuern zu dürfen. Update: Unverhofft kommt oft. Uns so freue ich mich am Sonntag um 10:00 Uhr in Raum V7 noch in einem zweiten Vortrag vertreten zu sein. Zusammen mit Michael Decker von der ASPICON GmbH erfahrt ihr, wie man „Mit Ansible Collections & Workflows gegen das Playbook-Chaos“ angehen kann.

Darüber hinaus beteilige ich mich als Sessionleiter für die folgenden drei Vorträge an der Veranstaltung:

So habe ich auf jeden Fall einen Platz im Raum sicher. ;-)

Wer ebenfalls helfen möchte, kann sich unter Mitmachen! informieren und melden.

Für mich ist dieses Jahr einiges im Programm dabei. Doch freue ich mich ebenso sehr auf ein Wiedersehen mit alten Bekannten aus der Gemeinschaft und darauf, neue Gesichter (Namen kann ich mir meist erst Jahre später merken) kennenzulernen.

Also bis bald in der Karl-Marx-Stadt.

Chemnitzer Linux-Tage Banner
  •  

Glücksmomente und Zeiten der Schmerzen mit IPv6

Am 16. und 17. März 2024 werde ich euch auf den Chemnitzer Linux-Tagen um 10:00 Uhr in Raum V6 mit einem Vortrag über IPv6 unterhalten.

Dazu bin ich noch auf der Suche nach ein paar Beispielen aus dem echten Leben. Falls ihr mögt, teilt mir doch eure schönsten und schlimmsten Momente im Zusammenhang mit IPv6 mit und ich prüfe, ob ich sie in meinen Vortrag mit einbauen kann.

  • Wann und wie hat IPv6 euren Tag gerettet?
  • Wieso hat euch das Protokoll Alpträume beschehrt?
  • Was funktioniert wider Erwarten immer noch nicht mit IPv6?
  • Habt ihr lustige Geschichten, die ihr (anonym) mit der Welt teilen möchtet?

Ich freue mich über Einsendungen, Beiträge und Rückmeldungen:

Bitte schreibt dazu, ob ihr eine Namensnennung wünscht oder euer Beispiel anonym einfließen soll.

Um einen runden Vortrag zu erstellen, wird evtl. nicht jeder Beitrag einfließen können. Bitte habt Verständnis dafür und verzeiht, wenn ihr euch nicht im Vortrag wiederfindet. Ich werde eure Geschichten ggf. im Nachgang hier im Blog veröffentlichen.

Bis neulich in Chemnitz. :-)

  •  

Mit einem Dualstack-Proxy Internet-Protokolle verbinden

Stellt euch vor, ihr habt eine Menge von Servern, welche ausschließlich über IPv6-Adressen verfügen und deshalb keine Dienste nutzen können, welche nur über IPv4 bereitgestellt werden. Wer sich dies nicht vorstellen mag, findet in „IPv6… Kein Anschluss unter dieser Nummer“ ein paar Beispiele dafür.

Was kann man nun tun, damit diese IPv6-only-Hosts dennoch mit der IPv4-only-Welt kommunizieren können?

Eine mögliche Lösung ist die Nutzung eines Dualstack-Proxy-Servers. Das ist ein Server, welcher über Adressen beider Internet-Protokoll-Versionen verfügt und so stellvertretend für einen IPv6-Host mit einem IPv4-Host kommunizieren kann. Das folgende Bild veranschaulicht den Kommunikationsablauf:

Ablauf der Netzwerkkommunikation eines IPv6-Hosts mit einem IPv4-Host über einen Dualstack-Proxy-Server

Im Bild ist zu sehen:

  1. Wie IPv6-Host A eine Verbindung über IPv6 zum Proxy-Server B aufbaut und diesem bspw. die gewünschte URL mitteilt
  2. Der Proxy-Server B baut nun seinerseits eine IPv4-Verbindung zu IPv4-Host C auf, welcher die gewünschten Inhalte bereitstellt
  3. IPv4-Host C sendet seine Antwort über IPv4 an den Proxy-Server
  4. Der Proxy-Server sendet die gewünschten Inhalte anschließend via IPv6 an den IPv6-Host A zurück
Screencast zur Demonstration der Proxy-Nutzung

Das obige Video demonstriert die Nutzung eines Proxy-Servers durch den Abruf einer Demo-Seite mit curl:

  1. Mit dem host-Kommando wird gezeigt, dass für die Demo-Seite kein AAAA-Record existiert; die Seite ist also nicht via IPv6 erreichbar
  2. Mit dem ip-Kommando wird geprüft, dass der Host auf dem Interface ens18 ausschließlich über IPv6-Adressen verfügt
  3. Ohne Proxy ist die Demo-Seite nicht abrufbar
  4. Erst durch Nutzung des Proxys kann die Seite abgerufen werden

Funktioniert das auch von IPv4 nach IPv6?

Ja. Entscheidend ist, dass der verwendete Proxy beide IP-Versionen unterstützt.

Welcher Proxy ist empfehlenswert?

Der Proxy-Server muss beide IP-Versionen beherrschen. Ich persönlich bevorzuge Squid. Dieser ist in so gut wie allen Linux-Distributionen verfügbar, weit verbreitet, robust und selbstverständlich Freie Software.

Sind damit alle Herausforderungen bewältigt?

Für eine Virtualisierungs-Umgebung mit einer IPv4-Adresse und einem /64-IPv6-Netzsegment funktioniert diese Lösung gut. Sie funktioniert auch in jeder anderen Umgebung, wie gezeigt. Man beachte jedoch, dass man mit nur einem Proxy einen Single-Point-of-Failure hat. Um diesem zu begegnen, kann man Squid mit keepalived hochverfügbar gestalten.

Keepalived ist ebenfalls Freie Software. Sie kostet kein Geld, erhöht jedoch die Komplexität der Umgebung. Verfügbarkeit vs. Komplexität möge jeder Sysadmin selbst gegeneinander abwägen.

Wie mache ich meine IPv6-Dienste für IPv4-User erreichbar, die keinen Proxy haben?

Das Stichwort lautet Reverse-Proxy. Ein Artikel dazu erscheint in Kürze in diesem Blog. ;-)

Weiterführende Quellen und Links

  •  

Der My-IT-Brain Jahresrückblick 2023

Das Jahr 2024 ist nun schon zwei Wochen alt. Dennoch möchte ich noch einen Blick zurückwerfen und mich erinnern, wie das Jahr 2023 für meinen Blog verlaufen ist.

In 2023 wurden auf My-IT-Brain insgesamt 45 Artikel veröffentlicht. Dies sind 16 mehr als in 2022 und 14 mehr als in 2021. Jeden Monat sind mindestens zwei Artikel veröffentlicht worden.

Die Themen waren dabei wieder bunt gemischt. Allein Artikel über die Red Hat Enterprise Linux (RHEL) System Roles zogen sich wie ein roter Faden durch den Blog. Welche Artikel haben denn euch am besten gefallen? Lasst es mich gerne in den Kommentaren wissen.

Ich hoffe, es war für jeden von euch etwas Interessantes mit dabei und ihr folgt diesem Blog auch in 2024. Ihr könnt mir auch gerne Anregungen in die Kommentare schreiben, welche Themen ihr hier gerne behandelt sehen wollt. Vielleicht greife ich ja einige davon auf.

Und nun aber auf in ein spannendes Jahr 2024!

  •  

IPv6… Kein Anschluss unter dieser Nummer

Das Jahr 2023 neigt sich langsam dem Ende zu. In diesem Monat for 25 Jahren wurde das IPv6-Protokoll in RFC 2460 beschrieben, bevor es 2017 in RFC 8200 als Internet-Standard von der Internet Engineering Task Force (IETF) veröffentlicht wurde.

Seit immerhin sechs Jahren ist dieses IP-Protokoll also schon standardisiert. Da sollte man doch meinen, dass man im Jahr 2023 problemlos ein vernetztes System betreiben kann, welches nur mit einer IPv6-Adresse mit dem Internet verbunden ist. Leider ist dem nicht so.

In den folgenden kurzen Abschnitten schreibe ich mir meinen Frust von der Seele und dokumentiere, was heute alles mit IPv6 noch nicht geht. Falls ihr weitere Fälle ergänzen möchtet, nutzt gerne die Kommentare, um eurem IPv6-Frust Luft zu machen.

Red Hat Satellite 6.14

Bei der Planung einer Red Hat Satellite 6.14 Installation bin ich über folgenden Satz in der Dokumentation gestolpert:

You can install Satellite and Capsules in IPv6-only systems, dual-stack installation is not supported.

URL: https://access.redhat.com/documentation/en-us/red_hat_satellite/6.14/html/installing_satellite_server_in_a_connected_network_environment/preparing-environment-for-installation-in-ipv6-network_satellite

Das ist schade. Betreibt man Server in IPv4- und IPv6-Netzwerken und möchte eine vollständig unterstützte Lösung, muss man aktuell zwei Satellite installieren.

Ich wollte jedoch einen Satellite in einer reinen IPv6-Umgebung installieren, daher sollte mich diese Anmerkung nicht weiter stören. Da störten mich folgende Stellen im gleichen Kapitel der Dokumentation schon mehr:

You must deploy an external IPv4 HTTP proxy server. This is required because Red Hat Content Delivery Network distributes content only over IPv4 networks, therefore you must use this proxy to pull content into the Satellite on your IPv6 network.

You must configure Satellite to use this IPv4 HTTP proxy server as the default proxy. For more information, see Adding a Default HTTP Proxy to Satellite.

URL: https://access.redhat.com/documentation/en-us/red_hat_satellite/6.14/html/installing_satellite_server_in_a_connected_network_environment/preparing-environment-for-installation-in-ipv6-network_satellite#requirements-for-installation-in-an-ipv6-network_satellite

Zuerst wollte ich dies nicht glauben, habe einen Fehler in der Dokumentation vermutet. Es ist 2023 und Content Delivery Network (CDN) von Red Hat unterstützt kein IPv6? Das kann doch nicht sein! Kann es doch:

Der zweite Link in obiger Liste führt ausschließlich IPv4-Adressen auf. Einzelne Kommentare lassen darauf schließen, dass es jedoch durchaus Interesse an IPv6-Konnektivität gibt. Also installiere ich erstmal einen Proxy-Server mit Dual-Stack, damit ich Hosts aus einem reinen IPv6-Netzwerk via subscription-manager register beim Red Hat Subscription Management (RHSM) registrieren kann.

subscription-manager cli command does not support IPv6 proxy

Nachzulesen in:

Die gute Nachricht, es sind gefixte Versionen für RHEL 9 und RHEL 8 in Aussicht. Auf einen Fix für RHEL 7 würde ich nicht warten und diese Systeme lieber migrieren oder aktualisieren, ist das Support-Ende doch bereits nah.

Also lege ich mein Vorhaben erstmal beiseite und wende mich anderen Wochenendprojekten zu, die vielleicht mehr Erfolg versprechen.

ansible-galaxy does not work on IPv6 only hosts

Nun guck an, da ist mein Kollege Andreas also schon im Jahr 2022 in den Ansible-Issue #77308 gelaufen. Ihr interessiert euch für den aktuellen Stand dieser Geschichte? Siehe:

So langsam komme ich mir vor wie ein bekannter spanischer Junker, welcher gegen Windmühlen pardon Riesen anritt. Aber es ist ja nicht so, dass mir die Themen ausgehen. Klone ich mir halt ein Repo von Github und trage ein bisschen zu Open Source bei…

IPv6 support for cloning Git repositories #10539

Ich spare mir viele Worte und präsentiere nur folgenden Code-Block:

$ host -t AAAA github.com
github.com has no AAAA record

URL zur Diskussion: https://github.com/orgs/community/discussions/10539

Auch hier kein Anschluss unter dieser Nummer.

Fazit

Ich möchte meine jüngsten Erfahrungen umschreiben mit: „An manchen Tagen hat man kein Glück und an anderen kommt auch noch Pech dazu.“

Für Red Hat möchte ich sagen, ist es ein Priorisierungs-Thema. Wenn der Wunsch nach IPv6 auf Kundenseite hinreichend groß wird, wird man hier handeln. Bei Github wird es ähnlich sein. Ich muss vielleicht nur nochmal 25 Jahre warten.

  • Welche Erfahrungen habt ihr mit IPv6 gemacht?
  • Habt ihr es schon an den Nagel gehängt; oder bleibt ihr hartnäckig und gebt nicht auf?
  • Ich freue mich auf eure schönsten Fehlschläge und Erfolgsmomente.
  •  

RHEL System Roles: nbde_client

In diesem Artikel stelle ich euch die RHEL System Role nbde_client vor, mit welcher sich Hosts für Network Bound Disk Encryption (NBDE) installieren lassen. Er ist Bestandteil einer losen Serie, in der ich eine Reihe von System Roles vorstelle, mit denen häufig anfallende Aufgaben in der Systemadministration erledigt werden können.

Wer sich zuerst über die genannten Begriffe informieren möchte, lese:

Umgebung

Für das folgende Beispiel verwende ich eine Umgebung, bestehend aus:

  • Einem Ansible-Controller (RHEL 9) mit den Paketen
    • ansible-core
    • rhel-system-roles
  • Jeweils einem RHEL 8 und RHEL 9 Server mit Minimalinstallation und einem LUKS-Gerät (/dev/sdc in den Beispielen in diesem Text)

Die Installation von RHEL sowie der genannten Pakete sind nicht Bestandteil dieses Artikels. Wer hierzu einen Einstieg sucht, findet entsprechende Dokumentation unter:

Die Rolle

Durch die Installation des Pakets rhel-system-roles existiert diese Rolle bereits auf meinem System und muss nur noch konfiguriert werden. Die Rolle selbst findet man im Pfad /usr/share/ansible/roles/rhel-system-roles.nbde_client/ und die Dokumentation in /usr/share/doc/rhel-system-roles/nbde_client/README.md. Letztere enthält verschiedene Beispiele für häufige Anwendungsfälle.

Anwendungsfall

In meinem Labor betreibe ich zwei NBDE-Server (TANG-Server) rhel-hetz-tang1 und rhel-hetz-tang2 sowie zwei NBDE-Clients (Clevis-Clients) rhel-hetz-clevis1 und rhel-hetz-clevis2. Die beiden NBDE-Clients besitzen jeweils ein LUKS-Device /dev/sdc, welches aktuell durch eine LUKS-Passphrase gesichert ist.

Zukünftig sollen diese LUKS-Devices durch die Kommunikation mit einem NBDE-Server entschlüsselt werden. Die LUKS-Passphrase soll entfernt werden.

Damit wird zukünftig ein Neustart der Clients aus der Ferne ermöglicht. Gleichzeitig bleibt das verschlüsselte Gerät bei Diebstahl vor unbefugtem Zugriff geschützt.

Das Playbook

Hinweis: Das folgende Playbook ist nicht idempotent. Um dies zu ändern, ist dem ersten Task eine Bedingung hinzuzufügen, damit dieser nur dann ausgeführt werden, wenn die Bedingung erfüllt ist.

Für dieses Beispiel ist die fehlende Idempotenz des Playbooks jedoch kein Problem, da grubby das Argument nur dann hinzufügt, wenn es nicht bereits vorhanden ist.

---
- hosts: clevis
  tasks:
  - name: Configure ip address for interface during early boot
    ansible.builtin.command:
      cmd: grubby --update-kernel=ALL --args='GRUB_CMDLINE_LINUX_DEFAULT="net.ifnames=0 biosdevname=0 ip={{ ansible_default_ipv4.address }}::{{ ansible_default_ipv4.gateway }}:{{ ansible_default_ipv4.netmask }}::{{ ansible_default_ipv4.alias }}:none"'

  - name: Enroll Clevis clients
    include_role:
      name: rhel-system-roles.nbde_client
    vars:
      nbde_client_bindings:
        - device: /dev/sdc
          encryption_password: "{{ luks_password }}"
          password_temporary: true
          slot: 2
          servers:
            - http://rhel-hetz-tang1.example.com
            - http://rhel-hetz-tang2.example.com
  • Der erste Task stellt sicher, dass das Netzwerkinterface aktiviert und mit einer IP-Adresse konfiguriert wird; dies ist notwendig, um den Tang-Server kontaktieren zu können, da in dem genutzten Netzwerk-Segment kein DHCP verfügbar ist; Solltet ihr ein Netzwerk-Segment nutzen, in dem DHCP zur Verfügung steht, kann der erste Task entfallen
  • Um das LUKS-Device für NBDE zu konfigurieren wird die LUKS-Passphrase benötigt, welche in der Variablen luks_password steckt
  • Ich empfehle die Variable luks_password mit ansible-vault vor neugierigen Blicken zu schützen
  • Durch password_temporary: true wird die LUKS-Passphrase aus dem jeweiligen Key-Slot gelöscht, nachdem das LUKS-Device für NBDE konfiguriert wurde

Achtung (I know, the warning comes after the spell): Wenn zur Laufzeit ein Fehler auftritt und der Key-Slot mit der LUKS-Passphrase bereits gelöscht wurde, die NBDE-Konfiguration jedoch nicht erfolgreich war, verliert man Zugriff auf das LUKS-Device. In meiner Labor-Umgebung bin ich das Risiko eingegangen. In der echten Welt, müsst ihr selbst entscheiden, ob ihr mehr Vorsicht walten lasst.

Fazit

Zur Erstellung des Playbooks habe ich die Informationen aus /usr/share/doc/rhel-system-roles/nbde_client/README.md und dem Kapitel 12.18. Using the nbde_client System Role for setting up multiple Clevis clients genutzt. Bis ich festgestellt habe, dass ich auch noch den Task „Configure ip address for interface during early boot“ benötige, hat es ein wenig gedauert. Nun habe ich allerdings ein Playbook, dass ich zukünftig wiederverwenden kann.

In der erstellten Konfiguration, können die LUKS-Devices nur entschlüsselt werden, wenn mindestens einer der beiden Tang-Server im Netzwerk erreichbar ist. Wird ein so gesicherter Server gestohlen und sind die Tang-Server nicht aus dem Internet erreichbar, bleiben die Daten in der verschlüsselten Partition wie gewohnt geschützt. Es ist jedoch möglich den Server neuzustarten, ohne manuell die LUKS-Passphrase an der Konsole eingeben zu müssen.

Quellen und weiterführende Links

  1. Red Hat Enterprise Linux (RHEL) System Roles {en}
  2. Ansible Documentation: Role Directory Structure {en}
  3. Red Hat Software and Download Center {en}
  4. Die Vorteile einer Red Hat Subskription
  5. RHEL System Roles: selinux
  6. RHEL System Roles: timesync
  7. RHEL System Roles: sshd
  8. RHEL System Roles: firewall
  9. RHEL System Roles: rhc
  10. RHEL System Roles: nbde_server
  •  

RHEL System Roles: nbde_server

In diesem Artikel stelle ich euch die RHEL System Role nbde_server vor, mit welcher sich Tang-Server für Network Bound Disk Encryption (NBDE) installieren lassen. Er ist Bestandteil einer losen Serie, in der ich eine Reihe von System Roles vorstelle, mit denen häufig anfallende Aufgaben in der Systemadministration erledigt werden können.

Wer sich zuerst über die genannten Begriffe informieren möchte, lese zuerst:

Im folgenden Text verwende ich die Begriffe NBDE-Server und Tang-Server synonym. Bitte lasst euch dadurch nicht verwirren.

Umgebung

Für das folgende Beispiel verwende ich eine Umgebung, bestehend aus:

  • Einem Ansible-Controller mit den Paketen (RHEL 9)
    • ansible-core
    • rhel-system-roles
  • Jeweils einem RHEL 8 und RHEL 9 Server mit Minimalinstallation

Die Installation von RHEL sowie der genannten Pakete sind nicht Bestandteil dieses Artikels. Wer hierzu einen Einstieg sucht, findet entsprechende Dokumentation unter:

Die Rolle

Durch die Installation des Pakets rhel-system-roles existiert diese Rolle bereits auf meinem System und muss nur noch konfiguriert werden. Die Rolle selbst findet man im Pfad /usr/share/ansible/roles/rhel-system-roles.nbde_server/ und die Dokumentation in /usr/share/doc/rhel-system-roles/nbde_server/README.md. Letztere enthält verschiedene Beispiele für häufige Anwendungsfälle.

Ich möchte mit dieser Rolle Folgendes erreichen:

  • Installation von Tang auf den beiden Zielsystemen
  • Konfiguration von SELinux im Modus enforcing
  • Konfiguration der Host-Firewall

Das Playbook

Das Playbook ist recht übersichtlich. tang bezeichnet eine Gruppe aus meinem Ansible-Inventory, welche die Systeme enthält, die ich als NBDE-Server konfigurieren möchte.

---
- name: Manage nbde server with selinux and firewall
  hosts: tang
  vars:
    nbde_server_manage_firewall: true
    nbde_server_manage_selinux: true
  roles:
    - rhel-system-roles.nbde_server

Nach der Anwendung der Rolle lauscht der Tang-Service auf Port 80/tcp der Zielsysteme und ist aus dem Netzwerk erreichbar.

Probleme

Leider läuft es dieses Mal nicht ganz so rund wie üblich. Der Task [redhat.rhel_system_roles.selinux : Set an SELinux label on a port] schlägt auf dem RHEL 8 Host mit folgender Fehlermeldung fehl: „Failed to import the required Python library (libselinux-python)“

Das Problem und die Lösung beschreibt Red Hat in dem Solution Article: Ansible playbook fails with libselinux-python aren’t installed on RHEL8 (Login required)

Fazit

Diesmal lief es nicht ganz so reibungslos wie gewohnt.

Letztendlich konnten die beiden NBDE-Server dennoch schneller konfiguriert werden, als wäre ich der manuellen Prozedur in Chapter 12. Configuring automated unlocking of encrypted volumes using policy-based decryption gefolgt.

Die Server sind damit aufgesetzt, nächste Woche beschreibe ich, wie die Clients konfiguriert werden.

Quellen und weiterführende Links

  1. Red Hat Enterprise Linux (RHEL) System Roles {en}
  2. Ansible Documentation: Role Directory Structure {en}
  3. Red Hat Software and Download Center {en}
  4. Die Vorteile einer Red Hat Subskription
  5. RHEL System Roles: selinux
  6. RHEL System Roles: timesync
  7. RHEL System Roles: sshd
  8. RHEL System Roles: firewall
  9. RHEL System Roles: rhc
  •  

Einführung in das Advanced Intrusion Detection Environment (AIDE)

Diese Einführung gibt Antworten auf die folgenden Fragen:

  • Was ist ein Intrusion Detection System?
  • Was ist AIDE?
  • Wie installiert und konfiguriert man es?
  • Wie nutzt man AIDE?

In dieser Einführung verwendete Betriebssysteme:

  • Debian 12 (Bookworm)
  • Red Hat Enterprise Linux (RHEL) 9

Um dieser Einleitung folgen zu können, solltet ihr mit den Grundlagen der Linux-Systemadministration vertraut sein und zumindest mit den folgenden Begriffen etwas anfangen können:

Einleitung

Ein Intrusion Detection System (englisch intrusion „Eindringen“, IDS) bzw. Angriffserkennungssystem ist ein System zur Erkennung von Angriffen, die gegen ein Computersystem oder Rechnernetz gerichtet sind. Das IDS kann eine Firewall ergänzen oder auch direkt auf dem zu überwachenden Computersystem laufen und so die Sicherheit von Netzwerken und Computersystemen erhöhen. Erkannte Angriffe werden meistens in Log-Dateien gesammelt und Benutzern oder Administratoren mitgeteilt; hier grenzt sich der Begriff von Intrusion Prevention System (englisch prevention „Verhindern“, IPS) ab, welches ein System beschreibt, das Angriffe automatisiert und aktiv verhindert.

Quelle: https://de.wikipedia.org/wiki/Intrusion_Detection_System (Letzter Abruf: 2023-09-08)

Die Gruppe der Intrusion Detection Systems (IDS) untergliedert sich in:

  • Host-basierte IDS, welche auf einem Host installiert und betrieben werden
  • Netz-basierte IDS, welche auf Netzwerkkomponenten installiert werden und die Kommunikation auf Netz-Ebene überwachen
  • Hybride IDS, welche die Komponenten aus den vorstehend genannten Gruppen kombinieren

Beim AIDE handelt es sich um ein Host-basiertes IDS. Es ist unter der GPL-2.0 lizenziert.

Zweck und Nutzen des AIDE

Aus dem vorhergehenden Abschnitt ist bekannt, dass es sich bei AIDE um ein Host-basiertes System zur Angriffs- bzw. Einbruchserkennung für Linux-Systeme handelt. Es stellt ein kostengünstiges Werkzeug dar, mit dem die Integrität eines Systems überprüft werden kann.

Es soll dem Administrator helfen, zu erkennen, ob Dateien oder Verzeichnisse eines Systems hinsichtlich ihres Inhalts und bzw. oder ihrer Eigenschaften wie z.B. Berechtigungen, SELinx-Kontext, erweiterte Attribute, etc. verändert wurden.

Grundlegende Funktionsweise des AIDE

  • Die zu überwachenden Dateien und Verzeichnisse werden durch reguläre Ausdrücke in der Konfigurationsdatei bestimmt
  • Basierend auf diesen Regeln wird eine Datenbank erstellt
  • Nach dem Initialisieren der Datenbank kann AIDE dazuverwendet werden, die Integrität der Dateien und Verzeichnisse zu überprüfen
    • Die initial erstellte Datenbank dient dabei als Referenz
    • Bei folgenen Überprüfungen wird eine neue Datenbank erstellt und mit der Referenzdatenbank verglichen
  • Änderungen an überwachten Dateien und Verzeichnissen werden in der Logdatei /var/log/aide/aide.log protokolliert

Schwäche von AIDE und Host-basierter IDS im Allgemeinen

  • Programm, Konfigurationsdatei(en), Datenbank und Logdatei liegen lokal auf dem jeweiligen Host
  • Angreifer, welche lokale Dateien verändern können, können potenziell auch die zu AIDE gehörenden Dateien verändern
  • Dadurch muss die Integrität der zur Integritätsprüfung eingesetzten IDS bezweifelt werden

Um diese Schwäche zu minimieren, sind folgende Maßnahmen durch Administratoren in Erwägung zu ziehen:

  • Logdateien an einen zentralen Loghost senden
  • Die AIDE-Referenzdatenbank außerhalb des zu überwachenden Hosts speichern
  • Den Abgleich gegen die AIDE-Referenzdatenbank außerhalb des zu überwachenden Hosts durchführen

Wie diese Maßnahmen umgesetzt werden können, beschreibe ich in einem folgenden Beitrag.

Auswirkungen auf die eigene Arbeitsweise

Werden beispielsweise Konfigurationsdateien unterhalb von /etc auf Änderungen hin überwacht, wird auch jede beabsichtige Änderung protokolliert. Das Programm kann zwischen legitimen und unautorisierten Änderungen nicht unterscheiden.

Daher ist nach jeder legitimen Änderungen die Referenzdatenbank zu aktualisieren. Ich empfehle, dies als einen Schritt in den Konfiguration-Management-Workflow zu integrieren und diese Aufgabe einen Automaten wie Ansible, Chef, Puppet o.ä. erledigen zu lassen. Dies erscheint mir weniger fehleranfällig zu sein als bei einer manuellen Durchführung, wo dieser Schritt sicher gern einmal vergessen wird.

Die Installation von AIDE

AIDE ist in den Paketquellen der meisten Distributionen vorhanden und kann wie folgt installiert werden.

RHEL 9

$ sudo dnf in aide
[sudo] password for tronde: 
Updating Subscription Management repositories.
Last metadata expiration check: 2:26:44 ago on Fri 08 Sep 2023 08:16:28 PM CEST.
Dependencies resolved.
================================================================================
 Package Arch      Version            Repository                           Size
================================================================================
Installing:
 aide    x86_64    0.16-100.el9       rhel-9-for-x86_64-appstream-rpms    154 k

Transaction Summary
================================================================================
Install  1 Package

Total download size: 154 k
Installed size: 354 k
Is this ok [y/N]: 
  • Obiger Code-Block zeigt die Installationsanweisung für RHEL 9
  • Die Konfigurationdatei /etc/aide.conf besitzt im Auslieferungszustand bereits 303 Zeilen; ohne Kommentare und Leerzeilen sind es immerhin noch 161
  • Den Aufbau der Datei erklärt die Manpage aide.conf(5)
  • Um AIDE sinnvoll nutzen zu können, sollte sich jeder Administrator mit dem Inhalt von /etc/aide.conf vertraut machen; oder würdet ihr einem Firewall-Regelwerk vertrauen, das ihr nicht kennt?
  • Im Abschnitt „Gedanken zur Konfiguration von AIDE“ findet ihr meine Gedanken und Hinweise zur Konfiguration

Debian 12 (Bookworm)

$ sudo apt install aide
[sudo] password for jkastning: 
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  aide-common liblockfile-bin liblockfile1 libmhash2
Suggested packages:
  figlet
The following NEW packages will be installed:
  aide aide-common liblockfile-bin liblockfile1 libmhash2
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 372 kB of archives.
After this operation, 1064 kB of additional disk space will be used.
Do you want to continue? [Y/n]
  • Obiger Code-Block zeigt die Installationsanweisung für Debian 12
  • Neben aide werden noch die Pakete aide-common, liblockfile-bin, liblockfile1 und `libmhash2` installiert
    • Neben der Konfigurationdatei /etc/aide/aide.conf installiert Debian auch das Verzeichnis /etc/aide/aide.conf.d, in welchem sich direkt nach der Installation schon etliche Konfigurationsdateien befinden:
$ ls -l /etc/aide/aide.conf.d/ | wc -l
212
  • Auch hier empfehle ich Administratoren, sich mit der Konfiguration zu beschäftigen und sich damit vertraut zu machen (siehe dazu auch aide.conf(5))
  • Im folgenden Abschnitt „Zur Konfiguration von AIDE“ findet ihr meine Gedanken und Hinweise zur Konfiguration

Zur Konfiguration von AIDE

Während AIDE in RHEL über eine einzige Datei (/etc/aide.conf) konfiguriert wird, gibt es in Debian eine Konfigurationsdatei (/etc/aide/aide.conf) und die Verzeichnisse /etc/aide/aide.conf.d sowie /etc/aide/aide.settings.d, welche weitere Dateien zur Konfiguration und Einstellungen beinhalten.

Eine AIDE-Konfigurationsdatei aide.conf besteht aus drei verschiedenen Arten von Zeilen:

  • Optionen, welche die Konfigurationsparameter und Gruppen definieren; aufgebaut sind diese nach dem Muster Parameter = Wert bzw. Gruppenname = Wert
  • Regeln, welche bestimmen, welche Dateien und Verzeichnisse in die Datenbank aufzunehmen sind und welche Attribute überwacht werden sollen
  • Macros, mit denen sich Variablen definieren lassen; z.B. definierte @@define foo bar die Variable foo mit dem Wert bar

AIDE kann die folgenden Attribute bzw. Elemente von Dateien auf Änderungen hin überwachen:

#p:      permissions
#i:      inode
#n:      number of links
#u:      user
#g:      group
#s:      size
#b:      block count
#m:      mtime
#a:      atime
#c:      ctime
#S:      check for growing size
#acl:           Access Control Lists
#selinux        SELinux security context
#xattrs:        Extended file attributes
#md5:    md5 checksum
#sha1:   sha1 checksum
#sha256:        sha256 checksum
#sha512:        sha512 checksum
#rmd160: rmd160 checksum
#tiger:  tiger checksum

Der folgende Code-Block zeigt die Definition der beiden Gruppen NORMAL und DIR (aus der /etc/aide.conf in RHEL 9), welche spezifizieren, welche Attribute überwacht werden sollen, wenn die jeweilige Gruppe in einer Regel verwendet wird.

NORMAL = p+i+n+u+g+s+m+c+acl+selinux+xattrs+sha512

# For directories, don't bother doing hashes
DIR = p+i+n+u+g+acl+selinux+xattrs

Welche Dateien und Verzeichnisse in die AIDE-Datenbank aufzunehmen bzw. auszuschließen sind durch reguläre Ausdrücke bestimmt. Der nächste Code-Block zeigt drei Beispiele, die anschließend erläutert werden:

/etc NORMAL
=/var/log/ DIR
=/home DIR
!/dev
  • Das Verzeichnis /etc und alle darunterliegenden Dateien und Verzeichnisse werden in die AIDE-Datenbank aufgenommen und mit den Regeln aus der Gruppe NORMAL verknüpft
  • Nur das Verzeichnis /var/log/ und die direkt darunter befindlichen Dateien und Verzeichnisse werden in die AIDE-Datenbank aufgenommen und mit der Gruppe DIR verknüpft; der Inhalt der Unterverzeichnisse wird nicht in die Datenbank aufgenommen
  • Ausschließlich /home wird aufgenommen; nicht jedoch der Inhalt davon
  • Das Verzeichnis /dev und alle darunterliegenden Dateien und Verzeichnisse werden nicht in die AIDE-Datenbank aufgenommen

Initialisierung der AIDE-Datenbank

Mit Sicherheit und Vertrauen ist das immer so eine Sache. Am besten ist es stets, wenn Vertrauen für Sicherheit nicht erforderlich ist. Daher rate ich an dieser Stelle nochmals ausdrücklich, die AIDE-Konfiguration zu überprüfen und ggf. den eigenen Bedürfnissen anzupassen… Nur um direkt gegen meinen eigenen Rat zu verstoßen.

Der Umfang an Regeln ist in beiden Systemen so groß, dass ich in dieser Einführung nicht alle einzeln erläutern kann. Ich vertraue für diese Einführung daher darauf, dass die Distributionen eine sinnvolle Konfiguration ausliefern.

Initialisiert wird die Datenbank je nach Distribution mit einem leicht abgewandelten Befehl.

Beispiel mit RHEL 9

$ sudo time aide --init
Start timestamp: 2023-09-18 20:50:06 +0200 (AIDE 0.16)
AIDE initialized database at /var/lib/aide/aide.db.new.gz

Number of entries:      54290

---------------------------------------------------
The attributes of the (uncompressed) database(s):
---------------------------------------------------

/var/lib/aide/aide.db.new.gz
  MD5      : xOf5Bs/Hb2Caa5i2K41fbg==
  SHA1     : KoCkqwfe+oZ2rlQTAU+AWQBrt2I=
  RMD160   : eM6IC68wq1VRhDbyHhRqy+63ldI=
  TIGER    : lQC+UTBqUm0iEDdKA0u7THqAPLNQxegH
  SHA256   : vdzjqIr/m7FgjXdZLQG+D1Pvf75WlF17
             WYiA6gU+4Pg=
  SHA512   : EdMB0I92j05zlfjXHcJFasZCAvkrK9br
             6zQEcDfD4IDM8D9c1Sz0r7A5tJTKGXVZ
             AFCOJR65j66ihKB0suFS6w==


End timestamp: 2023-09-18 20:50:19 +0200 (run time: 0m 13s)

Die erzeugte Datenbank wird umbenannt, indem das new aus dem Dateinamen entfernt wird.

$ sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

Die umbenannte Datei stellt die Referenzdatenbank dar, gegen die mit dem Befehl aide --check geprüft werden kann, ob es Änderungen im Dateisystem gab.

In diesem Artikel gebe ich mich damit zufrieden, dass die Datenbank auf dem zu überwachenden Host liegt und damit dem Risiko unterliegt, von einem Angreifer manipuliert zu werden (siehe zu den Schwächen oben). Ich gehe in einem Folgeartikel darauf ein.

Beispiel mit Debian 12

Unter Debian wird die AIDE-Datenbank mit dem Wrapper-Script aideinit (siehe aideinit(8)) initialisiert. Das README unter /usr/share/doc/aide-common/README.Debian.gz warnt bereits davor, dass Debian mit zu restriktiven Einstellungen daherkommt:

Configuring AIDE the Debian way
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AIDE’s Debian default configuration takes a very paranoid stance and
is likely to report more changes than you will need to focus your
attention on.

/usr/share/doc/aide-common/README.Debian.gz

Lassen wir uns überraschen…

$ sudo time aideinit
Running aide --init...
7044.57user 54.97system 2:00:40elapsed 98%CPU (0avgtext+0avgdata 132408maxresident)k
231120192inputs+88320outputs (12major+66397minor)pagefaults 0swaps

Das hat deutlich länger gedauert und endete mit einer deutlich kürzeren Ausgabe. Die erzeugte Datenbank ist jedoch wie bei RHEL im Verzeichnis /var/lib/aide/ zu finden.

:~# ls -l /var/lib/aide/
total 43536
-rw------- 1 root  root  22286930 Sep 19 15:13 aide.db
-rw------- 1 _aide _aide 22286930 Sep 19 15:13 aide.db.new
:~# qm start 102
:~# file /var/lib/aide/aide.db.new 
/var/lib/aide/aide.db.new: gzip compressed data, max compression, from Unix, original size modulo 2^32 44239215
:~# file /var/lib/aide/aide.db
/var/lib/aide/aide.db: gzip compressed data, max compression, from Unix, original size modulo 2^32 44239215

Warum die Erstellung so viel länger gedauert hat, weiß ich nicht. Ich habe keine Idee dazu. Auch Debian erzeugt eine gzip-komprimierte Datenbank, auch wenn hier keine Dateiendung darauf hinweist. Ich finde das etwas seltsam, behalte die Standardeinstellung für diese Einführung jedoch bei. Dafür muss die Datei nicht manuell umbenannt werden, da direkt eine Kopie erstellt wird, die als Referenzdatenbank genutzt werden kann.

Im Gegensatz zu RHEL wird unter Debian auch ein Timer namens dailyaidecheck.timer installiert, welcher täglich einen automatischen Check auf Veränderungen durchführt. Allerdings ist es für einen Angreifer ein Leichtes, diese Timer-Unit zu deaktivieren.

Auf Änderungen prüfen

Unter Debian und RHEL werden die in der Referenzdatenbank enthaltenen Elemente mit folgendem Befehl auf Änderungen überprüft:

:~# aide --check                                    # unter RHEL
:~# aide --check --config /etc/aide/aide.conf       # unter Debian

Ich habe meine Testsysteme ein paar Tage laufen lassen und einen AIDE-Integritätscheck durchgeführt. Hier das Ergebnis für ein RHEL 9 System:

$ sudo aide --check
Start timestamp: 2023-09-26 19:54:59 +0200 (AIDE 0.16)                          
AIDE found differences between database and filesystem!!                        
                                                                                
Summary:                                                                        
  Total number of entries:      54290   
  Added entries:                0                                               
  Removed entries:              0                                               
  Changed entries:              3                                               
                                                                                
---------------------------------------------------                             
Changed entries:                                                                
---------------------------------------------------               
                                                                                
f = ...    . ..S : /var/log/insights-client/insights-client.log.3               
f < ...    . ... : /var/log/rhsm/rhsmcertd.log                                  
f < ...    . ... : /var/log/squid/cache.log                                     
                                                                                
---------------------------------------------------              
Detailed information about changes:
---------------------------------------------------                             
                                                                                
File: /var/log/insights-client/insights-client.log.3                            
  SELinux  : system_u:object_r:insights_clien | unconfined_u:object_r:insights_c
             t_var_log_t:s0                   | lient_var_log_t:s0
                                                                                
File: /var/log/rhsm/rhsmcertd.log                                               
  Size     : 1426                             | 1343                            
                                                                                
File: /var/log/squid/cache.log                                                  
  Size     : 6230                             | 334              
                                                                                
                                                                                
---------------------------------------------------
The attributes of the (uncompressed) database(s):                               
---------------------------------------------------                             
                                                                                
/var/lib/aide/aide.db.gz                                                        
  MD5      : xOf5Bs/Hb2Caa5i2K41fbg==   
  SHA1     : KoCkqwfe+oZ2rlQTAU+AWQBrt2I=                                       
  RMD160   : eM6IC68wq1VRhDbyHhRqy+63ldI=                                       
  TIGER    : lQC+UTBqUm0iEDdKA0u7THqAPLNQxegH                                   
  SHA256   : vdzjqIr/m7FgjXdZLQG+D1Pvf75WlF17                                   
             WYiA6gU+4Pg=                                                       
  SHA512   : EdMB0I92j05zlfjXHcJFasZCAvkrK9br                                   
             6zQEcDfD4IDM8D9c1Sz0r7A5tJTKGXVZ                     
             AFCOJR65j66ihKB0suFS6w==                                           
                                                                                
                                                                                
End timestamp: 2023-09-26 19:55:12 +0200 (run time: 0m 13s)

Die Integritätsprüfung in obigen Code-Block führt Änderungen an drei Dateien auf:

  • Das SELinux-Label einer Log-Datei hat sich geändert
  • Die Größe von zwei weiteren Log-Dateien hat sich geändert
  • Die Änderungen werden in einer Zusammenfassung und im Detail ausgegeben
  • Eine Erläuterung zur Ausgabe unter „Changed entries“ findet sich im Absatz summarize_changes in aide.conf(5).
  • Man erhält Informationen darüber, was sich geändert hat, nicht warum sich diese Änderungen ergeben haben

Abbruch meiner Tests unter Debian 12 (Bookworm)

Unter Debian hat die Integritätsprüfung über Stunden einen CPU-Kern blockiert. Der Prozess ist in einem futex Syscall hängen geblieben.

Ob es an meinem System liegt oder AIDE unter Debian generell ein Problem hat, kann ich nicht sagen. Ich bin der Sache nicht weiter nachgegangen.

Falls jemand von euch AIDE unter Debian einsetzt und dies liest, freue ich mich, wenn ihr eure Erfahrungen mit mir teilt.

Die Referenzdatenbank aktualisieren

Mit dem Befehl aide --update wird die Datenbank-Integrität geprüft und eine neue Datenbank /var/lib/aide/aide.db.new.gz erzeugt. Die bestehende Referenzdatenbank /var/lib/aide/aide.db.gz wird dabei nicht überschrieben und bleibt zunächst erhalten. Möchte man diese länger aufbewahren, kann man sie umbenennen und bspw. einen Zeitstempel anhängen. Anschließend erzeugt man mit mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz eine neue Referenzdatenbank.

Der folgende Code-Block zeigt die Ausgabe von aide --update unter RHEL 9.

~]# aide --update                                            
Start timestamp: 2023-09-26 20:13:52 +0200 (AIDE 0.16)
AIDE found differences between database and filesystem!!
New AIDE database written to /var/lib/aide/aide.db.new.gz
                                                                                
Summary:                                
  Total number of entries:      54290
  Added entries:                0
  Removed entries:              0    
  Changed entries:              3                                               
                                                                                
---------------------------------------------------
Changed entries:                                                                
---------------------------------------------------
                                                                                
f = ...    . ..S : /var/log/insights-client/insights-client.log.3
f < ...    . ... : /var/log/rhsm/rhsmcertd.log
f < ...    . ... : /var/log/squid/cache.log

---------------------------------------------------        
Detailed information about changes:                                             
---------------------------------------------------

File: /var/log/insights-client/insights-client.log.3                     [0/100]
  SELinux  : system_u:object_r:insights_clien | unconfined_u:object_r:insights_c
             t_var_log_t:s0                   | lient_var_log_t:s0
                                                                                
File: /var/log/rhsm/rhsmcertd.log                                               
  Size     : 1426                             | 1343                            
                                                                                
File: /var/log/squid/cache.log                                                  
  Size     : 6230                             | 334                             
                                        
                                                                                
---------------------------------------------------                             
The attributes of the (uncompressed) database(s):
---------------------------------------------------         
                                        
/var/lib/aide/aide.db.gz       
  MD5      : xOf5Bs/Hb2Caa5i2K41fbg==                                           
  SHA1     : KoCkqwfe+oZ2rlQTAU+AWQBrt2I=                                       
  RMD160   : eM6IC68wq1VRhDbyHhRqy+63ldI=              
  TIGER    : lQC+UTBqUm0iEDdKA0u7THqAPLNQxegH                                   
  SHA256   : vdzjqIr/m7FgjXdZLQG+D1Pvf75WlF17         
             WYiA6gU+4Pg=                                                       
  SHA512   : EdMB0I92j05zlfjXHcJFasZCAvkrK9br            
             6zQEcDfD4IDM8D9c1Sz0r7A5tJTKGXVZ                                   
             AFCOJR65j66ihKB0suFS6w==   
                                        
/var/lib/aide/aide.db.new.gz     
  MD5      : Dgoc1/L5F1UfXPAQRvMdTg==
  SHA1     : 23RFwEBIh0kw/3TiiVAh39Fzx0Q=                                       
  RMD160   : 1szie2CW1dyLmaKFg01j48Fr+Us=                                       
  TIGER    : TgdG3zNAOSZH2D9jkyvBves8PtjC0lCR      
  SHA256   : hjn9vxFxg4KoVwT3YvgU347EhvTCg5ey                                   
             lfktpr/OrcA=                                                       
  SHA512   : x6E3YPa0eILD3nZqDt6N755KSmPRFOz8                                   
             lhKD9CimYScSpxyoVxJAVWiozR8KUwkt                    
             Ao7mgy3BgtUA0MZuNMv43w==                                           
                                                                                

End timestamp: 2023-09-26 20:14:03 +0200 (run time: 0m 11s)
~]# ls -l /var/lib/aide                                      
total 6184                                                                      
-rw-------. 1 root root 3163359 Sep 18 20:50 aide.db.gz                         
-rw-------. 1 root root 3163384 Sep 26 20:14 aide.db.new.gz

Ende

An dieser Stelle endet die Einführung in das Advanced Intrusion Detection Environment (AIDE). Kommt das Ende für euch abrupt? Ist es ein Ende mit Schrecken? Lasst es mich gern wissen.

In dieser Einführung habe ich beschrieben, was Intrusion-Detection-Systeme im Allgemeinen und AIDE im Speziellen sind. Ich bin auf deren Nutzen eingegangen und habe die Schwächen von AIDE als Host-basiertem IDS benannt. Installation, Konfiguration, Integritäts-Check und Aktualisierung der Datenbank wurden erklärt und mit Beispielen belegt.

Was ist nun von AIDE zu halten?

Nun, es ist besser als nichts. Man besitzt damit ein Werkzeug, mit dem sich Änderungen im Dateisystem erkennen lassen. Man muss sich jedoch der Schwächen Host-basierter IDS bewusst sein. Ein Angreifer mit lokalen root-Rechten kann dieses Werkzeug mit wenig Aufwand unschädlich machen bzw. die eigenen Änderungen verschleiern.

Sicher kann man einen Integritätscheck automatisiert alle 5 Minuten durchführen und für Änderungen eine E-Mail-Benachrichtigung einrichten. Doch wirkt dies etwas hemdsärmelig. Daher werde ich dieses Thema in einem späteren Artikel aufgreifen und zeigen, wie man AIDE in einen Automations- bzw. Konfigurations-Management-Prozess einbinden kann.

  •  

Kurztipp: RAR unter Linux registrieren

Vor kurzem gab es das „WinRAR | 9GAG Special Offer!“ und ich bin einer von 5449 Personen, die bei diesem Angebot zugeschlagen haben. Der Key gilt nicht nur für WinRAR, sondern auch für die...

  •  
❌