y0o.de · GNU/Linux Nachrichten u.Ä.

🔒
❌ Über y0o.de
Es gibt neue verfügbare Artikel. Klicken Sie, um die Seite zu aktualisieren.
Ältere BeiträgeMy-IT-Brain

In-Place-Upgrade für Red Hat Enterprise Linux (RHEL)

20. September 2021 um 07:00

In diesem Beitrag beschreibe ich exemplarisch, wie ein In-Place-Upgrade von RHEL 7 auf RHEL 8 durchgeführt werden kann. Dabei beschreibe ich zuerst, was ein In-Place-Upgrade ist und in welchen Fällen es sinnvoll sein kann, bevor ich im Hauptteil anhand einer Test-VM die Durchführung demonstriere.

Was ist ein In-Place-Upgrade?

Als In-Place-Upgrade wird der Vorgang bezeichnet, bei dem ein Betriebssystem auf ein neues Major-Release aktualisiert wird, ohne das System dabei neuinstallieren zu müssen. Statt dessen werden alle zum Betriebssystem gehörenden Dateien gegen die entsprechende Version des neuen Release ausgetauscht.

Nutzer von Debian und Ubuntu kennen dieses Verfahren unter dem Begriff Distributions-Upgrade.

In-Place-Upgrade vs. Neuinstallation

Grundsätzlich bevorzuge ich die Neuinstallation eines Systems. Da man sich üblicherweise mit Backups und Deployment-Skripten darauf vorbereitet hat, einen Dienst bzw. eine Anwendung nach einem Verlust des laufenden Systems wiederherstellen zu können, kann man sich dies auch zu Nutze machen und den Dienst bzw. die Anwendung auf einem frisch installierten System wiederherzustellen. Auf diese Weise werden keine Altlasten über mehrere Betriebssystemversionen mitgeschleppt.

Gleichzeitig kann man die Downtime verkürzen, indem das neue System parallel zum alten aufgebaut wird und man nach dem Abschluss aller Arbeiten und Tests umschaltet. Das Altsystem kann im Nachgang in Ruhe abgebaut werden.

Es gibt jedoch auch Gründe, die für ein In-Place-Upgrade sprechen. Verfügt man nur über einen einzigen Host und kann kein Parallelsystem aufbauen, kann ein In-Place-Upgrade die Lösung sein.

Evtl. verfügt man selbst zwar über ausreichend Berechtigungen, um das vorhandene System zu aktualisieren, für die Provisionierung neuer Systeme ist man jedoch auf die Unterstützung weiterer Stellen angewiesen. Die Abhängigkeitskette lässt sich hier zum Teil deutlich reduzieren.

Dabei muss stets bedacht werden, dass bei einem In-Place-Upgrade auch ein katastrophaler Fehler eintreten kann, welcher zum Verlust des Systems führt. Es ist daher dringend angeraten, eine Datensicherung zu haben, aus welcher das System wiederhergestellt werden kann. Besitzt man ein Backup, auf das man sich verlassen kann, kann es auch schon losgehen.

Das Upgrade von RHEL 7 auf RHEL 8

Laut Kapitel 1 der unter [0] verlinkten Dokumentation stellt das In-Place-Upgrade den von Red Hat unterstützten und empfohlenen Weg dar, um auf das nächste Major-Release zu aktualisieren. Dabei kann man stets nur von der letzten Verfügbaren RHEL 7 Version auf das jeweils letzte gerade RHEL 8 Release (z.B. 8.4) aktualisieren. Details hierzu können im Artikel unter [1] nachgelesen werden.

Die folgenden Abschnitte können die Dokumentation unter [0] nicht ersetzen. Sie sollen lediglich einen kompakten Überblick über den Prozess geben.

Limitierungen

Zum Zeitpunkt der Artikelerstellung , kann das In-Place-Upgrade nicht auf Systemen mit verschlüsselten Dateisystemen durchgeführt werden.

Netzwerkspeicher, wie z.B. iSCSI oder NAS, werden nicht unterstützt und müssen während des Upgrades ausgehängt werden. Die dazugehörigen Dienste, wie z.B. autofs müssen vorübergehend deaktiviert werden.

Weitere bekannte Probleme sind Kapitel 8 in [0] zu entnehmen.

Vorbereitung

Bevor man mit dem Upgrade beginnen kann, sind folgende Voraussetzungen zu schaffen:

  • Das System erfüllt die minimalen Systemvoraussetzungen für RHEL 8 (siehe [2]).
  • Zugriff auf Repos mit aktuellen Paketen für RHEL 7.9 und RHEL 8.4.
  • Korrekte Registrierung des Systems am Red Hat Content Delivery Network (CDN) oder den Red Hat Satellite Server mittels Red Hat Subscription Manager (RHSM).

Wichtig: Ich empfehle ausdrücklich, vor Beginn der Arbeiten ein aktuelles Backup bzw. einen Snapshot zu erstellen, um auf den Ausgangszustand vor der Upgrade-Prozedur zurückkehren zu können.

Kapitel 2 in [0] bietet eine ausführliche Schritt-für-Schritt-Anleitung zur Vorbereitung des Upgrades. Der folgende Codeblock bietet eine kompakte Übersicht der einzelnen Schritte. Als Zielsystem dient eine aktuelle RHEL 7.9 Minimal-Installation.

[tronde@rhel7-t1 ~]$ # Überprüfung, ob eine RHEL-Subskription abonniert wurde
[tronde@rhel7-t1 ~]$ sudo subscription-manager list --installed
[sudo] password for tronde: 
+-------------------------------------------+
    Installed Product Status
+-------------------------------------------+
Product Name:   Red Hat Enterprise Linux Server
Product ID:     69
Version:        7.9
Arch:           x86_64
Status:         Subscribed
Status Details: 
Starts:         06.10.2020
Ends:           06.10.2021

[tronde@rhel7-t1 ~]$ # Aktivierung des RHEL 7 Basis- und Extras-Repo
[tronde@rhel7-t1 ~]$ sudo subscription-manager repos --enable rhel-7-server-rpms
Repository 'rhel-7-server-rpms' is enabled for this system.
[tronde@rhel7-t1 ~]$ sudo subscription-manager repos --enable rhel-7-server-extras-rpms
Repository 'rhel-7-server-extras-rpms' is enabled for this system.

[tronde@rhel7-t1 ~]$ # Ist locale auf en_US.UTF-8 gesetzt?
[tronde@rhel7-t1 ~]$ cat /etc/locale.conf
LANG="en_US.UTF-8"

[tronde@rhel7-t1 ~]$ sudo yum install leapp leapp-repository
# Ausgabe gekürtzt
Transaction Summary
================================================================================
Install  2 Packages (+24 Dependent packages)

Total download size: 5.3 M
Installed size: 19 M
Is this ok [y/d/N]: y
# Ausgabe gekürtzt

Pre-Upgrade-Bericht erstellen

Bevor das eigentliche Upgrade durchgeführt wird, führe ich auf meinem Testsystem das Kommando leapp preupgrade aus. Dieses sammelt Informationen über das System, um die Upgradefähigkeit zu bewerten und erstellt einen detaillierten Bericht, welcher im Pfad /var/log/leapp/leapp-report.txt abgelegt wird.

[tronde@rhel7-t1 ~]$ sudo leapp preupgrade
# Ausgabe gekürzt
============================================================
                           ERRORS                           
============================================================

2021-08-31 06:33:26.035495 [ERROR] Actor: repository_mapping
Message: Data file /etc/leapp/files/repomap.csv is invalid or could not be retrieved.
Summary:
    Details: Could not fetch repomap.csv from https://cert.cloud.redhat.com/api/pes/repomap.csv (unreachable address).
    Hint: Read documentation at: https://access.redhat.com/articles/3664871 for more information about how to retrieve the file.
2021-08-31 06:35:22.415297 [ERROR] Actor: restricted_pcis_scanner
Message: Data file /etc/leapp/files/unsupported_driver_names.json is invalid or could not be retrieved.
Summary:
    Details: Could not fetch unsupported_driver_names.json from https://cert.cloud.redhat.com/api/pes/unsupported_driver_names.json (unreachable address).
    Hint: Read documentation at: https://access.redhat.com/articles/3664871 for more information about how to retrieve the file.
2021-08-31 06:35:47.800140 [ERROR] Actor: pes_events_scanner
Message: Data file /etc/leapp/files/pes-events.json is invalid or could not be retrieved.
Summary:
    Details: Could not fetch pes-events.json from https://cert.cloud.redhat.com/api/pes/pes-events.json (unreachable address).
    Hint: Read documentation at: https://access.redhat.com/articles/3664871 for more information about how to retrieve the file.

============================================================
                       END OF ERRORS                        
============================================================


Debug output written to /var/log/leapp/leapp-preupgrade.log

============================================================
                           REPORT                           
============================================================

A report has been generated at /var/log/leapp/leapp-report.json
A report has been generated at /var/log/leapp/leapp-report.txt

============================================================
                       END OF REPORT                        
============================================================

Answerfile has been generated at /var/log/leapp/answerfile
[tronde@rhel7-t1 ~]$

Dem obigen Codeblock ist zu entnehmen, dass der Pre-Upgrade-Check Fehler festgestellt hat, die behoben werden müssen, bevor ein In-Place-Upgrade durchgeführt werden kann. Dankenswerter Weise ist sowohl in der Ausgabe auf STDOUT als auch in /var/log/leapp/leapp-report.txt der Knowledge-Base-Artikel [3] verlinkt, welcher die Lösung parat hält.

Ist dieser Fehler behoben, lässt man leapp preupgrade ein weiteres Mal laufen und prüft die Ausgabe erneut. Auf meinem Testsystem erhalte ich nun folgende Ausgabe:

[root@rhel7-t1 ~]# leapp preupgrade
# Ausgabe gekürzt
============================================================
                     UPGRADE INHIBITED                      
============================================================

Upgrade has been inhibited due to the following problems:
    1. Inhibitor: Missing required answers in the answer file
Consult the pre-upgrade report for details and possible remediation.

============================================================
                     UPGRADE INHIBITED                      
============================================================


Debug output written to /var/log/leapp/leapp-preupgrade.log

============================================================
                           REPORT                           
============================================================

A report has been generated at /var/log/leapp/leapp-report.json
A report has been generated at /var/log/leapp/leapp-report.txt

============================================================
                       END OF REPORT                        
============================================================

Answerfile has been generated at /var/log/leapp/answerfile

Diesmal weist die Ausgabe darauf hin, dass ein Upgrade durch fehlende Antworten in /var/log/leapp/answerfile verhindert wird. Die genannte Datei kann mit einem Editor geöffnet und entsprechend bearbeitet werden:

[remove_pam_pkcs11_module_check]
# Title:              None
# Reason:             Confirmation
# =================== remove_pam_pkcs11_module_check.confirm ==================
# Label:              Disable pam_pkcs11 module in PAM configuration? If no, the upgrade process will be interrupted.
# Description:        PAM module pam_pkcs11 is no longer available in RHEL-8 since it was replaced by SSSD.
# Type:               bool
# Default:            None
# Available choices: True/False
# Unanswered question. Uncomment the following line with your answer
confirm = True

Die Datei enthält direkt eine Erklärung, warum das erwähnte Modul zu entfernen ist und wie dies zu geschehen hat.

Anschließend empfiehlt sich ein Blick in den Bericht unter /var/log/leapp/leapp-report.txt, um zu prüfen, ob einem Upgrade evtl. weitere Gründe entgegen stehen. Auf die Ausgabe des Berichts in diesem Artikel wird aus Platzgründen verzichtet. Da der Inhalt auf jedem System unterschiedlich ausfallen kann, ist sein Nutzen an dieser Stelle ohnehin stark begrenzt.

Durchführung des In-Place-Upgrade

An dieser Stelle wird es ernst. Man sollte sich noch einmal vergewissern, dass man einen Snapshot bzw. ein geeignetes Backup des Systems hat. Dann wird das Upgrade mit folgendem Befehl gestartet:

# leapp upgrade
# Ausgabe gekürzt
============================================================
                           REPORT                           
============================================================

A report has been generated at /var/log/leapp/leapp-report.json
A report has been generated at /var/log/leapp/leapp-report.txt

============================================================
                       END OF REPORT                        
============================================================

Answerfile has been generated at /var/log/leapp/answerfile

Dieser Vorgang kann mehrere Minuten dauern. Leapp lädt notwendige Daten herunter und bereitet die RPM-Transaktionen für das Upgrade vor. Dabei wird erneut geprüft, ob Gründe vorliegen, die ein Upgrade verhindern können. Sollte dies der Fall sein, bricht leapp den Vorgang ab und erzeugt einen neuen Bericht.

Ist das Upgrade erfolgreich durchgelaufen, muss das System manuell neugestartet werden. Das System startet anschließend in eine RAM-Disk und aktualisiert alle Pakete des Systems. Anschließend wird automatisch ein Neustart ausgeführt. Dieser Vorgang lässt sich am besten an einer (virtuellen) Konsole beobachten.

Nachdem das Upgrade abgeschlossen ist, kann man sich wieder am System anmelden und mit folgenden Kommandos prüfen, ob das System den gewünschten Status hat (vgl. Kapitel 5 in [0]):

[root@rhel7-t1 ~]# cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.4 (Ootpa)

[root@rhel7-t1 ~]# uname -r
4.18.0-305.12.1.el8_4.x86_64

[root@rhel7-t1 ~]# subscription-manager list --installed
+-------------------------------------------+
    Installed Product Status
+-------------------------------------------+
Product Name:   Red Hat Enterprise Linux for x86_64
Product ID:     479
Version:        8.4
Arch:           x86_64
Status:         Subscribed
Status Details: 
Starts:         06.10.2020
Ends:           06.10.2021

[root@rhel7-t1 ~]# subscription-manager release
Release: 8.4

Hier sieht alles gut aus.

Post-Upgrade-Tasks

Kapitel 6 in [0] beschreibt detailliert, welche Aufgaben nach einem erfolgreichen In-Place-Upgrade noch auszuführen sind, um ein möglichst sauberes System zu erhalten.

Auf meinem Testsystem sind einige RHEL 7 Pakete zurückgeblieben, welche ich mit folgendem Kommando entferne:

# dnf remove `rpm -qa | grep -e '\.el[67]' | grep -vE '^(gpg-pubkey|libmodulemd|katello-ca-consumer)' | sort`
Updating Subscription Management repositories.
Dependencies resolved.
===============================================================================
 Package              Arch       Version                     Repository   Size
===============================================================================
Removing:
 doxygen              x86_64     1:1.8.5-4.el7               @System      15 M
 kernel               x86_64     3.10.0-1160.31.1.el7        @System      64 M
 kernel               x86_64     3.10.0-1160.36.2.el7        @System      64 M
 leapp                noarch     0.12.1-1.el7_9              @System      93 k
 leapp-repository     noarch     0.14.0-4.el7_9              @System     1.7 M
 python2-leapp        noarch     0.12.1-1.el7_9              @System     618 k
 ustr                 x86_64     1.0.4-16.el7                @System     279 k

Transaction Summary
===============================================================================
Remove  7 Packages

Freed space: 146 M
Is this ok [y/N]:

# cd /lib/modules && ls -d *.el7*
3.10.0-1160.25.1.el7.x86_64  3.10.0-1160.36.2.el7.x86_64
3.10.0-1160.31.1.el7.x86_64

# /bin/kernel-install remove 3.10.0-1160.36.2.el7.x86_64 /lib/modules/3.10.0-1160.36.2.el7.x86_64/vmlinuz
# /bin/kernel-install remove 3.10.0-1160.25.1.el7.x86_64 /lib/modules/3.10.0-1160.25.1.el7.x86_64/vmlinuz
# /bin/kernel-install remove 3.10.0-1160.31.1.el7.x86_64 /lib/modules/3.10.0-1160.31.1.el7.x86_64/vmlinuz

Damit ist es geschafft. Das System wurde erfolgreich auf RHEL 8 aktualisiert.

Fazit

Dieser Artikel stellt das RHEL-In-Place-Upgrade vor und nennt kurz einige Gründe, wann dies gegenüber einer Neuinstallation Vorteile bietet. Anschließend wurde das Upgrade an einem Testsystem demonstriert mit dem Ziel, einen Überblick über den Upgrade-Prozess zu geben.

Für In-Place-Upgrades von Produktionssystemen ist ein Blick in die Hersteller-Dokumentation, Backups und sorgfältige Planung unerlässlich.

Das für diesen Artikel verwendete Testsystem besteht lediglich aus einer Minimal-Installation ohne Anwendungen von Dritten. Ob ein In-Place-Upgrade auch mit installierten Anwendungen Dritter funktioniert, hängt vom Einzelfall ab und ist sorgfältig zu prüfen und zu testen.

Erste Versuche mit Web- und Anwendungsservern aus unserer Umgebung konnten mit positivem Ergebnis abgeschlossen worden.

Es gibt Anwendungsfälle, wo ein In-Place-Upgrade vorteilhaft ist. Ich persönlich bevorzuge, wenn möglich und vom Aufwand vertretbar, jedoch die Neuinstallation inkl. Migration der Daten auf einem neuen System. So kann sichergestellt werden, dass keine unentdeckten Altlasten mitgeschleppt werden.

[0] Upgrading from RHEL 7 to RHEL 8. Instructions for an in-place upgrade from Red Hat Enterprise Linux 7 to Red Hat Enterprise Linux 8. Red Hat Enterprise Linux 8. Red Hat Customer Content Services.

[1] Supported in-place upgrade paths for Red Hat Enterprise Linux (Login required)

[2] Red Hat Enterprise Linux technology capabilities and limits

[3] Data required by the Leapp utility for an in-place upgrade from RHEL 7 to RHEL 8 (Login required)

Grundlagenwissen: Verschlüsselungsverfahren

13. September 2021 um 07:00

Verschlüsselung, zur Wahrung der Vertraulichkeit einer Nachricht, spielt in der IT-Welt eine große Bedeutung. Ein Grundverständnis weit verbreiteter Verschlüsselungsverfahren ist Pflicht für jene, die in der IT arbeiten. Aber auch für Nutzer ist ein Grundverständnis hilfreich, um Anwendungen, Apps und Dienste hinsichtlich ihrer Sicherheit einschätzen und bewerten zu können.

In diesem Artikel erkläre ich die grundlegenden Konzepte asymmetrischer und symmetrischer Verschlüsselungsverfahren. Mein Ziel ist es, damit ein solides Grundwissen zu vermitteln, ohne in die Tiefen der Mathematik abzuschweifen. So werdet ihr diesem Artikel auch folgen können, wenn Mathematik nicht zu euren stärksten Fächern gehörte.

Akteure

Alice und Bob werden als Synonyme für Sender und Empfänger einer Nachricht
verwendet: Alice sendet eine Nachricht an Bob. Neben Alice und Bob werden
noch folgende Akteure in diesem Text eine Rolle spielen:

Eve, von engl. eavesdropper (zu deutsch Lauscher/Lauscherin), ist passiver Angreifer. Sie versucht, ausgetauschte Nachrichten mitzuhören (und auch zu verstehen). Sie kann die übertragenen Nachrichten jedoch nicht verändern oder in die
Systeme von Sender und Empfänger eindringen.

Marvin bezeichnet einen aktiven Angreifer. Dieser kann aktiv in das Geschehen
eingreifen, indem er z. B. Nachrichten fälscht oder zu übertragende Nachrichten
verändert.

Trudy, von engl. intruder (Eindringling), wird in ähnlicher Rolle wie Marvin gebraucht. Im Unterschied zu diesem jedoch mit dem Fokus auf das Eindringen in ein bestehendes System.

Verschlüsselung

Durch die in diesem Text beschriebenen Verschlüsselungsverfahren sollen in Bezug auf eine Kommunikationsverbindung im Wesentlichen die drei folgenden Ziele erreicht werden:

Vertraulichkeit Nur direkt an der Kommunikation beteiligte Sender und Empfänger haben Zugriff auf den Inhalt einer Nachricht. Unbeteiligte Dritte können den Inhalt der Nachricht hingegen nicht lesen.

Integrität Durch entsprechende Verfahren kann ̈uberprüft werden, ob eine Nachricht auf dem Übertragungsweg verändert wurde. Dadurch wird die Nachricht vor Fälschung durch Dritte auf dem Übertragungsweg geschützt.

Authentizität Der Absender einer Nachricht kann überprüft werden. Es soll damit verhindert werden, dass Marvin Nachrichten im Namen von Alice versendet.

Dabei werden im Allgemeinen symmetrische und asymmetrische Verschlüsselungsverfahren unterschieden.

Symmetrische Verschlüsselung

Symmetrische Verschlüsselung beschreibt ein Verfahren, bei dem zur Ver- und
Entschlüsselung von Daten der gleiche Schlüssel verwendet wird. Mit einem solchen Schlüssel kann Alice bspw. ihre Daten verschlüsseln, um sie vor den neugierigen Augen Eves zu schützen. Damit nun niemand außer Alice die Daten entschlüsseln und lesen kann, muss Alice den Schlüssel geheim halten. Daher wird dieses Verfahren auch als secret key Verschlüsselung bezeichnet.

Möchte Alice nach diesem Verfahren Nachrichten mit Bob austauschen, müssen beide über den gleichen Schlüssel verfügen, um Nachrichten ver- und entschlüsseln zu können. Die Kenntnis des geheimen Schlüssels stellt ein gemeinsames Geheimnis von Alice und Bob dar. Dieses Geheimnis wird auch als shared secret bezeichnet.

symmetriy-key-encryption
Nachrichtenübertragung unter Einsatz symmetrischer Verschlüsselung

In obiger Abbildung verwendet Alice einen geheimen Schlüssel, um eine Nachricht an Bob zu verschlüsseln. Bob verwendet den gleichen geheimen Schlüssel, um die Nachricht wieder zu entschlüsseln. Hören Eve und Trudy die Nachricht während der Übertragung ab, sehen sie nur den verschlüsselten Text und nicht die ursprüngliche Nachricht. Die Kommunikation von Alice und Bob bleibt so lange vertraulich, wie der verwendete Schlüssel geheim bleibt.

Die Schwierigkeit bei der symmetrischen Verschlüsselung besteht darin, dass Alice vor Beginn des Nachrichtenaustauschs Bob den geheimen Schlüssel mitteilen muss. Hierbei besteht das Risiko, dass der geheime Schlüssel bei der Übertragung von Eve abgehört werden kann. Eve könnte damit fortan die Kommunikation zwischen Alice und Bob mithören, mit Hilfe des geheimen Schlüssels entschlüsseln und damit auf den ursprünglichen Nachrichtentext zugreifen.

Asymmetrische Verschlüsselung

Symmetrische Verschlüsselung leistet gute Arbeit bei der Verarbeitung großer Datenmengen mit hoher Geschwindigkeit. Doch bleibt das Problem des sicheren
Schlüsselaustauschs. Dieses Problem wächst mit der Menge der Kommunikationsteilnehmer. Denn alle Teilnehmer müssen über den gleichen geheimen Schlüssel verfügen. Je mehr Teilnehmer Kenntnis über den geheimen Schlüssel haben, desto größer ist das Risiko der Kompromittierung.

Dieses Problem versucht die asymmetrische Verschlüsselung (welche auch als
public key Verschlüsselung bezeichnet wird) zu lösen, indem für die Ver- und
Entschlüsselung unterschiedliche Schlüssel verwendet werden.

Nutzer erstellen mit Hilfe einer Anwendung zuerst ein Schlüsselpaar, bestehend aus einem privaten und einem öffentlichen Schlüssel.

public-private-keygeneration.svg
Erzeugung eines Schlüsselpaars: Blaue Bildelemente sind geheim, orange sind öffentlich. Bildquelle: https://de.wikipedia.org/wiki/Datei:Orange_blue_public_private_keygeneration_de.svg

Der öffentliche Schlüssel wird zur Verschlüsselung einer Nachricht genutzt und kann frei verteilt werden. Die mit diesem öffentlichen Schlüssel verschlüsselten Daten können, wie in folgender Abbildung dargestellt, ausschließlich mit dem dazugehörigen privaten Schlüssel wieder entschlüsselt werden.

public-key-cryptography.svg
Verschlüsselung mit öffentlichem Schlüssel und Entschlüsselung mit privatem Schlüssel. Bildquelle: https://de.wikipedia.org/wiki/Datei:Orange_blue_public_key_cryptography_de.svg

Darüber hinaus kann mit dem privaten Schlüssel eine Signatur erstellt werden. Mit Hilfe des dazugehörigen öffentlichen Schlüssels kann anschließend die Authentizität und Integrität einer Nachricht überprüft werden:

digital_signature_de.svg
Signieren mit privatem Schlüssel und Verifikation mit öffentlichem Schlüssel. Bildquelle: https://de.wikipedia.org/wiki/Datei:Orange_blue_digital_signature_de.svg

Die asymmetrische Verschlüsselung findet z. B. Anwendung in OpenPGP, S/MIME und SSL/TLS-Verbindungen.

Da der zur Verschlüsselung benötigte Schlüssel nicht geheim gehalten werden muss, kann dieser auf vielfältige Weise z. B. auf Webseiten, im E-Mail-Anhang
oder über Schlüsselserver veröffentlicht werden.

Die folgende Abbildung zeigt, wie Bob eine Nachricht mit dem öffentlichen Schlüssel von Alice verschlüsselt. Alice kann diese Nachricht ausschließlich mit ihrem dazugehörigen privaten Schlüssel wieder entschlüsseln. Hört Eve die Kommunikation
ab, kann sie die Nachricht nicht entschlüsseln, da sie den zugehörigen privaten
Schlüssel nicht besitzt.

public-key-encryption.png
Bob verschlüsselt eine Nachricht und sendet sie an Alice. Bildquelle: https://en.wikipedia.org/wiki/File:Public_key_encryption.svg

Wenn Bob die Nachricht an Alice zusätzlich noch mit seinem eigenen privaten Schlüssel signiert hat, kann Alice mit Bobs öffentlichen Schlüssel überprüfen, ob die Nachricht tatsächlich von Bob stammt oder auf dem Übertragungsweg evtl. von Marvin verändert wurde.

Asymmetrische Verschlüsselung kann für die gleichen Zwecke wie symmetrische Verschlüsselung verwendet werden. Das Verfahren ist jedoch wesentlich langsamer als symmetrische Verschlüsselungsverfahren. Daher kommen in der Praxis häufig hybride Verfahren zum Einsatz.

Dabei verwendet Alice z. B. den öffentlichen Schlüssel von Bob, um einen symmetrischen Schlüssel sicher an Bob zu übertragen. Damit Bob verifizieren kann,
dass ihm der symmetrische Schlüssel auch wirklich von Alice gesendet wurde, kann Alice diesen zusätzlich mit ihrem privaten Schlüssel signieren. Bob kann den symmetrischen Schlüssel mit seinem privaten Schlüssel entschlüsseln. Anschließend nutzen Alice und Bob für die weitere Kommunikation den symmetrischen Sitzungsschlüssel.

Zusammenfassung

Dieser Artikel ist Kapitel 2 aus meinem TLS/SSL Kochbuch entnommen. Er vermittelt Grundlagenwissen zu symmetrischen und asymmetrischen Verschlüsselungsverfahren.

Während sich symmetrische Verfahren besonders durch ihre hohe Geschwindigkeit auszeichnen, stellt der sichere Austausch des shared secrets eine große Herausforderung dar. Das Problem des Schlüsselaustauschs wurde mit den asymmetrischen Verfahren gelöst. Allerdings arbeiten diese deutlich langsamer als symmetrische Verfahren. Daher werden diese Verfahren in der Praxis häufig kombiniert. So kommt ein asymmetrisches Verfahren zum Einsatz, um einen Sitzungsschlüssel auszutauschen (shared secret), welcher für die weitere Kommunikation verwendet wird.

Die in diesem Artikel beschriebenen Verfahren finden z.B. in OpenPGP, S/MIME und X.509-Zertifikaten Anwendung. Sie alle haben gemeinsam, dass Nutzer über eine private Komponente verfügen, welche stets geheim zu halten ist und eine öffentliche Komponente, die unbeschränkt geteilt werden kann.

Eine solide Kenntnis der beteiligten kryptographischen Verfahren erleichtert das Verständnis und den Umgang mit den genannten Protokollen und Werkzeugen im Alltag. Ich freue mich, wenn es mir mit diesem Artikel gelungen ist, dieses Grundlagenwissen zu vermitteln.

Quellen und weiterführende Links

  • J. Callas u. a. OpenPGP Message Format. IETF RFC 4880. The Internet Engineering Task Force (IETF R©), 2007. url: https://tools.ietf.org/html/rfc4880.
  • Charlie Kaufman, Radia Perlman und Mike Speciner. Network security : private communication in a public world ; [now includes IPsec, SSL, PKI, AES, and web security]. eng. 2. ed. Prentice Hall series in computer networking and distributed systems. Upper Saddle River, N.J. ; London: Prentice Hall PTR, 2002, XXVI, 713 S. : graph. Darst. isbn: 0-13-046019-2.
  • B. Ramsdell u. a. Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.2 Message Specification. IETF RFC 5751. The Internet Engineering Task Force (IETF R©), Jan. 2010. url: https://tools.ietf.org/html/rfc5751.
  • Ivan Risti ́c. Bulletproof SSL and TLS : [understanding and deploying SSL/TLS and PKI to secure servers and web applications]. eng. London: Feisty Duck, 2014, XXII, 506 S. : graph. Darst., Kt. isbn: 978-1-907117-04-6.

Wie (rechts-)sichere elektronische Kommunikation aussehen könnte

06. September 2021 um 07:00

Am 31. August 2021berichtete die Tagesschau, dass die Telekom ihren De-Mail-Service zum 31. August 2022 einstellen wird. Diesen Schritt kann ich persönlich gut nachvollziehen, empfand ich die DE-Mail und den ePostbrief doch schon 2012 als Rohrkrepierer.

In diesem Beitrag möchte ich euch meine persönliche Vorstellung schildern, wie (rechts-)sichere elektronische Kommunikation aussehen könnte. Auf Fachchinesisch verzichte ich dabei bewusst und gehe bei der Technik nur soweit ins Detail wie absolut notwendig. So können möglichst viele Personen dem Text folgen.

Im ersten Abschnitt beschäftige ich mich damit, welche Merkmale eine (rechts-)sichere elektronische Kommunikationslösung aufweisen muss. Allerdings bin ich kein Jurist, so dass mir eine Beurteilung, ob etwas nach geltendem Recht tatsächlich rechtssicher ist, nicht möglich ist.

Anschließend beschreibe ich, warum es aus meiner Sicht bisher nicht geklappt hat, eine Lösung zu etablieren und was den existierenden Lösungen zum Erfolg fehlt.

Zum Schluss beschreibe ich meine Wunschlösung.

Welche Merkmale muss eine Lösung besitzen?

Eine Lösung für die Kommunikation mit und zwischen Behörden, Bürgern und Unternehmen muss gewisse Anforderungen an Authentizität, Integrität, Vertraulichkeit, Verbindlichkeit und Zurechenbarkeit erfüllen.

So muss hinreichend sichergestellt bzw. nachvollzogen werden können, von wem eine Nachricht stammt (Authentizität) und ob sie auf dem Weg vom Sender zum Empfänger verändert worden ist (Integrität). Ebenso muss sichergestellt werden, dass ein Sender einer Nachricht seine Willensbekundung nicht unzulässig abstreiten kann (Verbindlichkeit und Zurechenbarkeit). Üblicherweise sollen nur der Sender und die adressierten Empfänger Kenntnis über den Inhalt einer Nachricht erlangen (Vertraulichkeit).

In der analogen Welt dient zum Nachweis der Authentizität häufig die Vorlage eines Ausweisdokuments und/oder die eigenhändige Unterschrift. Bei einem Brief mit eigenhändiger Unterschrift wird in der Regel die Integrität unterstellt. Auch die Anforderungen an die Verbindlichkeit und Zurechenbarkeit gelten dabei in den meisten Fällen als erfüllt. Vertraulichkeit erreicht man häufig schon dadurch, dass man eine Nachricht in einem verschlossenen Briefumschlag verschickt, statt sie auf eine Postkarte zu schreiben. All diese Maßnahmen bieten keinen hinreichenden Schutz vor der Ausspähung und Manipulation durch Geheimdienste. Doch dies ist meines Wissens auch nicht die Anforderung, welche an die analogen Kommunikationsmittel gestellt wird.

Eine elektronische Lösung muss mindestens die gleichen Anforderungen erfüllen wie ihr analoges Gegenstück. Sonst bietet sie kaum einen Mehrwert und stellt den Nutzer sogar schlechter.

Das vermutlich wichtigste Merkmal kommt zum Schluss. Eine Lösung muss gleichermaßen auf dem Desktop-PC, Notebook, Tablet und selbstverständlich Smartphone nutzbar sein.

Digitale Signaturen für Authentizität, Integrität, Verbindlichkeit und Zurechenbarkeit

Ich belasse es hier bewusst bei einer ganz allgemeinen und un-technischen Beschreibung des Verfahrens.

Eine digitale Signatur besteht grundsätzlich aus zwei Komponenten. Einer Komponente zum Signieren einer Nachricht bzw. eines Antrags oder sonstigen Dokuments und einer Komponente, mit welcher eine solche Signatur überprüft und ihrem Besitzer zugeordnet werden kann.

Und technische Internetstandards dazu existieren bereits. Das Rad muss nicht neu erfunden werden:

Unbestritten ist, dass es im Bereich der nutzbaren Implementierung dieser Standards noch erhebliches Verbesserungspotenzial gibt.

Vertraulichkeit durch Verschlüsselung

Hierfür existieren in der IT bereits etablierte Ansätze. Diese sind oben in vier Punkten bereits aufgeführt.

Den größten Fehler, den man begehen kann, ist eine eigene Verschlüsselung für seine Anwendung zu entwickeln. Die Erfahrung zeigt, dass es nicht lange dauert, bis diese gebrochen ist. Auch hier gilt, erfindet das Rad nicht neu.

Ob es sich dabei stets um Ende-zu-Ende-Verschlüsselung handeln muss, stelle ich in Frage. Ein Brief wird häufig bereits im Posteingang geöffnet und dann intern an die bearbeitende Stelle weitergeleitet. Äquivalent und in vielen Fällen ausreichend wäre demnach eine Transport-Verschlüsselung, welche eine Nachricht verschlüsselt vom Sender an den Verantwortungsbereich einer Organisation bzw. des Empfängers transportiert, wo diese intern jedoch entschlüsselt weitergeleitet und bearbeitet werden kann. Dem spricht nicht entgegen, dass es Nachrichten einer erhöhten Vertraulichkeitsstufe geben kann, welche nur durch bestimmte Empfänger entschlüsselt werden können dürfen.

In diesem Bereich existieren bereits funktionierende Lösungen, welche die klassische E-Mail ergänzen. Zugegeben sind diese aktuell jedoch technisch versierten Personen vorbehalten, da es seit Jahren an einfach zu nutzenden Client-Implementierungen mangelt.

Einwurf-Einschreiben und das Fax mit Sendebericht

Sind Fristen zu wahren, ist es nach meiner Erinnerung ausreichend, wenn eine Nachricht innerhalb der Frist im Verantwortungsbereich des Empfängers eingeht. Damit kann der Briefkasten oder das empfangende Fax gemeint sein. Zum Nachweis dient dem Sender in diesen Fällen ein Einschreiben oder der Sendebericht des Fax.

Entsprechende rechtliche Rahmenbedingungen vorausgesetzt, wäre es ausreichend, wenn eine E-Mail den empfangenden Mailserver fristgerecht erreicht. Mit der „Delivery Status Notification (DSN)“ existiert auch hier bereits eine technische Lösung, bei welcher der Mailserver eine Status-E-Mail an den Absender der E-Mail versendet. Einziger Haken an dieser Sache ist, dass es aktuell allein in der Verantwortung des Mailserver-Betreibers liegt, ob diese Funktion aktiviert ist oder nicht. Man kann sich also nicht darauf verlassen, dass man eine entsprechende Benachrichtigung erhält.

Warum es bisher nicht geklappt hat

Hier lassen sich in meinen Augen zwei Problembereiche differenzieren.

Sicherheit und Nutzbarkeit

Die gute alte E-Mail an sich ist wie eine Postkarte. Jeder, der sie auf dem Transportweg in die Hände bekommt, kann sie lesen. Um die E-Mail für Authentizität und Integrität zu ertüchtigen, gibt es seit Jahren OpenPGP und S/MIME, welche für normale Nutzer völlig unbenutzbar sind. Selbst unter meinen IT-Kollegen sind diese Verfahren nicht weit verbreitet.

Selbst wenn das Projekt „pretty Easy privacy“ hier eine Vereinfachung der Handhabung anstrebt, bleibt hier das Problem, dass OpenPGP-Signaturen keine qualifizierten Signaturen nach Signaturgesetz darstellen.

Bei den Alternativen sieht es jedoch nicht besser aus. An dieser Stelle mache ich es mir einfach und verlinke die entsprechenden Abschnitte in der Wikipedia zu DE-Mail, ePostbrief und BeA.

Henne-Ei-Problem

Lange Zeit besaß ich sowohl eine DE-Mail- als auch ePostbrief-Adresse und wartete auf entsprechende Angebote, wo ich einen Mehrwert aus der Nutzung ziehen kann.

Ich bin jetzt jedenfalls für die De-Mail
gerüstet und hoffe, dass im Laufe des Jahres möglichst viele
öffentliche Einrichtungen und Unternehmen der Privatwirtschaft ebenfalls
die Möglichkeit schaffen, die Kommunikation via De-Mail abzuwickeln.
Denn nur wenn diese Institutionen mitziehen wird sich die De-Mail
durchsetzen können und einen echten Mehrwert bieten. Und so werde ich
skeptisch und gespannt die weitere Entwicklung der De-Mail beobachten.

Auf dem Weg zur DE-Mail Adresse

Das Zitat stammt aus einem Beitrag von 2013. Für diesen Beitrag habe ich noch einmal geprüft, welche der Organisationen eine DE-Mail-Adresse besitzen, mit denen ich gerne auf sicherem Wege kommunizieren möchte. Das Ergebnis lässt sich aus folgender Tabelle ablesen.

Name der Organisation/des Unternehmens/der BehördeDE-Mail ja/nein?
Meine Direkt-Banknein
Meine Hausbanknein
Mein Arbeitgebernein
LBV NRWja
Meine Krankenkassenein
Alle meine verschiedenen Versicherungsanbieternein
Meine Gemeindeverwaltungnein
Die Kreisverwaltungja
Von mir regelmäßig genutzter Online-Handelnein
Tabelle: Wer unterstützt DE-Mail?

Zumindest für mich persönlich ist das Angebot sehr überschaubar. Dabei sind die DE-Mail-Adressen dann auch noch häufig gut auf den Webseiten der Anbieter versteckt. Andere, komfortabel nutzbare Kontaktmöglichkeiten stehen bereit und im Vordergrund.

Obige Anbieter haben alle gemeinsam, dass es akzeptable Kontaktmöglichkeiten gibt. So ist auf Seite der Empfänger und auf meiner Seite als Absender die Motivation gering, DE-Mail zu nutzen.

Dieses Henne-Ei-Problem wurde bis heute nicht gebrochen. Und ich glaube nicht daran, dass sich dies noch ändern wird.

Ein ähnliches Henne-Ei-Problem sehe ich aktuell auch noch bei der eID-Funktion des elektronischen Personalausweises. Außer meiner Kfz-Zulassungsstelle habe ich noch keine weiteren Anbieter gefunden, wo mir diese Funktion einen Vorteil bringt.

Wie könnte eine Lösung aussehen?

Im ersten Abschnitt dieses Beitrags habe ich bereits etwas zu Authentizität, Integrität, Verbindlichkeit und Zurechenbarkeit geschrieben. Alle diese Punkte würde ich mit einem Produkt im Scheckkartenformat adressieren, das viele Deutsche Staatsbürger bereits ihr Eigen nennen. Mit dem Personalausweis:

Dieser Personalausweis bietet neben einer Online-Ausweis-Funktion auch die Möglichkeit, Signaturzertifikate für eine qualifizierte elektronische Unterschrift zu speichern.

Mit der Online-Ausweis-Funktion gibt es die Henne. Jetzt brauchen wir noch Eier. Und mit Eiern meine ich Angebote der Behörden, Ämter und Verwaltungen zur Nutzung dieser Funktion. Diese sind nicht durch Gewinnerzielungsabsicht gehemmt und können maßgeblich dazu beitragen, den Teufelskreis zu durchbrechen. Bei den notwendigen Prozessen muss ein Fokus darauf gelegt werden, die Hürde zur Adaption durch private Unternehmen nicht zu hoch zu legen, da diese sonst keine Motivation haben, ein weiteres Authentifizierungsverfahren anzubieten.

Es gibt Kartenlesegeräte und Apps. Hier fehlt es in meinen Augen eigentlich nur noch an Angeboten.

Etwas düsterer sieht es aktuell mit der Unterschrift aus:

Derzeit gibt es keinen Anbieter für Signaturzertifikate, die mit dem Personalausweis verwendet werden können.

URL: https://www.personalausweisportal.de/Webs/PA/DE/buergerinnen-und-buerger/der-personalausweis/funktionen/funktionen-node.html#doc14626304bodyText3

Das traurige Ende dieser Funktion ist in einem heise-Artikel aus Oktober 2018 nachzulesen. Die darin genannte Petition erreichte ihr Quorum leider nicht. Die Frage lautet nun, wo bekommen wir eine Henne für diese Funktion her? Hier wünsche ich mir, dass unsere Bundesregierung uns diese beschafft.

Denn ein Teil der Infrastruktur, welche zur Verwaltung von Signaturzertifikaten benötigt wird, existiert bereits. Um einen neuen Personalausweis zu beantragen, muss die Identität des Antragstellers festgestellt werden. Hier kann ein und derselbe Verwaltungsprozess sowohl zur Beantragung des Personalausweises, als auch zur Beantragung eines Signaturzertifikats benutzt werden.

Der Vorteil für die Bürgerinnen und Bürger ist offensichtlich. Mit einem Gang zum Amt erhalten sie ihren Personalausweis mit Signaturzertifikat. Sie müssen sich daheim nicht mehr damit beschäftigen, wie sie nun ein Zertifikat auf ihren nPA bekommen.

Alternativ dazu bietet die Möglichkeit der Fernsignatur evtl. die Chance, an unsere Henne zu kommen. Das BSI hat hierzu von 2019 bis 2020 ein Pilotprojekt durchgeführt und erfolgreich beendet.

Anschließend sind es auch hier die Behörden, Ämter und Verwaltungen, welche die ersten Eier legen müssen, um die kritische Masse zu erreichen. Andere Organisationen werden dann nachziehen. Denn ich bin mir sicher, das Interesse an einer sicheren digitalen Unterschrift ist groß.

Damit hätten wir eine Lösung, um sich online auszuweisen und um Dokumente digital zu unterschreiben (signieren). Was noch fehlt, ist eine Möglichkeit diese Dokumente, unter Einhaltung eines Mindestmaß an Vertraulichkeit, an den gewünschten Empfänger zu versenden.

Tja, hier fällt mir leider auch nichts besseres ein, als die gute alte E-Mail zu ertüchtigen. Alternativ kann ich mir jedoch auch einen SSL/TLS-geschützten Uploadbereich beim Empfänger vorstellen, in den ich meine Anträge/Dokumente hochladen kann und nach dem erfolgreichen Upload eine Quittung bekomme. Allerdings fehlt bei letztem Verfahren die Antwortmöglichkeit.

Mit dem nPA als Signaturkarte und der dazugehörigen Infrastruktur fehlt es hier allerdings nur noch an passenden Clientanwendungen, um diese Zertifikate praktisch nutzbar zu machen.

Stammen die für die Verschlüsselung benötigten öffentlichen Schlüssel eines Empfängers aus einem amtlichen Verzeichnis, wurde im Vorfeld geprüft, ob der öffentliche Schlüssel von Bob auch wirklich zu Bob gehört. Und nicht Trudy einfach einen Schlüssel auf einen Schlüsselserver hochlädt und behauptet, Bob zu sein.

Sicher ist es nicht ganz so einfach, wie hier geschrieben. Sonst hätte es ganz sicher schon jemand umgesetzt. Doch denke ich, dass man ausgehend vom Personalausweis und dem elektronischen Aufenthaltstitel hier eine Lösung schaffen kann. Unsere Regierung muss es sich dazu im „Neuland“ nur gemütlich einrichten und vorangehen.

PS: Und vielleicht klappt es ja irgendwann doch noch mit verschlüsselter E-Mail-Kommunikation. ;)

Kommentare auf My-IT-Brain

05. September 2021 um 09:36

Liebe Leserinnen und Leser,

es freut mich, wenn euch meine Artikel gefallen und ihr euch die Zeit nehmt, sie zu kommentieren.

Leider wird auch dieses Blog, wie viele andere, von Kommentar-Spam geplagt. Es kann daher vorkommen, dass mancher legitime Kommentar fälschlicher Weise als Spam markiert und aussortiert wird. Wenn ich einmal pro Woche die Spamliste überfliege, kann es passieren, dass ich euren Kommentar darin schlicht übersehe. Dies tut mir leid. Doch kann ich es einfach nicht leisten, alle, als Spam markierten, Kommentare einzeln zu prüfen. Daher habe ich eine Bitte.

Falls ihr einen Kommentar zu einem meiner Beiträge geschrieben oder auf einen Kommentar geantwortet habt und euer Kommentar nicht innerhalb von 1-2 Tagen freigeschaltet wird, schreibt bitte eine kurze E-Mail an webmaster(aet)my-it-brain(Punkt)de. Dann schaue ich gezielt nach.

Sollte diesers Blog eure Kommentare in der Vergangenheit verschluckt haben, möchte ich mich an dieser Stelle dafür entschuldigen.

Kommentar: Linux-Container — Spreu und Weizen

30. August 2021 um 07:00

In diesem Beitrag möchte ich meine persönliche Meinung zu und über Linux-Container mit euch teilen. Ich freue mich, wenn sich daraus eine Diskussion entwickelt, in der ihr eure Erfahrungen und Gedanken zum Thema einbringt.

Mir geht es dabei ausschließlich um Linux-Container, welche ich von ähnlichen Konzepten wie z.B. den LDOMs und Kernel-Zones unter Solaris, etc. bewusst abgrenzen möchte.

Was habe ich mit Containern zu tun?

Nun, Container haben in vielen Branchen Fuß gefasst, in denen IT/EDV eine Rolle spielt und werden voraussichtlich nicht mehr verschwinden. Ich selbst bin als Sysadmin und Nerd sowohl aus privatem Interesse, als auch beruflich mit dem Thema in Berührung gekommen.

Mit den Konzepten und der Architektur bin ich vertraut. Mit dem Wochenendprojekt „Kanboard im Container…“ verfüge ich über wenig praktische Erfahrung.

Wie lautet das Versprechen der Container-Technologie?

Alles wird agiler, schneller, effizienter, sicherer UND einfacher. Das Übliche halt.

Im Wesentlichen bieten Container die Chance, dass Anwendungen mit all ihren Abhängigkeiten ausgeliefert werden können.

Damit könnte das Ende der Zeit eingeläutet werden, wo einer Anwendung eine Installationsanleitung mit dem Kapitel „Systemvoraussetzungen“ beiliegt, mit welcher der Administrator sich auf die Suche nach den benötigten Bibliotheken und Paketen macht, welche in seiner konkreten Umgebung zu installieren und zu konfigurieren sind, bevor die eigentliche Anwendung installiert werden kann.

In der schönen neuen Welt verpacken Entwickler alles, was ihre Anwendung braucht, in einen Container, welchen sie anschließend in den Versand geben (deployen) können. Auf dem Zielsystem wird nur noch eine kompatible Container-Engine benötigt und die Anwendung läuft.

Dabei sind Szenarien realistisch, in denen Anwendungen z.B. in einem Ubuntu-Userland auf einem RHEL-Kern laufen und umgekehrt.

Auch Update-Szenarien können deutlich vereinfacht werden. Ein neues Release kommt in Form eines neuen Container-Images, welches instanziiert wird. Gibt es Probleme, bringt man die laufende Instanz um und startet eine Instanz vom vorherigen Container-Image. Vorausgesetzt die Container beinhalten keine persistent zu speichernden Daten (was sie laut Konzept nicht sollen), kann das wirklich gut funktionieren.

Und wie fühlt sich das bis jetzt in der Praxis an?

Die kurze Antwort auf diese Frage lautet: „Sehr unterschiedlich. Das Spektrum reicht von gut bis durchwachsen.“

Ich möchte noch einmal erwähnen, dass ich Systemadministrator und kein Anwendungsentwickler bin. Ich entwickle also keine Software, welche dann mit CI/CD-Pipelines verarbeitet und ausgerollt wird. Meine Aufgabe ist eher die Bereitstellung und der Betrieb von Umgebungen, in denen Container ausgeführt werden können. Zu möglichen Kunden/Nutzern zählen dabei Teams, die eigene Anwendungen entwickeln, aber auch Teams, welche Anwendungen in Form von Container-Repositorien bzw. -Images geliefert bekommen und diese dann betreiben müssen.

Insbesondere in dem Bereich, wo uns die Aufgabe des Betriebs von extern erstellten Anwendungen obliegt, machen wir gerade ein paar Erfahrungen, die ich hier gerne aus meiner persönlichen Sicht teilen möchte.

Beginnen möchte ich mit der insgesamt positiven Erfahrung, die ich mit meinem Wochenendprojekt „Kanboard im Container…“ gemacht habe. Hier laufen eine Anwendung und eine Datenbank jeweils als Container in einem Pod auf einem RHEL 8 Host mit einer Rootless-Podman-Installation und einem Reverse-Proxy. Die Dokumentation von Red Hat und dem Kanboard-Projekt sind hinreichend genau und verständlich, um diese Anwendung ohne große Mühe zu betreiben. Ohne große Verrenkungen kann ich unterschiedliche Versionen aus dem Postgres-Container-Repo ausprobieren und verschiedene Releases der Anwendungen testen.

Leider hat man nicht immer soviel Glück. Ein anderes Software-Projekt, dessen Namen ich hier bewusst nicht nenne, liefert eine kleine Sammlung von Bash-Skripten aus, welche in einer bestimmten Reihenfolge auszuführen sind, um zur Laufzeit eine Docker-Compose-Datei zu generieren, auf deren Basis dann entsprechende Container gestartet werden. Wenn nun ein Update ansteht, ist der ganze Prozess mit der Ausführung der Bash-Skripte in wohldefinierter Reihenfolge erneut durchzuturnen. Das ganze lässt sich ausschließlich auf einem Host mit einer Docker-Installation ausführen und ist zu Podman inkompatibel. Ob es auch mit einer Rootless-Docker-Installtion läuft, ist noch zu testen. Ein Deployment auf einem Kubernetes-Cluster ist undenkbar. Das Projekt stellt keinerlei Informationen dazu bereit.

Übrigens handelt es sich bei diesem Projekt nicht um ein 1-2 Personen FOSS-Projekt, sondern um eines, hinter dem ein Unternehmen steht, welches kostenpflichtige Support-Verträge für seine Anwendung vertreibt.

Es bleibt also wieder mal nur, die eigene Umgebung der Anwendung anzupassen, die sich andernfalls nur mit extrem hohen Aufwand integrieren lässt. Das kennen wir schon aus dem Zeitalter vor der Container-Erscheinung. Es ist in diesem Fall halt etwas anders, aber nicht besser.

In einem anderen Fall blieb das Erfolgserlebnis aus ähnlichen Gründen aus. Der Container mit der gewünschten Anwendung lies sich nicht in die Zielumgebung integrieren, da ein für die Kommunikation benötigtes Software-Modul fehlt. Erste Aussage des Herstellers: „Da müssen sie noch Paket XY im Container nachinstallieren.“

Halt Stopp! Sollten mit dem Container nicht alle notwendigen Abhängigkeiten mit ausgeliefert werden? Jetzt sollen wir Software im Container nachinstallieren, was zur Folge hat, dass wir damit ein neues Image erzeugen, welches wir zukünftig wieder selbst weiterpflegen dürfen? So habe ich mir die schöne neue Welt aber nicht vorgestellt. Den Aufwand mit den eigenen Anpassungen haben wir ohne Container auch. Auch hier wird es erstmal nur anders, aber nicht besser.

Allerdings möchte ich zur Ehrenrettung des Anbieters hinzufügen, dass er das fehlende Modul in sein Image einbauen und zukünftig selbst pflegen und ausliefern möchte und uns hier lediglich um Unterstützung beim Test bittet. Dies ist für mich im Sinne von FOSS und vollkommen akzeptabel. Wir wissen allerdings noch nicht, ob der Anbieter sein Versprechen hält.

Wo ist nun das Dilemma?

Ich persönlich habe eine Präferenz, wie Betriebsplattformen für Container aussehen sollten. So sehe ich die Nutzung von Rootless-Podman für einfache Anwendungen und Kubernetes bzw. Kubernetes-kompatible Lösungen für die Orchestrierung als sinnvoll an.

Leider kann ich mir nicht immer aussuchen, welche Software es zu betreiben gilt. Allzu oft muss mit dem gearbeitet werden, was bestellt bzw. geliefert wurde. Und hier sind die Probleme fast so zahlreich wie außerhalb der Container-Welt. Die einen laufen nur mit Docker, aber nicht im Rootless-Modus. Die anderen verlangen eine Docker-Swarm-Umgebung und Kubernetes mögen sie beide nicht. Das ist halt Pech.

Manchmal lassen sich die gelieferten Container auch ganz einfach starten, dafür aber überhaupt nicht in bestehende Umgebungen integrieren. So kann es schon in Arbeit ausarten, wenn man den voreingestellten Datenbank-Container herausoperieren muss, um den vorhandenen Datenbank-Cluster nutzen zu können.

Ein wenig neidisch blicke ich dabei zu Berufskollegen, die eigene Softwareentwicklung betreiben und von den Vorzügen ihrer Kubernetes-Cluster schwärmen.

Allerdings stehe ich mit meinen Erfahrungen noch ganz am Anfang und lasse mich gerne überraschen, was die Zukunft noch bringt.

Was habt ihr für Erfahrungen im Umgang und mit dem Betrieb von Containern gemacht? Könnt ihr hier Geschriebenes in Teilen nachvollziehen oder sind eure Erfahrungen völlig anderer Natur? Ich freue mich auf eure Beiträge in den Kommentaren und per E-Mail.

Bis bald im schönen neuen Container-Land.

Quick Ansible: Enforce SSHD configuration options

09. August 2021 um 07:00

You need to enforce certain configuration options in sshd_config, while leaving the rest of the config to your colleagues? Your colleagues need to be able to change these parameters too, temporarily, but they should be reset after a certain time? And you wanna do it with Ansible? Read on.

---
- hosts: all
  tasks:
  - name: sshd configuration file update
    blockinfile:
      path: /etc/ssh/sshd_config
      insertbefore: BOF # Beginning of the file
      marker: "# {mark} ANSIBLE MANAGED BLOCK BY LINUX-ADMIN"
      block: |
        PermitRootLogin no
        PubkeyAuthentication yes
        AuthorizedKeysFile .ssh/authorized_keys
        PasswordAuthentication no
      backup: yes
      validate: /usr/sbin/sshd -T -f %s

  - name: Restart SSHD
    service:
      name: sshd
      state: restarted

I’ll show you a playbook that sets the options PermitRootLogin, PubkeyAuthentication, AuthorizedKeysFile and PasswordAuthentication using the Ansible module blockinfile.

What happens here is that at the beginning of the file sshd_config a block is getting inserted containing the shown key-argument pairs. Inserting this block at the beginning of the file ensures that these lines are used, because first occurrence wins (see sshd_config(5)).

This playbook ensures the desired configuration that the user root is not permitted to login via ssh, public key authentication is enabled, the .ssh/authorized_keys file from user’s HOME directory should be used, and password authentication is disabled. Before /etc/ssh/sshd_config gets changed a backup is created and the new file is going to be validated prior to saving it.

The second task restarts the sshd service to make sure the desired config is going to be used.

Of course, any user with sudo or root access could edit the sshd_config file and restart the service to change the desired settings; and it might be OK to do so temporarily. To make sure any changes to the file will be reset to the desired config you could just run the playbook every 30 minutes per cron.

This was a really quick example of how to use ansible to set or change configuration settings. I hope you enjoyed it.

Neue Schwachstelle in Linux(-Paket) gefunden! Bin ich betroffen?

02. August 2021 um 07:00

Es ist nur eine Frage der Zeit, bis die Fachpresse oder ein CERT über eine neue Schwachstelle im Linux-Kern oder einem der anderen für Linux verfügbaren Pakete berichtet. Diese Schwachstellen werden meist unter einer sogenannten CVE-Nummer geführt, welche die jeweilige Schwachstelle eindeutig referenziert.

In diesem Artikel beschreibe ich, wie ihr mit Hilfe der CVE-Nummer herausfinden könnt, ob euer System betroffen ist und wie ihr die aktualisierte Paketversion identifiziert, welche gegen die beschriebene Schwachstelle abgesichert ist. Der Text ist in Abschnitte gegliedert, welche die entsprechende Vorgehensweise für die Distributionen Debian (Link zum Abschnitt), RHEL (Link zum Abschnitt) und Ubuntu (Link zum Abschnitt) beschreiben.

Debian Security Bug Tracker

Unter der URL https://security-tracker.debian.org/tracker/ befindet sich der Security Bug Tracker des Debian-Projekts. Am Ende der Bug-Tracking-Seite gibt es ein Suchfeld, über welches man nach einer CVE-Nummer suchen kann.

screenshot-debian-security-bug-tracker
Screenshot: Security Bug Tracker

Der folgende Screenshot zeigt das Suchergebnis für CVE-2021-33909.

screenshot-search-result-cve-2021-33909
Screenshot: Ergebnis der Suche nach CVE-2021-33909

In der unter der Überschrift „Vulnerable and fixed Packages“ dargestellten Tabelle werden die verwundbaren und abgesicherten Paketversionen für die aktuell unterstützten Debian-Releases aufgeführt. So ist in diesem Fall das Paket für den Linux-Kern in Version 4.19.194-1 verwundbar, während mit der aktualisierten Version 4.19.194-3 eine abgesicherte Version bereitsteht.

Um nun zu sehen, welche Version auf dem eigenen System läuft, kann man z.B. das folgende Kommando verwenden, welches die Version des laufenden Kernels ausgibt:

tronde@host:~$ uname -v
#1 SMP Debian 4.19.194-2 (2021-06-21)

Da es sich bei der laufenden Version nicht um die abgesicherte Version handelt, ist davon auszugehen, dass das System verwundbar ist. Ein Update ist hier also angeraten.

Der folgende Code-Block zeigt, dass ein entsprechendes Update auch bereits angeboten wird (Ausgabe gekürzt):

tronde@host:~$ apt list --upgradable
Auflistung... Fertig
[...]
linux-image-4.19.0-17-amd64/stable 4.19.194-3 amd64 [aktualisierbar von: 4.19.194-2]
[...]

Für ein Nicht-Kernel-Paket sieht der Ablauf ein wenig anders aus. Nehmen wir dazu beispielhaft eine Schwachstelle im Paket systemd. Dazu suchen wir im Security Bug Tracker nach CVE-2021-33910.

screenshot-search-result-cve-2021-33910
Screenshot: Suchergebnis zu CVE-2021-33910

Die systemd-Paketversion 241-7~deb10u7 ist also gegen diese Schwachstelle verwundbar, während Version 241-7~deb10u8 abgesichert ist. Eine Möglichkeit, sich die installierte Version anzeigen zu lassen, besteht mit dem Befehl dpkg -l <PAKETNAME>, wobei die Spalte „Version“ die relevante Versionsnummer enthält:

tronde@host:~$ dpkg -l systemd
Gewünscht=Unbekannt/Installieren/R=Entfernen/P=Vollständig Löschen/Halten
| Status=Nicht/Installiert/Config/U=Entpackt/halb konFiguriert/
         Halb installiert/Trigger erWartet/Trigger anhängig
|/ Fehler?=(kein)/R=Neuinstallation notwendig (Status, Fehler: GROSS=schlecht)
||/ Name           Version       Architektur  Beschreibung
+++-==============-=============-============-=================================
ii  systemd        241-7~deb10u7 amd64        system and service manager

Der Ausgabe ist zu entnehmen, dass auch in diesem Fall die verwundbare Version installiert ist. Auch hier stehen Updates für mehrere Pakete zur Verfügung:

tronde@host:~$ apt list --upgradable | grep systemd

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

libpam-systemd/stable 241-7~deb10u8 amd64 [aktualisierbar von: 241-7~deb10u7]
libsystemd0/stable 241-7~deb10u8 amd64 [aktualisierbar von: 241-7~deb10u7]
systemd-sysv/stable 241-7~deb10u8 amd64 [aktualisierbar von: 241-7~deb10u7]
systemd/stable 241-7~deb10u8 amd64 [aktualisierbar von: 241-7~deb10u7]

Ich empfehle an dieser Stelle, alle angebotenen Updates zu installieren, da diese in aller Regel mehr Vorteile als Nachteile für das aktuelle System bedeuten.

Red Hat CVE Database

Red Hat bietet unter der URL https://access.redhat.com/security/security-updates/#/cve eine Datenbank zur Suche nach CVEs an. Ruft man die URL auf, so werden existierende CVEs in umgekehrt chronologischer Reihenfolge angezeigt. Über das Suchfeld kann gezielt nach CVE-Nummern gesucht werden. Die Ergebnisse werden anschließend in tabellarischer Form präsentiert.

rh-cve-database
Screenshot: Red Hat CVE Database

Mit einem Klick auf die CVE-Nummer gelangt man auf eine Seite, welche die Schwachstelle im Detail beschreibt und darüber hinaus Informationen zur Mitigation und abgesicherten Paketen bietet. Der folgende Screenshot zeigt einen Auszug dieser Seite für CVE-2021-33909. Darin ist eine Tabelle dargestellt, welcher die betroffenen Plattformen und die jeweiligen Paketnamen zu entnehmen sind. Die Tabelle lässt sich über das Suchfeld weiter filtern und nach Spalten sortieren. So kann man leichter einen Überblick über alle von der Schwachstelle betroffenen Pakete der eigenen Plattform bekommen.

screenshot-affected-pkgs-and-issued-errata
Screenshot: Affected Packages and Issued Red Hat Security Errata for CVE-2021-33909

Red Hat behebt sicherheitsrelevante Probleme mit Hilfe sogenannter Red Hat Security Advisories (RHSA). Der Spalte Errata der obigen Tabelle ist das jeweilige RHSA zu entnehmen. Ein Klick darauf führt zur jeweiligen Beschreibung des RHSA. Es ist nicht unüblich, dass ein RHSA mehrere Schwachstellen adressiert, wie das Beispiel RHSA-2021:2725 zeigt. Darüber hinaus bieten die RHSA Informationen, welche Pakete aktualisiert wurden und ob ein Neustart des Systems erforderlich ist, um eine Schwachstelle zu schließen.

In dem hier gewählten Beispiel ist das RHEL7-Kernel-Paket kernel-3.10.0-1160.36.2.el7.x86_64.rpm gegen CVE-2021-33909 abgesichert. Folgender Befehl zeigt mir, dass dieses Paket auf meinem RHEL7-System noch nicht verwendet wird:

[tronde@rhel7 ~]$ uname -r
3.10.0-1160.31.1.el7.x86_64

Alternativ kann man die Paketversion auch mit dem Kommando rpm -qa | grep <PAKETNAME> ermitteln. Dieses Kommando funktioniert auch für Nicht-Kernel-Pakete.

[tronde@rhel7 ~]$ rpm -qa | grep kernel
kernel-3.10.0-1160.31.1.el7.x86_64
kernel-devel-3.10.0-1160.24.1.el7.x86_64
kernel-devel-3.10.0-1160.31.1.el7.x86_64
kernel-3.10.0-1160.24.1.el7.x86_64
texlive-l3kernel-svn29409.SVN_4469-45.el7.noarch
kernel-headers-3.10.0-1160.31.1.el7.x86_64
kernel-3.10.0-1160.21.1.el7.x86_64
abrt-addon-kerneloops-2.1.11-60.el7.x86_64
kernel-devel-3.10.0-1160.21.1.el7.x86_64
kernel-tools-libs-3.10.0-1160.31.1.el7.x86_64
kernel-tools-3.10.0-1160.31.1.el7.x86_64

Dank des RHEL-Paket-Managers YUM bzw. DNF und der in den Repositories bereitgestellten Metainformationen, müssen jedoch nicht mühsam Versionsnummern manuell abgeglichen werden. Die Kenntnis der CVE-Nummer oder des RHSA genügen. Der erste Code-Block zeigt, wie ein RHEL7-System gegen CVE-2021-33909 abgesichert werden kann (Ausgabe gekürzt):

[tronde@rhel7 ~]$ sudo yum --cves=CVE-2021-33909 update
[sudo] Passwort für tronde: 
Geladene Plugins: langpacks, nvidia, product-id, search-disabled-repos,
                : subscription-manager
[...]
7 package(s) needed (+0 related) for security, out of 27 available
Abhängigkeiten werden aufgelöst
--> Transaktionsprüfung wird ausgeführt
---> Paket bpftool.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket bpftool.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket kernel.x86_64 0:3.10.0-1160.36.2.el7 markiert, um installiert zu werden
---> Paket kernel-devel.x86_64 0:3.10.0-1160.36.2.el7 markiert, um installiert zu werden
---> Paket kernel-headers.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket kernel-headers.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket kernel-tools.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket kernel-tools.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket kernel-tools-libs.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket kernel-tools-libs.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket python-perf.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket python-perf.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
--> Abhängigkeitsauflösung beendet
--> Transaktionsprüfung wird ausgeführt
---> Paket kernel.x86_64 0:3.10.0-1160.21.1.el7 markiert, um gelöscht zu werden
---> Paket kernel-devel.x86_64 0:3.10.0-1160.21.1.el7 markiert, um gelöscht zu werden
--> Abhängigkeitsauflösung beendet

Abhängigkeiten aufgelöst

================================================================================
 Package            Arch    Version                  Paketquelle          Größe
================================================================================
Installieren:
 kernel             x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms    50 M
 kernel-devel       x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms    18 M
Aktualisieren:
 bpftool            x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.5 M
 kernel-headers     x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   9.0 M
 kernel-tools       x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.1 M
 kernel-tools-libs  x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.0 M
 python-perf        x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.1 M
Entfernen:
 kernel             x86_64  3.10.0-1160.21.1.el7     @rhel-7-server-rpms   64 M
 kernel-devel       x86_64  3.10.0-1160.21.1.el7     @rhel-7-server-rpms   38 M

Transaktionsübersicht
================================================================================
Installieren   2 Pakete
Aktualisieren  5 Pakete
Entfernen      2 Pakete

Gesamtgröße: 110 M
Is this ok [y/d/N]:

Mit diesem einen Befehl ist es möglich, gezielt alle betroffenen Pakete zu aktualisieren, um die Schwachstelle zu schließen. Sollen in einem Durchgang mehrere CVEs geschlossen werden, so können mehrere CVE-Nummern durch Kommata getrennt angegeben werden.

Ebenso ist es möglich, mit den RHSA-Nummern zu arbeiten, wie der folgende Code-Block zeigt (Ausgabe gekürzt):

[tronde@rhel7 ~]$ sudo yum --advisory=RHSA-2021:2725 update
Geladene Plugins: langpacks, nvidia, product-id, search-disabled-repos,
                : subscription-manager
[...]
7 package(s) needed (+0 related) for security, out of 27 available
Abhängigkeiten werden aufgelöst
--> Transaktionsprüfung wird ausgeführt
---> Paket bpftool.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket bpftool.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket kernel.x86_64 0:3.10.0-1160.36.2.el7 markiert, um installiert zu werden
---> Paket kernel-devel.x86_64 0:3.10.0-1160.36.2.el7 markiert, um installiert zu werden
---> Paket kernel-headers.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket kernel-headers.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket kernel-tools.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket kernel-tools.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket kernel-tools-libs.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket kernel-tools-libs.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
---> Paket python-perf.x86_64 0:3.10.0-1160.31.1.el7 markiert, um aktualisiert zu werden
---> Paket python-perf.x86_64 0:3.10.0-1160.36.2.el7 markiert, um eine Aktualisierung zu werden
--> Abhängigkeitsauflösung beendet
--> Transaktionsprüfung wird ausgeführt
---> Paket kernel.x86_64 0:3.10.0-1160.21.1.el7 markiert, um gelöscht zu werden
---> Paket kernel-devel.x86_64 0:3.10.0-1160.21.1.el7 markiert, um gelöscht zu werden
--> Abhängigkeitsauflösung beendet

Abhängigkeiten aufgelöst

================================================================================
 Package            Arch    Version                  Paketquelle          Größe
================================================================================
Installieren:
 kernel             x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms    50 M
 kernel-devel       x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms    18 M
Aktualisieren:
 bpftool            x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.5 M
 kernel-headers     x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   9.0 M
 kernel-tools       x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.1 M
 kernel-tools-libs  x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.0 M
 python-perf        x86_64  3.10.0-1160.36.2.el7     rhel-7-server-rpms   8.1 M
Entfernen:
 kernel             x86_64  3.10.0-1160.21.1.el7     @rhel-7-server-rpms   64 M
 kernel-devel       x86_64  3.10.0-1160.21.1.el7     @rhel-7-server-rpms   38 M

Transaktionsübersicht
================================================================================
Installieren   2 Pakete
Aktualisieren  5 Pakete
Entfernen      2 Pakete

Gesamtgröße: 110 M
Is this ok [y/d/N]:

Auch hier können mehrere RHSA (oder auch RHBA und RHEA) durch Kommata getrennt angegeben werden. Die dargestellten Kommandos funktionieren selbstverständlich auch unter RHEL 8.

Damit ist es möglich, Schwachstellen gezielt und mit minimalen Auswirkungen auf das System zu schließen. Ich persönlich empfehle jedoch, das Patch-Fenster zu nutzen und sofern möglich alle verfügbaren Updates zu installieren. Denn in der Regel ist der Nutzen durch aktualisierte Pakete größer, als das Risiko eines potenziellen Schadens.

Die Paketmanager YUM und DNF bieten, Dank der von Red Hat bereitgestellten Metainformationen in den Repos, vielfältige Möglichkeiten, um die Installation oder Aktualisierung von Paketen granular zu steuern. Weiterführende Informationen finden sich den Manpages yum(8) und dnf(8).

In wie weit sich die hier beschriebene Vorgehensweise auch für CentOS Stream bzw. Fedora eignet, kann ich nicht sagen, da ich diese noch nicht untersucht habe.

Ubuntu CVE reports

Canonical stellt für Ubuntu unter der URL https://ubuntu.com/security/cve eine CVE-Datenbank bereit, in der sich der Status von Schwachstellen über deren CVE-Nummer recherchieren lässt.

screenshot-ubuntu-cve-reports-search
Screenshot: Ubuntu CVE reports search

Eine Suche nach einer CVE-Nummer führt zu einer Seiten mit einen Statusreport, welcher betroffene Pakete in den jeweiligen Releases und deren Status aufführt. Der folgende Screenshot zeigt dies beispielhaft für den CVE-2021-33909 und das Paket linux:

status-cve-2021-33909
Screenshot: Status des Paket ‚linux‘ zum CVE-2021-33909

Der Spalte „Status“ ist die Versionsnummer der abgesicherten Paketversion zu entnehmen. Die Vorgehensweise, um herauszufinden, welche Paketversion aktuell auf dem eigenen System installiert ist, entspricht der für Debian und kann im dortigen Abschnitt nachgelesen werden.

Zusammenfassung

Zumindest die im Rahmen dieses Artikels getesteten Distributionen bieten Webseiten, auf denen man sich zum Stand von Schwachstellen informieren kann. Dabei kann die in der Fachpresse oder vom CERT kommunizierte CVE-Nummer für eine gezielte Suche nach Informationen zur jeweiligen Schwachstelle verwendet werden.

Mir persönlich haben die Möglichkeiten von YUM und DNF zur granularen Steuerung und gezielten Mitigation von Schwachstellen am besten gefallen. Dabei sei jedoch erwähnt, dass ich längst nicht alle Distributionen und deren Paketwerkzeuge betrachtet habe.

Vorstellung: Red Hat Accelerators Program

26. Juli 2021 um 07:00

In diesem Beitrag möchte ich euch das Red Hat Accelerators Programm vorstellen und einige Beispiele geben, was wir dort so tun. Ich selbst bin seit 2019 Mitglied dieser Gemeinschaft und freue mich, mit IT-Experten aus verschiedensten Branchen und Red Hat selbst austauschen zu können. Dieser Artikel gibt meine persönliche Meinung und Sicht auf die Red Hat Accelerators wieder. Diese kann mit der von Red Hat übereinstimmen, muss es aber nicht.

Das Programm selbst beschreibt sich als globale Gemeinschaft, bestehend aus IT-Experten unter den Red Hat Kunden/Partnern, welche ihr Wissen und ihre Leidenschaft für Red Hat Produkte und Open Source Projekte mit Fachkollegen und Red Hat teilen und sich darüber austauschen mögen. Dem Einzelnen verspricht das Programm dabei folgenden Nutzen.

Netzwerken

Kurz gesprochen sind die Red Hat Accelerators ein Slack Channel voller interessanter Menschen. Diese stammen aus den verschiedensten Branchen, wie z.B. dem Gesundheitswesen, der Automobilindustrie, Versicherungen und Banken, um nur einige zu nennen. Dazu gesellen sich auch einige „Rote Hüte“, darunter Technical Account Manager, Mitarbeiter:innen aus verschiedenen Produkt-Teams und selbstverständlich die Community-Managerinnen Andi und Lili.

Wenn man seit vielen Jahren im gleichen Unternehmen arbeitet und stets nur zu den eigenen Kollegen Kontakt hat, stellt sich häufig eine gewisse Betriebsblindheit ein. Bei den Red Hat Accelerators bietet sich die Gelegenheit, mit Fachkollegen aus der gleichen, aber vor allem auch aus anderen Branchen in Kontakt zu treten und sich auszutauschen, um über den Tellerrand schauen zu können und der Betriebsblindheit entgegen zu wirken.

Ganz nebenbei lernt man neue Anwendungsfälle für bekannte oder weniger bekannte Produkte kennen. Gleiches gilt für Fehler in bzw. Probleme mit eben diesen Produkten. So bilden sich im Chat häufig so etwas wie spontane Arbeitskreise, die Probleme in der allerneusten Version eines Produktes adressieren. Hier wird sich gegenseitig geholfen. Und sollte einmal noch keine Lösung existieren, nimmt meist einer der anwesenden TAMs (steht wahlweise für Technical Account Manager oder The Almighty Moderator) das Problem/die Frage mit, um eine Lösung zu finden.

Mir hat sich durch diesen Austausch schon einige Male ein neuer Blickwinkel eröffnet, wodurch sich neue Lösungswege auftaten. Und das selbst über Red Hat Produkte hinaus.

Zugang zu Produkt-Teams und zukünftigen Releases

Für mich persönlich ist dies der größte Nutzen, den ich aus dem Red Hat Accelerators Programm ziehe. Ich habe hier die Möglichkeit, frühzeitig Kenntnis über (geplante) Neuerungen in Red Hat Produkten zu erlangen und durch qualifizierte Beiträge die Produktentwicklung mit zu beeinflussen.

Die Produkt-Teams stellen ihre Ideen und Pläne in gemeinsamen Videokonferenzen mit den Accelerators vor und diskutieren mit uns über Anwendungsfälle sowie Vor- und Nachteile der Änderungen.

Diese Form der Kommunikation hat Vorteile sowohl für Red Hat selbst, als auch für uns Kunden. Red Hat erfährt von seinen Kunden, wo der Schuh drückt, was sich diese wünschen, um ihren Arbeitsalltag effizienter zu gestalten. Als Kund erfährt man frühzeitig von geplanten Entwicklungen und Ideen und kann diese in gewissem Rahmen mit beeinflussen. Dazu möchte ich drei Beispiele geben.

Umfragen

Regelmäßig werden Umfragen zu Produkten aus dem Red Hat Portfolio und IT-Themen durchgeführt, die viele von uns im Arbeitsalltag betreffen. Red Hat nutzt diese Fragen dazu, um seine Kunden besser kennen zu lernen. Basierend auf diesen Umfragen werden weitere Sitzungen geplant, um einzelne Punkte in kleineren Arbeitsgruppen besprechen zu können.

Umfragen werden z.B. als webbasierte Formulare durchgeführt oder als Live-Interviews mit den Produkt-Teams.

Produktvorstellungen

Hier stellt ein Produkt-Team geplante Neuerungen, Änderungen oder neue Funktionen vor und stellt sich direkt der Kritik der Accelerators. Es wird dabei darauf geachtet, dass Kritik konstruktiv geäußert wird. Ein einfaches „Das ist Mist.“ oder „Das finde ich doof.“ ist dabei nicht gern gesehen. Ein konstruktives „Ich würde mir dieses oder jenes aus folgenden Gründen wünschen.“ wird gern entgegengenommen.

Als Accelerator hat man hier die Möglichkeit, seine Wünsche mitzuteilen. Es besteht keine Garantie und kein Anspruch, dass diese Berücksichtigung finden. Auch kann man die Entwicklung nicht direkt bestimmen. Doch hat Red Hat selbstverständlich ein Interesse daran, möglichst viele seiner Kunden bei der Stange und bei Laune zu halten. Denn ein glücklicher Kunde kauft gern nochmal, während ein unglücklicher Kunde vermutlich etwas neues ausprobiert.

Schön finde ich bei diesen Veranstaltungen auch, dass man erfahren kann, warum einige Wünsche nicht berücksichtigt werden oder auf der Roadmap sehr weit hinten anstehen müssen. Dies schafft Transparenz und ist in meinen Augen sehr zu begrüßen.

Doch auch für Red Hat kann es hier manchmal eine Enttäuschung geben, wenn z.B. ein Design-Entwurf von einer großen Mehrheit abgelehnt (im Sinne von: „Wir mögen das wirklich nicht und wünschen es uns wie folgt.“) wird.

Fokus-Gruppen

In den sogenannten Fokus-Gruppen bietet sich für ausgewählte Accelerators die Chance, eng mit einem Red Hat Produkt-Team zusammen zu arbeiten.

So hatte ich im Sommer 2020 das Vergnügen, in der Fokus-Gruppe Red Hat Insights unter Leitung von Mohit Goyal (Senior Principal Product Manager, Red Hat) mitzuarbeiten. Hier bot sich mir die Möglichkeit, die besonderen Anforderungen an den Einsatz einer solchen Lösung in Deutschland und in meiner Organisation zu vertreten und dafür zu sensibilisieren. Durch den Einfluss mehrerer Red Hat Accelerators wurde die geplante automatische Registrierung von RHEL-Systemen in Red Hat Insights auf unbestimmte Zeit verschoben.

So viel Einfluss auf eine laufende Produktentwicklung hatte ich bisher bei keinem anderen Hersteller. Und ich wünsche mir deutlich mehr davon.

Welche Vorteile hat Red Hat davon?

Selbstverständlich profitiert auch Red Hat von dem Accelerators-Programm. Wie bereits erwähnt, bekommt der Hersteller hier wertvolle Rückmeldungen von vertrauten Kunden, direkt aus der Praxis. Darüber hinaus stehen die Accelerators bereit, Produktneuheiten zu testen, zu validieren und den Einsatz in der eigenen Umgebung zu prüfen, bevor diese veröffentlicht werden. Dadurch kann bei Problemen noch rechtzeitig gegengesteuert werden.

Das Programm hilft Red Hat, seine Kunden und deren Bedürfnisse besser zu verstehen und die eigenen Produkte noch besser am Bedarf der Kunden auszurichten.

Und natürlich verfügt Red Hat mit den Accelerators über ein Heer aus Enthusiasten, Evangelisten und Missionaren, welche die Open Source Botschaft in die Welt hinaus tragen. Und wir alle wissen doch, dass Mund-zu-Mund-Propaganda die wirksamste Form der Werbung ist.

Wie kann man Mitglied werden?

Ihr seid bereits Red Hat Kunde und mein Beitrag hat euch neugierig gemacht, so dass ihr ebenfalls zu den Red Hat Accelerators dazustoßen möchtet? Das ist gut, denn die EMEA-Region und besonders der deutschsprachige Raum ist aktuell noch etwas unterrepräsentiert.

Bitte lest euch die Programm-Bedingungen (in englischer Sprache) durch und bewerbt euch.

Ich selbst darf übrigens keinerlei Geschenke von Red Hat oder dem Accelerators-Programm annehmen. Wenn ihr im letzten Feld des Bewerbungsformulars also meinen Namen angebt, ist mir nicht mehr und nicht weniger gewiss, als der ewige Dank von Andi und Lili.

Es ist in 2021 ein Lenovo ThinkPad T14s (AMD) geworden

07. Juni 2021 um 07:00

Anfang April habe ich mir Gedanken zu Neuer Hardware in 2021 gemacht. Zu der Zeit hatte ich ein TUXEDO Pulse 14 Gen 1 und ein ThinkPad P14s Gen 1 ins Auge gefasst.

Eure Rückmeldungen in den Kommentaren und das Studium etlicher Testberichte auf notebookcheck.net mündeten nun in einer Entscheidung. Besonders das umfangreiche Feedback von ‚Art‘ hat meine Kaufentscheidung beeinflusst. Danke dafür.

Ich habe mir nun ein Lenovo Campus ThinkPad T14s 20UJS00K00 für 1.399 Euro bei cyberport gekauft. Das Gerät beinhaltet (Quelle: Datenblatt):

  • CPU: AMD Ryzen™ 7 Pro 4750U Prozessor (bis zu 4,1 GHz), Octa-Core
  • Display: 35,6 cm (14 Zoll) IPS Full-HD Display mit LED-Hintergrundbeleuchtung, 400 nits, 800:1 Kontrast
  • RAM: 32 GB DDR4-3200 SO-DIMM fest verlötet
  • Festplatte: 1 TB SSD M.2 2280 PCIe NVMe Opal2
  • Webcam: IR Kamera und HD720p Kamera mit ThinkShutter
  • WLAN und Bluetooth: Wireless LAN 802.11 ax und Bluetooth 5.1
  • Weitere Anschlüsse:
    • 2x USB 3.2 Gen 1 (1x Always On)
    • 2x USB 3.2 Type-C Gen 2 (mit Power Delivery und DisplayPort 1.4)
    • 1x HDMI 2.0
    • Ethernet extension connector (proprietärer Anschluss)
    • Mikrofoneingang / Kopfhörerausgang (komb.)
    • Dockinganschluss
    • MicroSD-Kartenleser; Lesegerät für Smartcards

Das Feedback von ‚Art‘ bezieht sich zwar auf das P14s, doch teilt sich dieses Modell etliche Komponenten mit dem T14s, so dass ich in der Hoffnung gekauft habe, einige Eigenschaften übertragen zu können. Dieses Feedback, der Trackpoint, dieser Testbericht und der Preis waren die Haupteinflussfaktoren bei diesem Kauf.

Es folgt ein erster persönlicher Erfahrungsbericht zum neuen Gerät.

Ach du Schreck, ist das dünn.

Mein erstes ThinkPad war ein R61. Ich habe dessen Größe, Gewicht und Robustheit geschätzt. Auch das T410 und das X201 machen einen stabilen und robusten Eindruck. Und nun ist da dieses T14s.

  • hoehenvergleich-t14s-t410
    Vergleich zwischen T41s (links) und T410 (rechts)
  • hoehenvergleich-x201-t14s
    Höhenvergleich von X201 (links) zu T14s (rechts)

Mein erster Gedanke war: „Damit erschlägst du niemanden mehr.“ (Nicht, dass ich das jemals getan hätte.)

Für ein Gerät dieser Größe ist die Stabilität in Ordnung. Erwartungsgemäß ist es nicht so verwindungssteif, wie die älteren Modelle. Dafür ist es bedeutend leichter. Ich glaube, auf dieses Gerät muss ich deutlich besser acht geben, damit es lange hält.

Die äußeren Maße finde ich hingegen optimal. Es passt genau zwischen das T410 und das X201, was mir gut gefällt.

vergleich-t410-x201-t14s
T410 (links unten), X201 (oben) und T14s (rechts unten) auf einen Blick

Um es kurz zu machen, ich habe mich mit dem T14s angefreundet.

Die einzige Sache, die sich mir bisher noch nicht erschlossen hat, ist der Sinn hinter dem proprietären LAN-Anschluss.

proprietaerer-lan-anschluss
Der proprietäre LAN-Anschluss befindet sich zwischen dem USB-C-Ladeanschluss (links) und dem USB-A-Anschluss.

Um einen LAN-Anschluss mit bis zu 1 Gbps nach außen zu führen, hätte in einen Augen ein normaler USB-C-Port gereicht. Diesen hätte man auch noch anderweitig verwenden können. Aber vielleicht steckt ja noch mehr hinter diesem Port, das mir noch nicht bewusst ist.

Und wie läuft es mit Linux?

Debian Buster wollte nicht starten. Ich habe mehrere Debian Testing Images ausprobiert, doch hat mich die Partitionierung im Installer so genervt, dass ich schlussendlich (erstmal) zu Fedora 34 Workstation gegriffen habe. Hiermit funktionierte fast alles Out-of-the-Box.

Lediglich für den Standby-Modus war noch ein Firmware-Update auf Version 1.30 notwendig. Dank LVFS war dies im Handumdrehen aus Linux heraus erledigt.

Nur ein Bug nervt mich sehr. In meinem Gerät ist ein Touchpad und Trackpoint der Firma Elantech verbaut. Bei Nutzung des Trackpoints springt dieser sporadisch an die Seiten bzw. in die Ecken des Displays. Da dieser Bug bei Lenovo bekannt ist und reproduziert werden konnte, habe ich die Hoffnung, dass hier noch Abhilfe geschaffen wird.

Mit dem letzten Debian Testing weekly-build funktionieren Stand-By (ursächlich ist hier wohl eher die aktualisierte Firmware). Nur der Trackpoint-Bug existiert wenig überraschend auch hier.

Fazit

Alles in allem ist es ein schönes Gerät. Die Linux-Unterstützung ist gut und ich habe es behalten.

Das Problem mit dem Trackpoint ist wirklich nervig, doch verschmerzbar. Zudem hoffe ich hier auf Abhilfe.

An dieser Stelle noch einmal Danke für eure Kommentare, die mir bei der Entscheidung geholfen haben.

Weiterführende Links

Ansible: Wiederherstellung meines Blogs auf Buster und Bullseye in 2021

17. Mai 2021 um 07:00

Dies ist ein Update zu den Beiträgen:

  1. Konzept zum Deployment meines Blogs mit Ansible und
  2. Erfahrungsbericht zum Deployment meines Blogs mit Ansible.

Umgebung

Aktuell nutze ich als Ansible Control Node (ACN) ein Debian Buster mit Ansible 2.7.7. Die Backups liegen wie gehabt auf einem Speicher im lokalen Heimnetzwerk.

Als Zielsysteme für die Wiederherstellung dienen ein Debian 10 (Buster) und Debian Testing (das kommende Bullseye). Bei beiden Zielsystemen handelt es sich um minimale Installation in zwei VMs auf einem KVM-Hypervisor.

Ablauf

Zuerst habe ich meinen Blog aus dem Backup auf der Debian 10 VM wiederhergestellt. Dabei gab es tatsächlich ein Problem. Das VHOST-Template für den Webserver entsprach nicht mehr der Version, die auf dem Produktivsystem zum Einsatz kommt. Ich hatte schlicht vergessen, die Änderung nachzupflegen. Der Fehler wurde schnell identifiziert und behoben. Anschließend verlief der Wiederherstellungsprozess reibungslos.

Beim zweiten Versuch erfolgte die Wiederherstellung auf einer VM mit Debian Testing (Bullseye). Dieser Test ist für mich wichtig, um zu sehen, ob ich meinen Blog auch auf der kommenden stabilen Debian-Version ausrollen kann. Hier waren etwas mehr Anpassungen an der Rolle „deploy-my-blog“ notwendig, um dieses Blog erfolgreich wiederherstellen zu können. So haben sich einige Paketnamen geändert:

Alter NameNeuer Name
python-aptpython3-apt
python-mysqldbpython3-mysqldb
Gegenüberstellung der alten und neuen Paketnamen

Doch auch an der VM selbst war ein manueller Eingriff notwendig, bevor sich mein ACN überhaupt mit dem Node verbinden konnte. Ansible konnte auf dem Node keinen Python-Interpreter finden. Ich schiebe die Schuld der Version 2.7.7 in die Schuhe. Nachdem ich einen Symlink von /usr/bin/python auf /usr/bin/python3 erstellt hatte, klappte der Zugriff.

Der letzte Stolperstein war php-fpm. Kommt unter Buster Version 7.3 zum Einsatz so ist dies unter Bullseye 7.4. Da die Versionsnummer in meiner Ansible-Rolle hart verdrahtet ist, war auch hier eine Anpassung notwendig. Anschließend gelang auch hier die Wiederherstellung.

Fazit

Grundsätzlich klappte die Wiederherstellung wie gewohnt. Den Fehler mit der VHOST-Datei könnte ich zukünftig vermeiden, indem ich diese einfach mit aus dem Backup wiederherstelle, statt ein Template zu nutzen.

Das bei der Wiederherstellung auf einer neueren Betriebssystemversion Anpassungen erforderlich sind, hatte ich erwartet. Diese halten sich meiner Meinung nach in Grenzen und sind akzeptabel.

Die längste Zeit beanspruchte das Kopieren der Backups auf die Zielsysteme. Die eigentliche Wiederherstellung war mit den Stolpersteinen in 10-15 Minuten. Mit fehlerbereinigter Rolle sogar nur noch ca. 5 Minuten. Eine manuelle Wiedereinrichtung hat mich früher eher zwischen 30-60 Minuten gekostet. Von daher bin ich sehr zufrieden.

Postfix: From-Adresse beim Relay über Smarthost erzwingen

10. Mai 2021 um 06:31

In diesem Beitrag dokumentiere ich eine Lösung für die Meldung: „554 5.7.1 REJECT policy violation – too many different Display Names – code #242 (in reply to end of DATA command)“

Umgebung

Ich betreibe einen Virtual Private Server (VPS) im Internet, sowie einige Raspberry Pis und weitere Geräte, die man heute wohl am ehesten dem Internet der Dinge zuordnen würde.

Diese Systeme sollen mir Systemmeldungen per E-Mail senden. Dafür habe ich mir ein günstiges E-Mail-Postfach bei Mailbox.org gebucht und auf den betroffenen Systemen Postfix installiert und zum Versand über einen Smarthost konfiguriert. Die Konfiguration erfolgte über die Ansible-Rolle relaymail von Yannik. Diese dient jedoch nur als Werkzeug. Die Konfiguration kann selbstverständlich auch manuell durchgeführt werden.

Problembeschreibung

Bei einer Systemüberprüfung fielen mir einige Fehlermeldungen der folgenden Art ins Auge (einige Werte durch <Platzhalter> ersetzt):

„<Hostname und IP-Adresse> said: 554 5.7.1 id=<ID> – Rejected by next-hop MTA on relaying, from MTA(smtp:[<IP-Adresse>]:10025): 554 5.7.1 REJECT policy violation – too many different Display Names – code #242 (in reply to end of DATA command)“

Weitere Informationen zu dieser Meldung und deren Ursache finden sich im Mailbox.org-Benutzerforum in: „mailbox.org als smtp Relay nutzen“

Während meine Raspberry Pis mit Raspbian GNU/Linux 10 (buster) und Postfix 3.4.14-0+deb10u1 sich wie erwartet verhalten und lediglich meine E-Mail-Adresse in das Header-Feld „From“ eintragen, fügt mein VPS mit Debian GNU/Linux 10 (buster) und Postfix 3.4.14-0+deb10u1 den Namen des jeweiligen Benutzers bzw. Dienstes mit ein, welcher die E-Mail versenden möchte. Diese Informationen nimmt der VPS aus dem Kommentarfeld der /etc/passwd. Während die Kommentarfelder auf meinen Raspberry Pis leer sind, sind diese auf dem VPS entsprechend gefüllt.

Im E-Mail-Header stellt sich das dann wie folgt dar.

Header-Auszug bei E-Mail von Raspberry Pi

Date: Mon, 10 May 2021 04:56:32 +0200 (CEST)
From: no-reply@example.com

Header-Auszüge bei E-Mails vom VPS

From: no-reply@example.com (Cron Daemon)
To: root
Date: Mon, 10 May 2021 04:44:12 +0200 (CEST)
From: Jörg Kastning <no-reply@example.com>
Date: Mon, 10 May 2021 04:44:36 +0200 (CEST)
From: root <no-reply@example.com>

Lösung

Um das Problem aufzulösen, lasse ich nun Postfix das Header-Feld „From“ umschreiben und explizit auf den Wert no-reply@example.com setzen. In der /etc/postfix/main.cf müssen dazu folgende Zeilen vorhanden sein:

sender_canonical_classes = envelope_sender, header_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps
smtp_header_checks = regexp:/etc/postfix/header_check

Inhalt der /etc/postfix/sender_canonical_maps:

/.+/    no-reply@example.com

Dies sorgt dafür, dass Postfix das Feld „Envelope-From“ explizit auf no-reply@example.com setzt.

Inhalt der /etc/postfix/header_check:

/From:.*/ REPLACE From: no-reply@example.com

Hiermit wird der Wert des Header-Felds „From“ explizit auf no-reply@example.com gesetzt. Die Lösung habe ich hier gefunden. Damit läuft der Versand meiner Systembenachrichtigungen wieder.

Weitere Artikel zu Postfix und Smarthosts in diesem Blog

Linux-Distributionen zwischen Stabilität und Aktualität

03. Mai 2021 um 07:00

Die Linux-Gemeinschaft lässt sich grob in drei Lager unterteilen. Dabei nimmt ein Lager den Extremwert „stabil wie ein Fels“ mit z.B. Debian oldstable ein, während der andere Extremwert „bleeding edge“ durch Anhänger z. B. von Arch Linux besetzt wird. Das dritte Lager besetzt die Mitte, in der sich unzählige weitere Distributionen tummeln, die mehr zu dem einen oder dem anderen Extremwert hin tendieren.

Warum das so ist und welche Distribution einen, wie ich finde, ganz interessanten Mittelweg eingeschlagen hat, möchte ich in diesem Artikel beleuchten. Bierernst bin ich dabei allerdings nicht. Die ein oder andere Ausführung ist durchaus mit einem Augenzwinkern zu verstehen. ;-)

Stabil wie ein Fels

So soll eine Linux-Distribution aus Sicht vieler Systemadministratoren sein. Gut getestet, alle Komponenten perfekt aufeinander abgestimmt und über ihren Lebenszyklus nur wenigen — am besten gar keinen — Änderungen unterworfen. Einzig Sicherheitsaktualisierungen dürfen und sollen zeitnah geliefert werden.

Distributionen, die sich diesem Paradigma unterwerfen, versprechen geringe Wartungsaufwände und sind des Sysadmins Freund. In meinen Augen dürfen Debian, RHEL, SLES, etc. dieser Kategorie zugeordnet werden.

Doch bergen diese Distributionen paradigmenbedingt auch einige Nachteile. Da Kernel und Bibliotheken meist schon etwas älter sind — manche sagen dazu steinalt, andere gut abgehangen — wird neue Hardware evtl. nicht in vollem Umfang unterstützt. Oder die mitgelieferten Bibliotheken und Laufzeitumgebungen sind schlicht zu alt, um mit aktuellen Versionen verfügbarer Software noch kompatibel zu sein.

Um den Nachteilen zu begegnen, bleibt Sysadmins häufig nichts anderes übrig, als das wohlige Heim der Distribution zu verlassen und Laufzeitumgebungen aus Upstream- oder Drittanbieter-Repos zu installieren, Software selbst zu übersetzen oder sich Container in die heilige Halle zu stellen. Die Distributionen versuchen dem zu begegnen, in dem sie unter Umständen zu Minor-Releases neuere Software-Versionen als sogenannte Rebases oder Backports nachliefern. Das dies passiert ist jedoch keineswegs garantiert und stellt im Zweifel ein Risiko für die Stabilität dar.

Wenn die Distribution dann aber doch eine neue Softwareversion ausliefert, hat der Sysadmin meist keine Wahl. Entweder er bleibt auf der alten Version und erhält voraussichtlich keinerlei Sicherheitsupdates mehr für diese oder installiert die aktuelle Version und lernt die Neuerungen lieben bzw. damit zu leben.

Bleeding Edge

Mit diesem Beinamen werden häufig Distributionen bezeichnet, welche dem Rolling-Release-Modell folgen und Software mitliefern, die sehr nah am aktuellen Stand der Upstream-Entwicklung ist (the latest and greatest). In dieser Ecke findet man z. B. Distributionen wie Arch Linux, Manjaro, Fedora Rawhide, etc. wobei diese Liste keinen Anspruch auf Vollständigkeit erhebt.

Der Betrieb dieser Distributionen ist geprägt von häufigen Updates. Die stetige Weiterentwicklung birgt das Risiko, dass auch mal etwas kaputt geht und plötzlich nicht mehr funktioniert. Doch versprechen die Distributionen meist, dass gerade durch den schnellen Entwicklungszyklus gefundene Fehler auch schnell behoben werden. Wohingegen die Nutzer stabiler Version häufig Monate, wenn nicht Jahre oder gar vergebens auf einen Bugfix warten müssen.

Blöd wird es, wenn man Software betreiben muss, die nur für eine bestimmte Version einer Laufzeitumgebung, oder bestimmter Bibliotheken freigegeben ist und unterstützt wird. Wer solche Software betreibt, sollte sich jedoch von vornherein fragen, ob er bei rollenden Releases richtig aufgehoben ist.

Dann sind da auch noch jene unter uns, die für den Betrieb auf gewisse Zertifizierungen ihrer Betriebssysteme angewiesen sind. Hier sind die Zertifizierungsverfahren häufig länger, als die Lebensspanne eines Bleeding-Edge-Release.

Das Mittelfeld

Dieses Feld ist weitgespannt. Hier tummeln sich Distributionen wie Fedora, Ubuntu sowie viele weitere. Ihnen allen unterstelle ich, dass sie den besten Kompromiss suchen, um so stabil wie möglich und so aktuell wie nötig zu sein.

So habe auch ich in der Vergangenheit auf Ubuntu LTS gesetzt, da ich es für den besten Kompromiss hielt. Leider waren unsere Entwickler mit den mitgelieferten Software-Versionen nicht lange zufrieden und ließen sich nicht bis zum nächsten Release hinhalten. Also wurden auch hier wieder {Dritanbieter,Upstream}-Repos eingebunden und die Software von dort installiert. Eine Erfahrung die ich bisher unter jeder Distribution machen durfte.

Genauso gut kenne ich den umgekehrten Fall, wo Paket XY auf gar keinen Fall aktualisiert werden darf, da sonst ein Dienst unrettbar kaputt geht. Lasst euch gesagt sein, man hat es schon nicht leicht in der Systemadministration. ;-)

Appstreams und Module

Mit RHEL 8 hat Red Hat eine interessante Neuerung eingeführt, die sog. Module im Appstream-Repository. Nun ein Listing sagt vermutlich mehr, als viele Sätze:

$ sudo dnf module list nginx php postgresql
Updating Subscription Management repositories.
Last metadata expiration check: 0:27:21 ago on Mi 21 Apr 2021 05:41:58 CEST.
Extra Packages for Enterprise Linux Modular 8 - x86_64
Name            Stream        Profiles                        Summary                                 
nginx           mainline      common                          nginx webserver                         

Red Hat Enterprise Linux 8 for x86_64 - AppStream (RPMs)
Name            Stream        Profiles                        Summary                                 
nginx           1.14 [d]      common [d]                      nginx webserver                         
nginx           1.16          common [d]                      nginx webserver                         
nginx           1.18          common [d]                      nginx webserver                         
php             7.2 [d]       common [d], devel, minimal      PHP scripting language                  
php             7.3           common [d], devel, minimal      PHP scripting language                  
php             7.4           common [d], devel, minimal      PHP scripting language                  
postgresql      9.6           client, server [d]              PostgreSQL server and client module     
postgresql      10 [d]        client, server [d]              PostgreSQL server and client module     
postgresql      12            client, server [d]              PostgreSQL server and client module     

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled

Wie ihr sehen könnt, hat man damit die Auswahl aus mehreren Versionen ein und der selben Anwendung. Das kannte ich so bisher noch nicht, ohne zusätzliche Repos einbinden zu müssen, oder mich gar mit den berüchtigten Red Hat Software Collections beschäftigen zu müssen.

Als Sysadmin habe ich damit etwas Flexibilität dazugewonnen. Ich kann z. B. eine Altlast mit NGINX 1.14, PHP 7.2 und PostgreSQL 9.6 auf einem Host und eine aktuelle Anwendung mit NGINX 1.18, PHP 7.4 und PostgreSQL 12 auf einem anderen Host betreiben, dabei aber das gleiche stabile Release RHEL 8 nutzen.

Allerdings kann man nicht zwei verschiedene Versionen von z. B. PHP oder PostgreSQL parallel auf dem gleichen Host betreiben. Wer dies wünscht, kann die entsprechenden Anwendungen lokal in Podman-Containern ausführen. Auch hier stehen Images für die verschiedenen Versionen bereit.

Red Hat verspricht, neue Versionen von Anwendungen, Sprachen und Werkzeugen auf diesem Weg verfügbar zu machen. So sind in der Beta des kommenden RHEL 8.4 zum Beispiel PostgreSQL 13, Python 3.9 und Podman 3.0.1 enthalten. Zu beachten ist jedoch, dass die jeweiligen Streams ihre eigenen Life-Cycles besitzen, die es im Auge zu behalten gilt. Hier hilft ein Blick in die offizielle Dokumentation weiter:

Fazit

Ob diese Neuerung und die damit einhergehenden Vorteile in der Praxis von Relevanz sein werden, kann ich heute noch nicht sagen. Dafür fehlt mir noch etwas Erfahrung mit diesem neuen Konzept.

Ich persönlich glaube, dass sich Application Streams und das Konzept zur Verwendung von Containern nicht gegenseitig ausschließen, sondern sinnvoll ergänzen können. In meinen Augen gelingt es Red Hat mit Appstreams, seine stabile Distribution etwas in Richtung Aktualität zu schieben, ohne dabei Stabilität aufgeben zu müssen.

Aktualisierung eines Kanboard-Pods

26. April 2021 um 07:00

Dies ist der letzte Artikel in meiner kleinen Reihe, über meinen Ausflug ins Container-Land, zur Bereitstellung der Anwendung Kanboard.

Wie meine Reise ins Container-Land begonnen hat, kann in „Kanboard im Container…“ nachgelesen werden. Wie man einen Reverse-Proxy vor einem Pod betreibt sowie mit dem Thema Backup und Restore habe ich mich inzwischen ebenso beschäftigt. Letzteres habe ich zum Glück implementiert und getestet, bevor ich mit der Dokumentation Datenverlust erlitten habe. Damit die Anwendung nach einem Neustart automatisch startet und für ein bisschen Komfort, habe ich Systemd-Service-Units generiert. In diesem Teil geht es nun um die Aktualisierung dieser Umgebung.

Umgebung

Aktuell läuft Kanboard 1.2.18 auf einer RHEL 8 VM. Zur Ausführung sind folgende Werkzeuge und Container-Images beteiligt.

$ podman --version
podman version 2.2.1
$ podman images
REPOSITORY                              TAG      IMAGE ID      CREATED        SIZE
registry.redhat.io/rhel8/postgresql-96  latest   4ce7daa6dc1d  7 weeks ago    451 MB
docker.io/kanboard/kanboard             v1.2.18  e7ee6403944b  3 months ago   58.6 MB
k8s.gcr.io/pause                        3.2      80d28bedfe5d  14 months ago  688 kB

Um mir die Erstellung eines Pods und das Einhängen von Podman-Volumes zu erleichtern, nutze ich folgendes kleines Skript:

#!/bin/bash
podman run -d --pod new:kanboardpod --name kanboard --privileged -p 127.0.0.1:8080:80 -v kanboard_datadir:/var/www/app/data:Z -v kanboard_pluginsdir:/var/www/app/plugins:Z kanboard/kanboard:v1.2.18

podman run -d --pod kanboardpod --name pgsql_db -e POSTGRESQL_USER=<USERNAME> -e POSTGRESQL_PASSWORD=<Verrate ich nicht> -e POSTGRESQL_DATABASE=kanboard -v pgsql_dbdir:/var/lib/pgsql/data:Z rhel8/postgresql-96:1-107

Mein Pod und die drei dazugehörigen Container werden während der folgenden Schritte noch normal ausgeführt.

Die Container selbst sind dabei zustandslos. Die persistent zu speichernden Daten werden in Podman-Volumes im lokalen Dateisystem der VM abgelegt.

Vorgehensweise

Ich verzichte in diesem Fall bewusst auf podman-auto-update(1), da ich mir erstmal einen Überblick verschaffen möchte, was denn generell zu tun ist und wie die einzelnen Schritte aussehen können. Die grundsätzliche Reihenfolge für ein Update sieht dabei wie folgt aus:

  1. Aktuelle Container-Images aus einer Registry holen (podman-pull(1))
  2. Laufende Pod-Instanz stoppen und entfernen (podman-pod(1))
  3. Neue Pod-Instanz mit angepasstem Wrapper-Skript erstellen
  4. Systemd-Service-Units erneut generieren (podman-generate-systemd(1))
  5. Pod-Instanz stoppen
  6. Generierte Systemd-Service-Unit starten

An dieser Stelle möchte ich vorweg nehmen, dass es genau so einfach war, wie es sich anhört. Die neuen Container-Images habe ich mit folgenden Kommandos heruntergeladen.

$ podman pull docker.io/kanboard/kanboard:v1.2.19
Trying to pull docker.io/kanboard/kanboard:v1.2.19...
Getting image source signatures
Copying blob 0c2b98bb5f7e done
Copying blob ca3cd42a7c95 done
Copying blob e994ab432c32 done
Copying blob 7b30337f40d2 done
Copying blob f58d66ecc40b done
Copying config 2cb48121b7 done
Writing manifest to image destination
Storing signatures
2cb48121b7437ba15cd984472754b300395026c3e09e7c659b4f9b62e5b5b4dd

$ podman pull registry.redhat.io/rhel8/postgresql-96:1-127
Trying to pull registry.redhat.io/rhel8/postgresql-96:1-127...
Getting image source signatures
Copying blob 64607cc74f9c done
Copying blob 320ae7fa06a7 done
Copying blob 13897c84ca57 done
Copying blob b3b2bbe848df done
Copying config 9c6ab01c14 done
Writing manifest to image destination
Storing signatures
9c6ab01c14748f7ff79483759122cb28e0f2c8b0310e5c8d9b5af8383e91f163

$ podman images
REPOSITORY                              TAG      IMAGE ID      CREATED        SIZE
docker.io/kanboard/kanboard             v1.2.19  2cb48121b743  4 days ago     61.3 MB
registry.redhat.io/rhel8/postgresql-96  1-127    9c6ab01c1474  2 weeks ago    449 MB
registry.redhat.io/rhel8/postgresql-96  latest   4ce7daa6dc1d  7 weeks ago    451 MB
docker.io/kanboard/kanboard             v1.2.18  e7ee6403944b  3 months ago   58.6 MB
k8s.gcr.io/pause                        3.2      80d28bedfe5d  14 months ago  688 kB

Mit den folgenden Befehlen werden Informationen zum laufenden Pod angezeigt, der Service wird gestoppt und der Pod inkl. seiner Container entfernt.

$ podman pod ls
POD ID        NAME         STATUS   CREATED      INFRA ID      # OF CONTAINERS
2f3aa7d07e6e  kanboardpod  Running  4 weeks ago  34e8479a2847  3

$ systemctl --user stop pod-kanboardpod.service

$ podman pod ls
POD ID        NAME         STATUS  CREATED      INFRA ID      # OF CONTAINERS
2f3aa7d07e6e  kanboardpod  Exited  4 weeks ago  34e8479a2847  3

$ podman pod rm kanboardpod
2f3aa7d07e6eb7d4c3a0c9927dac222be52b8992f95929c12af8ce4afafd4eb1

In mein Wrapper-Skript (siehe Abschnitt Umgebung) trage ich die neuen Versionsnummern bei den entsprechenden Aufrufen ein:

#!/bin/bash
podman run -d --pod new:kanboardpod --name kanboard --privileged -p 127.0.0.1:8080:80 -v kanboard_datadir:/var/www/app/data:Z -v kanboard_pluginsdir:/var/www/app/plugins:Z kanboard/kanboard:v1.2.19

podman run -d --pod kanboardpod --name pgsql_db -e POSTGRESQL_USER=<USERNAME> -e POSTGRESQL_PASSWORD=<Verrate ich nicht> -e POSTGRESQL_DATABASE=kanboard -v pgsql_dbdir:/var/lib/pgsql/data:Z rhel8/postgresql-96:1-127

Nachdem das obige Wrapper-Skript ausgeführt wurde, prüfe ich, ob die neue Pod-Instanz läuft, erstelle die Service-Units und aktiviere diese:

$ podman pod ls
POD ID        NAME         STATUS   CREATED             INFRA ID      # OF CONTAINERS
85273ee9bb82  kanboardpod  Running  About a minute ago  82f45a722dff  3

$ podman container ls
CONTAINER ID  IMAGE                                         COMMAND         CREATED             STATUS                 PORTS                   NAMES
6becc68a9c20  registry.redhat.io/rhel8/postgresql-96:1-127  run-postgresql  About a minute ago  Up About a minute ago  127.0.0.1:8080->80/tcp  pgsql_db
82f45a722dff  k8s.gcr.io/pause:3.2                                          About a minute ago  Up About a minute ago  127.0.0.1:8080->80/tcp  85273ee9bb82-infra
e72ca46110be  docker.io/kanboard/kanboard:v1.2.19                           About a minute ago  Up About a minute ago  127.0.0.1:8080->80/tcp  kanboard

$ podman generate systemd --files --name kanboardpod
/home/bob/pod-kanboardpod.service
/home/bob/container-kanboard.service
/home/bob/container-pgsql_db.service

$ mv *.service .config/systemd/user/

$ podman pod stop kanboardpod
85273ee9bb82e49e236ae37d9320fd95af1eb186d7d965d72b9e2a270ca5cedf

$ systemctl --user daemon-reload
$ systemctl --user start pod-kanboardpod.service

Fazit

Das war einfacher als gedacht. Oder anders formuliert, es hat tatsächlich so funktioniert, wie ich es erwartet habe.

Mein kleines Wochenend-Projekt skaliert sicher nicht gut und ist als Beispiel für Produktionsumgebungen vermutlich weniger geeignet. Doch um Software als rootless-Container auszuführen und in kleinem Umfang zu testen, scheint dieser Weg durchaus geeignet zu sein.

Vielleicht schiebe ich in Zukunft noch einen Artikel unter Verwendung von podman-auto-update(1) nach.

Neue Hardware 2021

03. April 2021 um 13:50

Vergangenes Jahr habe ich meinen Tower-PC generalüberholt und mit frischer Hardware bestückt. Dieses Jahr möchte ich meine beiden ThinkPads (T410 und X201) durch aktuelle Hardware ablösen.

Das neue Gerät soll folgende Anforderungen erfüllen:

  • 100% Linux-Kompatibilität – Ich möchte auf dem Gerät Debian, RHEL, Fedora, Ubuntu LTS oder evtl. auch mal ganz was neues betreiben. Da möchte ich natürlich nicht für Hardware bezahlen, die ich anschließend nicht nutzen kann.
  • Lange Akkulaufzeit >7 Std. – Damit ich mit dem Gerät auf dem Sofa, im Garten, im Büro oder auch mal im Auto arbeiten kann, ohne nach wenigen Stunden an eine Steckdose gefesselt zu sein.
  • Gute Tastatur – Dies ist ein sehr subjektiver Punkt. Ich liebe die ThinkPad-Tastaturen. Die alten mehr, als die neuen. Ich hasse hingegen die Tastaturen aus der Dell Latitude Reihe.
  • Leise Lüfter – Wenn mehrere Prozesse schwere Arbeit verrichten, muss die Hardware selbstverständlich gekühlt werden. Wenn mich das Gerät allerdings bei der Internetrecherche und dem Schreiben von Texten bereits permanent anbläst und die Lüfter heulen lässt, nervt mich dies extrem.
  • Virtualisierung – Ich arbeite viel mit virtuellen Maschinen und zukünftig auch vermehrt mit Containern. Das neue Gerät soll nicht meinen Hypervisor ersetzen, aber für Testzwecke schon mal 2-3 VMs parallel starten können. Daher sind 8 Threads und mindestens 32 GB RAM Pflicht.
  • 1 TB Festplattenspeicher – Denn darunter wird der Platz nur wieder erschreckend schnell knapp.

Bisher habe ich mich in den Online-Shops von TUXEDO Computers und Lenovo umgesehen und die beiden folgenden Geräte ins Auge gefasst

TUXEDO Pulse 14

Ich hab das TUXEDO Pulse 14 Gen 1 wie folgt konfiguriert:

  • Display: Full-HD (1920×1080) IPS matt | 100% sRGB
  • RAM: 64 GB (2x 32 GB) 3200 MHz CL22 Samsung
  • CPU: AMD Ryzen 7 4800H (8x 2,9-4,2 GHz, 8 Cores, 16 Threads, 12 MB Cache, 45 W TDP)
  • Festplatte: 1 TB Samsung 980 Pro (NVMe PCIe 4.0)
  • WLAN & Bluetooth: Intel Wifi AX200 & Bluetooth 5.1
  • LAN: 1x Gigabit LAN/Netzwerk RJ45
  • Weitere Anschlüsse
    • 1x USB 3.2 Gen1 Typ-C (DisplayPort: nein; Power Delivery/DC-IN: ja, mind. 20V/4.5A)
    • 2x USB 3.2 Gen1 Typ-A
    • 1x USB 2.0 Typ-A
    • 1x HDMI 2.0 inkl. HDCP (4k UHD@60Hz / 2k FHD@120Hz)
    • 1x 2-in-1 Kopfhörer/Headset (Kopfhörer & Mikrofon)
    • 1x HD Webcam / Kamera inkl. Mikrofon
  • Preis: ca. 1489 EUR

Das ist in meinen Augen bereits eine gute Ausstattung zu einem fairen Preis. Nur bin ich skeptisch, ob mir die Tastatur gefallen wird und ich mich daran gewöhnen kann, keinen TrackPoint mehr zu haben.

Ist unter euch evtl. ein ehemaliger ThinkPad-User, welcher nun ein TUXEDO sein Eigen nennt und etwas zur Tastatur und dem Touchpad sagen mag? Und auch wenn ihr kein ThinkPad-User seid, freue ich mich über euer Feedback.

ThinkPad P14s Gen 1

Das ThinkPad P14s Gen 1 käme mit folgender Konfiguration in Frage:

  • Display: 35,6 cm (14,0″) FHD (1.920 x 1.080), IPS, entspiegelt, 300 cd/m², Multitouch, schmale Ränder
  • RAM: 32 GB DDR4 3.200 MHz (16 GB verlötet + 1 x 16 GB SODIMM gesteckt)
  • CPU: AMD Ryzen 7 PRO 4750U Prozessor (8 Kerne, 16 Threads, 8 MB Cache, bis zu 4,10 GHz)
  • Festplatte: 1 TB SSD, M.2 2280, PCIe 3.0 x4/PCIe 4.0 x4, NVMe, OPAL 2.0-fähig, TLC
  • WLAN & Bluetooth: Intel Wi-Fi 6 AX200 (2×2) WLAN, Bluetooth 5
  • LAN: 1x Gigabit LAN/Netzwerk RJ45
  • Weitere Anschlüsse
    • 2 x USB-A 3.2* (Gen 1) (1 Always-on)
    • 2 x USB-C 3.2 (Gen 2)
    • 1x HDMI 2.0
    • 1x 2-in-1 Kopfhörer/Headset (Kopfhörer & Mikrofon)
    • MicroSD-Kartenleser (UHS-II)
    • 1x Infrarot- und 720p-HD-Kamera mit Mikrofon
  • Sonstiges: Das System ist Red Hat Linux zertifiziert und das Gehäuse ist spritzwassergeschützt
  • Preis: ca. 1459 EUR

Die Akkulaufzeit beträgt nach MobileMark 2014 bis zu 13,25 Std. und nach MobileMark 2018 bis zu 10,5 Std. Das sagt mir persönlich erstmal gar nichts, da ich beide Benchmarks nicht kenne. Davon ab mag sich die reale Laufzeit im Wirkbetrieb, gerade unter Linux, völlig anders darstellen. Wie sind eure Erfahrungen mit der Akkulaufzeit von aktuellen ThinkPads unter Linux? Weicht diese stark von den Angaben ab?

Wer die Wahl hat, hat die Qual

Da sitze ich nun vor meinem altgedienten T410 und kann mich nicht entscheiden. Die Preise beider Geräte liegen sehr nahe beieinander. Bei TUXEDO bekomme ich die doppelte Menge RAM fürs Geld. Bei Lenovo bekomme ich eine gute Tastatur und meinen geliebten TrackPoint.

Bevor ich mich entscheide, werde ich das Web wohl noch nach ein paar Testberichten umgraben. Falls ihr welche kennt, freue ich mich über eure Hinweise.

Für welches Gerät würdet ihr euch denn entscheiden? Und warum?

Wenn ihr Geräte von anderen Herstellern kennt, die obige Anforderungen erfüllen und eine vergleichbare Ausstattung bieten, freue ich mich ebenfalls, wenn ihr Hinweise darauf in den Kommentaren verlinkt.

Euch allen noch ein frohes Osterfest.

Podman kann auch Systemd-Service-Units generieren

22. Februar 2021 um 08:00

Mit „Kanboard im Container…“ hat mein Ausflug ins Containerland begonnen. Mittlerweile läuft mein Pod bereits eine Weile und ich nutze die Anwendung regelmäßig. Jedoch musste ich nach jedem Neustart des Hosts den Pod kanboardpod manuell starten. Ich hatte mir daher vorgenommen, hierfür eine Systemd-Service-Unit zu erstellen, welche diesen Task automatisiert. Doch habe ich mit Freude festgestellt, dass podman-generate-systemd(1) mir diese Arbeit abnehmen kann.

Also starte ich einen ersten Versuch und erzeuge entsprechende Service-Unit-Dateien in meinem HOME-Verzeichnis. Die Option „--name“ sorgt dafür, dass in den Service-Unit-Dateien die Namen des Pods bzw. der Container verwendet werden, anstatt der UUIDs. Die Option „--files“ sorgt dafür, dass die Ausgabe in Dateien und nicht auf die Standard-Ausgabe geschrieben wird.

$ podman generate systemd --name --files kanboardpod
/home/alice/pod-kanboardpod.service
/home/alice/container-kanboard.service
/home/alice/container-pgsql_db.service

$ cat pod-kanboardpod.service
# pod-kanboardpod.service
# autogenerated by Podman 2.0.5
# Mon Jan 25 13:19:51 CET 2021

[Unit]
Description=Podman pod-kanboardpod.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target
Requires=container-kanboard.service container-pgsql_db.service
Before=container-kanboard.service container-pgsql_db.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
ExecStart=/usr/bin/podman start 62cdd29105a4-infra
ExecStop=/usr/bin/podman stop -t 10 62cdd29105a4-infra
ExecStopPost=/usr/bin/podman stop -t 10 62cdd29105a4-infra
PIDFile=/run/user/1000/containers/overlay-containers/b3c9bd9754cdc999108d0f4aad7d808c007cc34eee34faefd41ee39c3e1ca18b/userdata/conmon.pid       
KillMode=none
Type=forking

[Install]
WantedBy=multi-user.target default.target

$ cat container-kanboard.service 
# container-kanboard.service
# autogenerated by Podman 2.0.5
# Mon Jan 25 13:19:51 CET 2021

[Unit]
Description=Podman container-kanboard.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target
BindsTo=pod-kanboardpod.service
After=pod-kanboardpod.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
ExecStart=/usr/bin/podman start kanboard
ExecStop=/usr/bin/podman stop -t 10 kanboard
ExecStopPost=/usr/bin/podman stop -t 10 kanboard
PIDFile=/run/user/1000/containers/overlay-containers/99d386a42b186efb3347d909cea265b990469dc33e1889a3006425a71956699b/userdata/conmon.pid
KillMode=none
Type=forking

[Install]
WantedBy=multi-user.target default.target

$ cat container-pgsql_db.service 
# container-pgsql_db.service
# autogenerated by Podman 2.0.5
# Mon Jan 25 13:19:51 CET 2021

[Unit]
Description=Podman container-pgsql_db.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target
BindsTo=pod-kanboardpod.service
After=pod-kanboardpod.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
ExecStart=/usr/bin/podman start pgsql_db
ExecStop=/usr/bin/podman stop -t 10 pgsql_db
ExecStopPost=/usr/bin/podman stop -t 10 pgsql_db
PIDFile=/run/user/1000/containers/overlay-containers/fe757283f0662220fee23a563053ea7f30dbdf6d9fbb492c010a01dd7598fc9b/userdata/conmon.pid
KillMode=none
Type=forking

[Install]
WantedBy=multi-user.target default.target

Um die generierten Service-Units zu installieren und zukünftig als derjenige User auszuführen, welcher den Pod und die Container erzeugt hat, verschiebe ich sie in das zu erstellende Verzeichnis ~/.config/systemd/user. Anschließend werden die neuen Units in die Systemd-Konfiguration eingelesen und aktiviert.

$ mkdir -p .config/systemd/user
$ mv *.service .config/systemd/user/
$ systemctl --user enable pod-kanboardpod.service
$ podman pod stop kanboardpod
$ systemctl --user start pod-kanboardpod.service

Nachdem ich die Service-Units an die richtige Stelle verschoben und aktiviert hatte, habe ich meine laufende Pod-Instanz gestoppt und über die entsprechende Service-Unit gestartet.

Ich wähnte mich nun bereits am Ziel. Doch nach einem Neustart des Hosts war die Anwendung wieder nicht verfügbar. Die Service-Unit war nicht gestartet worden. Podman kann hier nichts dafür, denn es ist systemd, welcher dafür sorgt, dass im User-Kontext laufende Services beendet werden, wenn sich der entsprechende User ausloggt und diese erst startet, wenn der User sich einloggt.

Valentin Rothberg von Red Hat gab mir den entscheidenden Tipp, um dieses Problem zu lösen. Die Lösung versteckt sich in der Manpage zu podman-generate-systemd(1):

The systemd user instance is killed after the last session for the user is closed. The systemd user instance can be kept running ever after the user logs out by enabling lingering using

$ loginctl enable-linger <username>

Manual page podman-generate-systemd(1)

@Valentin: Thanks a lot, that solved my issue!

Fazit

Ich bin ehrlich gesagt hoch erfreut, dass die Entwickler hier eine Möglichkeit vorgesehen haben, um aus bestehenden Pods bzw. Container-Instanzen Systemd-Service-Units generieren zu können. Dies ermöglicht es, Container-Instanzen und Pods mit den gewohnten Werkzeugen zu starten, zu stoppen und deren Status zu kontrollieren.

So besteht die Möglichkeit, die rootless-Podman-Container auch als unprivilegierte Dienste laufen zu lassen. Das gefällt mir.

Running a NetBSD Virtual Machine on VMware ESXi on Arm Fling

15. Februar 2021 um 08:00

Dies ist ein Gastbeitrag von meinem geschätzten Kollegen Jörn Clausen. Der Beitrag wurde in englischer Sprache verfasst und behandelt die Installation von NetBSD auf dem VMware ESXi on ARM Fling.

In October 2020, VMware released a preview of their hypervisor ESXi for
the ARM architecture. It is free to download (registration needed, though) and will run for 180 days, and one of the supported platforms is the Raspberry Pi 4B. So it’s quite easy to give it a try. To install the ESXi ARM Fling, use the instructions you’ll find at the download page. The ESXi installation is not covered by this article.

A lot of Linux distributions and FreeBSD are working as guest OSes, and luckily NetBSD’s motto holds up: „Of course it runs NetBSD!“. Thanks to the work of Jared McNeill, the ARM port of NetBSD will run on ESXi for ARM.

As his instructions for creating a running NetBSD VM are a bit terse, I’d like to elaborate a little bit.

Prerequisites

You will need the following things:

  • ESXi on Arm Fling up and running (duh!)
  • SSH access to the ESXi host (activate either from the console or the
    web interface)
  • qemu-img, for example by installing emulators/qemu from
    pkgsrc

And of course you will need NetBSD. Download the latest installation image either from Jared’s site „http://www.armbsd.org/arm/“ (be sure to download „Generic 64-bit“ from the tab „NetBSD -current“), or use the latest HEAD release.

Creating a NetBSD VMDK file

Unpack the image:

$ gunzip arm64.img.gz

Increase the image to the size the hard disk should have. In this case, we grow it to just 2 GB:

$ qemu-img resize -f raw arm64.img 2g
Image resized.

Convert the image to a VMDK file

$ qemu-img convert -o compat6 -f raw arm64.img -O vmdk arm64.vmdk

Transfer the last file arm64.vmdk to the datastore on the ESXi host, either using scp or by uploading it via the web interface.

Creating a NetBSD VM

Log on to the ESXi host using ssh. Navigate to the directory where you uploaded the VMDK file. If you used a basic setup with all the defaults, this will be /vmfs/volumes/datastore1/.

Convert the VMDK file to a proper virtual hard disk:

# vmkfstools -i arm64.vmdk -d thin arm64-hd.vmdk
Destination disk format: VMFS thin-provisioned
Cloning disk 'arm64.vmdk'...
Clone: 100% done.

Switch to the web interface of ESXi and create a new VM. Use „Other“ as Guest OS family and „Other (64-bit)“ as Guest OS version.

Remove the hard disk that is automatically added to the VM. Instead, select „Add hard disk“ and „Existing hard disk“. Choose the VMDK you created in the last step (be sure to use arm64-hd.vmdk and not arm64.vmdk).

You can use the default network adapter (E1000e) or you can replace it with the paravirtualized one (VMXNET3).

Running the NetBSD VM

Now start the VM and open the console. The virtual machine should boot straight into the NetBSD boot loader and then into NetBSD. On the first boot, NetBSD will grow the filesystem to use the complete hard disk and reboot. After that, you should be able to login as root.

Now you have a complete NetBSD system. You can even run an X server on the console.

Mit Dokumentation zum Datenverlust

18. Januar 2021 um 08:00

Wie ihr sicher gemerkt habt, beschäftige ich mich im Rahmen eines Wochenend-Projekts mit „Kanboard im Container…“ im Speziellen und Linux-Containern im Allgemeinen. Die Einrichtung von „Backup und Restore im Kanboard-Container-Land“ liegt bereits hinter mir. Und das ist gut so, habe ich doch nun den ersten Datenverlust erlitten und musste meine Daten wiederherstellen.

Die etwas unglückliche Verkettung von Umständen, welche zum Datenverlust führten, möchte ich in diesem Artikel festhalten, so dass euch diese Erfahrung erspart bleiben kann.

Die Vorgeschichte

Da Container zustandslose Gebilde sind, nutze ich podman volumes, um die anfallenden Daten persistent zu speichern.

Als Einsteiger in die Thematik habe ich mich an der offiziellen Container-Dokumentation von Red Hat entlang gehangelt und bin den Anweisungen in Kapitel 3.4. Sharing files between two containers (die Dokumentation wurde überarbeitet; das Kapitel existiert so nicht mehr) gefolgt. Dort wird beschrieben, wie man den Volume-Pfad einer Variablen zuweist, welche später verwendet wird, um das Volume über den Pfad in den Container einzuhängen.

Da ich es nicht besser wusste, bin ich der Anleitung Schritt-für-Schritt gefolgt. Dies führte zu einer funktionierenden Konfiguration, in der meine Daten persistent gespeichert wurden.

Kommando ‚podman volume prune‘ und die Daten waren weg

Am Ende meiner Spielerei wollte ich das Spielfeld bereinigen. Dabei bin ich auf das Kommando podman volume prune gestoßen, welches laut podman-volume-prune(1) alle Volumens entfernt, die sich nicht in Verwendung befinden. Dies klang nach genau dem Befehl, nach dem ich gesucht habe.

TL;DR: Nach der Ausführung des Kommandos waren meine Volumes weg. Auch jene, die aktiv in laufenden Container-Instanzen eingehängt waren.

Die Analyse

Nach ein paar Tests und einer Internetrecherche stand die Ursache für das Verhalten fest. Diese ist im GitHub Issue #7862 dokumentiert und besagt, dass podman volume prune in Verwendung befindliche Volumes löscht, wenn diese über ihren Pfad und nicht über ihren Namen eingehängt wurden. Da ich wie oben beschrieben der Dokumentation von Red Hat strikt gefolgt bin, welche aber genau den Pfad und eben nicht den Namen verwendet, waren Ursache und Erklärung für den Datenverlust gefunden.

Die Folge

In Folge meiner Erfahrungen habe ich zwei Anfragen zur Produktverbesserung (englisch: Request For Enhancement oder kurz RFE) gestellt:

  1. Bug 1914096 – Needs improvement: Building, running, and managing containers: 3.4. Sharing files between two containers
  2. RFE: Let `podman volume prune` show the volumes that are going to be removed

Die erste Anfrage ist an Red Hat adressiert, mit der Bitte, in der Dokumentation den Volume-Namen an Stelle des in einer Variablen gespeicherten Volume-Pfades zu benutzen. Damit sollte verhindert werden, dass andere, die der Dokumentation folgen, die gleichen Erfahrungen wie ich machen müssen.

Als Ziel wird die Veröffentlichung von RHEL 8.4 anvisiert. Dieses Release sollte im Mai bzw. Juni 2021 erscheinen. Ich bin gespannt. Ich würde mich über eine frühere Aktualisierung der Dokumentation freuen. Update 2021-01-25: Bereits am 20. Januar wurde eine neue Version der Dokumentation veröffentlicht. In dieser war nur noch ein kleiner Tippfehler enthalten. Der Bug wurde mit dem heutigen Datum (25.01.2021) geschlossen. So ist sichergestellt, dass hier niemand mehr in die Falle tappt. Vielen Dank ans RHEL-Docs-Team im Allgemeinen und Gabriela im Speziellen.

Die zweite Anfrage richtet sich an das Upstream-Projekt. Sie beinhaltet den Vorschlag, podman volume prune (um eine Option) zu erweitern, so dass die Liste der zu löschenden Volumes angezeigt wird, bevor man die Entfernung bestätigt. Stand 17.01.2021 existiert bereits ein Pull-Request, welcher dieses Thema adressiert.

Meinen Artikel „Kanboard im Container…“ habe ich entsprechend angepasst, so dass auch dort die Volumen-Namen zum Einhängen verwendet werden und nicht die Volume-Pfade.

Alte Erkenntnis bestätigt

Dieses Beispiel zeigt wieder einmal sehr deutlich, wie wichtig eine funktionierende Datensicherung ist. Denn sie ist die zwingende Voraussetzung, um im Fehlerfall Daten auch wiederherstellen zu können. Daher kann ich nur jedem raten, ein entsprechendes Datensicherungs- und Wiederherstellungs-Konzept zu implementieren, bevor man Daten in eine Anwendung tut, die einem am Herzen liegen oder von denen die Zukunft des Unternehmens abhängt.

Zum Stöbern führe ich im Folgenden einige Artikel aus diesem Blog auf, welche sich mit dem Thema Backup befassen:

Reverse-Proxy für Kanboard im Container

11. Januar 2021 um 08:00

Im folgenden möchte ich kurz die Konfiguration dokumentieren, mit der ich Ziel 4 aus „Kanboard im Container…“ umgesetzt habe.

Zuerst habe ich meinen Pod mit dem Kanboard- und dem Posgresql-Container erstellt:

$ cat create-kanboard-pod.sh 
#!/bin/bash
kanboard_data=$(podman volume inspect kanboard_data --format {{.Mountpoint}})
kanboard_plugins=$(podman volume inspect kanboard_plugins --format {{.Mountpoint}})
kanboard_ssl=$(podman volume inspect kanboard_ssl --format {{.Mountpoint}})
pgsql_data=$(podman volume inspect pgsql_data --format {{.Mountpoint}})
podman run -d --pod new:kanboardpod --name kanboard -p 127.0.0.1:8080:80 -v $kanboard_data:/var/www/app/data:Z -v $kanboard_plugins:/var/www/app/plugins:Z kanboard/kanboard
podman run -d --pod kanboardpod --name pgsql_db -e POSTGRESQL_USER=root -e POSTGRESQL_PASSWORD=SuperGeheimesPasswort -e POSTGRESQL_DATABASE=kanboard -v $pgsql_data:/var/lib/pgsql/data:Z rhel8/postgresql-96

Als Reverse-Proxy nutze ich nginx, welchen ich mittels sudo dnf -y install nginx installiert habe. Die Konfigurationsdatei /etc/nginx/nginx.conf habe ich wie folgt ergänzt:

    server {
        listen 80;
        listen [::]:80;
        server_name kanboard.beispiel.de;
        return 301 https://kanboard.beispiel.de$request_uri;
    }

    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name kanboard.beispiel.de;

        ssl_certificate "/etc/letsencrypt/kanboard_fullchain.cer";
        ssl_certificate_key "/etc/letsencrypt/kanboard.beispiel.de.key";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers PROFILE=SYSTEM;
        ssl_prefer_server_ciphers on;

        location / {
            proxy_pass http://127.0.0.1:8080;
        }
    }

Damit nimmt der NGINX Anfragen auf den TCP-Ports 80 und 443 an, wobei ein Redirect von Port 80 auf 443 erfolgt. Diese Anfragen leitet der NGINX an den TCP-Port 8080 des Kanboard-Pods weiter.

Die Erneuerung des SSL-Zertifikats habe ich nach dem Tutorial „Let’s Encrypt: Nutzung des DNS-Alias-Modus mit dem acme.sh-Client“ automatisiert.

Backup und Restore im Kanboard-Container-Land

06. Januar 2021 um 08:00

In „Kanboard im Container“ habe ich einen Pod ins Leben gerufen, welcher die Anwendung Kanboard und eine dazugehörige Postgresql-Datenbank mittels Container bereitstellt. Backup und Restore zu konfigurieren und zu testen, habe ich letztes Wochenende nicht mehr geschafft. Dies hole ich in diesem Artikel nach.

Da die Container selbst zustandslos sind, interessieren mich nur die persistent gespeicherten Daten, welche außerhalb der Container im Dateisystem des Hosts gespeichert werden.

Umgebung

Auf einer virtuellen Maschine mit dem Gastbetriebssystem RHEL 8 läuft ein podman-Pod namens kanboardpod. Dieser Pod beinhaltet neben dem Infrastruktur-Container, einen Kanboard-Container namens kanboard und einen Postgresql-Container namens pgsql_db.

Die persistenten Daten des Kanboard-Containers werden in den Volumes kanboard_data und kanboard_plugins gespeichert. Die Datenbank-Dateien der Postgresql-DB liegen im Volume pgsql_data.

Die Namen des Pods und der Container sind hilfreich, da die Container darüber referenziert werden können. So muss man nicht mit den sperrigen IDs hantieren.

Backup

Kein Restore ohne Backup! Kein Backup, kein Mitleid!

Ich habe im Folgenden beschriebe Ansätze für ein Backup. Wenn ihr noch weitere habt, freue ich mich über eure Eingaben.

Ansatz 1: Backup auf Dateiebene — verworfen

Dieser Ansatz liegt nahe und ist einfach umzusetzen.

  1. Container stoppen
  2. Verzeichnisse im Dateisystem sichern
  3. Container wieder starten

Für meinen konkreten Anwendungsfall wäre dies auch ausreichend. Einen Dienst für die Dauer einer Datensicherung komplett stoppen zu müssen, ist jedoch nicht ideal. Daher schaue ich nach weiteren Möglichkeiten.

Ansatz 2: DB-Dump und Datei-Backup — Praktikabel aber möglicherweise inkonsistent.

Bei diesem Ansatz bleibt die Anwendung während der Datensicherung verfügbar. Während das Volume kanboard_data auf Dateiebene mittels tar gesichert wird, wird die Datenbank mittels pg_dump aus dem Container heraus gesichert. Das Backup-Skript sieht wie folgt aus:

#!/bin/bash
kanboard_data=$(podman volume inspect kanboard_data --format {{.Mountpoint}})
kanboard_plugins=$(podman volume inspect kanboard_plugins --format {{.Mountpoint}})
tar czf kanboardfiles.tgz $kanboard_data $kanboard_plugins
podman exec -t pgsql_db /usr/bin/pg_dump kanboard | gzip > ~/kanboard.sql.gz

Hinweis: Obiger Code-Schnipsel stammt aus der Kategorie Schnell-und-Schmutzig und sollte nicht in produktiven Umgebungen verwendet werden.

Der DB-Dump wird dabei direkt aus dem Container in mein Home-Verzeichnis geschrieben. Am Ende habe ich zwei unabhängige Dateien, die nun außerhalb der Container-Umgebung liegen. Da diese jedoch immer noch auf dem gleichen Host liegen, handelt es sich um kein richtiges Backup. Doch ist es nun nicht mehr schwer, sie auf ein anderes, entferntes Medium zu übertragen.

Der größte Nachteil dieses Ansatzes besteht darin, dass die Konsistenz der Sicherung nicht garantiert ist. Die Datenbank enthält Referenzen in das Dateisystem. Referenzen in der Datenbank und Inhalt des gesicherten Dateisystems müssen nicht in jedem Fall zueinander passen, da während der Sicherung weiter in der Anwendung gearbeitet werden kann.

Nun kann man natürlich vor der Sicherung den Container kanboard stoppen und anschließend wieder starten. Damit erhält man eine konsistente Sicherung zu dem Preis, dass die Anwendung temporär nicht verfügbar ist. Damit unterscheidet sich der Ansatz gegenüber Ansatz 1 nur noch darin, dass der Container pgsql_db online bleibt und man die DB mit pg_dump sichert, statt eine Sicherung auf Dateisystemebene zu machen.

Schön ist das nicht, doch mache ich es meiner Umgebung genau so.

Ansatz 3: Backup auf Basis eines konsistenten Dateisystem-Snapshots

Dies ist in meinen Augen der vernünftigste Ansatz.

Die persistenten Daten der Container liegen in einem Dateisystem. Unterstützt dieses Dateisystem Snapshots, können diese genutzt werden, um die Dateisysteminhalte zum Zeitpunkt des Snapshots auf das Backup-Medium zu übertragen und den Snapshot anschließend wieder zu entfernen. Anwendung und Datenbank können bei diesem Verfahren während der Sicherung weiterlaufen.

Das so erstellte Datenbank-Backup befindet sich allerdings in einem Zustand, als wäre die Datenbank unsauber beendet worden. Nach einem Restore werden demnach die WAL-Logs benötigt (siehe PostgreSQL 9.6.20 Documentation: 25.2. File System Level Backup).

Ich habe mich gegen diesen Ansatz entschieden, da mir in meiner Test-Umgebung noch die Erfahrung mit Dateisystem-Snapshots fehlt. Dies werde ich evtl. zu einem späteren Zeitpunkt unter die Lupe nehmen.

Restore

Ich habe mich für den Ansatz 2 entschieden. Damit habe ich folgende zwei Dateien:

  • kanboard.tgz – Enthält die persistenten Daten des Kanboards
  • kanboard.sql.gz – Enthält den Dump der Kanboard-Datenbank

Das tar-Archiv wird extrahiert und fertig. Um den DB-Dump mit dem Werkzeug pg_restore wieder einspielen zu können, muss dieser zuvor in ein Volume kopiert werden, das innerhalb des Postgresql-Containers zur Verfügung steht. Anschließend kann die Datenbank mit folgendem Befehl wiederhergestellt werden:

# pg_restore -C -d kanboard kanboard.sql

Fazit

Grundsätzlich habe ich Ziel Nummer 5 „Backup und Restore“ ebenfalls erreicht.

Der Restore erfordert noch einiges an Handarbeit und ist etwas fummelig. Soetwas möchte man in einer angespannten Situation nicht gerne haben. Hier ist noch etwas Feinschliff nötig.

Darüber hinaus kann ich mir vorstellen auch noch einen automatisierten Restore-Test zu etablieren, welcher prüft, ob sich ein erstellter DB-Dump auch wieder herstellen lässt. Das ist dann aber sicher ein eigenes Wochenendprojekt. Und nächstes Wochenende mache ich mal frei.

Kanboard im Container…

04. Januar 2021 um 08:00

… aber das sind ja gleich zwei Dinge auf einmal. Richtig. Denn hier versuche ich, etwas nützliches (Kanboard) mit der Möglichkeit, etwas zu lernen (Container), zu kombinieren.

Inspiriert durch Dirks Artikel und einem darauf folgenden, regen E-Mail-Verkehr, widme ich mich mal wieder dem Thema Linux-Container. Zuletzt hatte ich mich ca. 2016/2017 damit befasst und es mit der Erkenntnis zu den Akten gelegt, dass es noch ein Hype und für den produktiven Einsatz wenig geeignet war. Mittlerweile hat sich die Lage etwas geändert. Einige Unternehmen haben sich des Themas angenommen und arbeiten daran, Linux-Container Enterprise-Ready zu gestalten. So nehme ich wahr, dass in meinem beruflichen Netzwerk seit ca. Anfang 2019 OpenShift-Cluster wie Pilze aus dem Boden schießen. Man könnte den Eindruck gewinnen, dass Red Hat diese Subskriptionen wie geschnitten Brot verkauft. Andere Hersteller scheinen den relativ jungen Markt nicht allein den roten Hüten überlassen zu wollen. So hat VMware mit vSphere 7 und Tanzu hier ebenfalls eine Lösung im Portfolio und auch SUSE scheint sich mit dem Kauf von Rancher in diesem Segment stärker zu engagieren.

Ich selbst möchte mein Wissen rund um dieses Thema auffrischen und habe mir daher folgendes Wochenendprojekt überlegt. Um Projekte, Aufgaben oder schlicht den Alltag besser zu organisieren, möchte ich zukünftig die Anwendung Kanboard nutzen. Diese Anwendung unterstützt die Aufgaben- bzw. Projekt-Organisation nach der Kanban-Methode. Sie macht einen minimalistischen Eindruck, kommt ohne viel Schnick-Schnack daher und scheint daher gut zu mir zu passen. Um gleichzeitig praktische Erfahrungen im Umgang mit Linux-Containern zu sammeln, werde ich Kanboard mit einer Postgresql-Datenbank mit Hilfe von zwei Containern betreiben.

In meinen Augen wird Docker in den nächsten Jahren sowohl als Firma wie auch als Werkzeug stetig an Bedeutung verlieren. Daher setze ich bei der Umsetzung meines Wochenend-Projekts auf die Werkzeuge podman, skopeo und buildah.

Ich gehe in diesem Text nicht auf die Konzepte, die Architektur, sowie die Vor- und Nachteile von Linux-Containern ein. Hierzu wurde in den letzten Jahren bereits genug an anderer Stelle geschrieben. Informationen zu diesen Themen finden sich in der — im Aufbau befindlichen — Linksammlung und am Ende dieses Artikels.

Umfeld

Als Basis für dieses Projekt dient mir eine virtuelle Maschine in meinem heimischen Labor. Als Betriebssystem nutze ich ein aktuelles RHEL 8 mit der kostenlosen Developer-Subskription. Diese VM dient mir als Host zum Ausführen diverser Linux-Container. Um die Container aus dem Netzwerk erreichbar zu machen, installiere ich NGINX aus den Paketquellen von RHEL 8. Dieser kümmert sich als Reverse-Proxy um die Portweiterleitung zu den Containern.

Ziele

Mit diesem Wochenendprojekt möchte ich folgende Ziele erreichen:

  1. Bereitstellung der Anwendung Kanboard mittels Linux-Container
  2. Nutzung von Postgresql mittels Container als Kanboard-Datenbank-Backend
  3. Persistente Speicherung der Kanboard-Inhalte im Dateisystem des Hosts
  4. Erreichbarkeit und Nutzbarkeit von Kanboard über den NGINX-Reverse-Proxy
  5. Einrichtung Backup und Restore
  6. Updates

Schritt 1: rootless-Container-Umgebung einrichten

Während Entwickler viel Schweiß und Tränen investiert haben, damit Dienste wie Apache oder NGINX nach ihrem Start die root-Rechte ablegen können, liefen die ersten Linux-Container durchgängig mit root-Rechten. Dies ist aus Sicht der IT-Sicherheit nicht wünschenswert. Daher ist es in meinen Augen erfreulich, dass es mittlerweile auch ohne root-Rechte geht; Kernel User Namespaces sei Dank.

Ich folge der Red Hat Dokumentation (Kapitel 1.4, [1]), um den User Alice für die Nutzung von rootless-Containern einzurichten.

# echo "alice:165537:65536" >> /etc/subuid
[root@podhost-r8-1 ~]# echo "alice:165537:65536" >> /etc/subgid
[root@podhost-r8-1 ~]# echo "user.max_user_namespaces=65636" > /etc/sysctl.d/userns.conf
[root@podhost-r8-1 ~]# sysctl -p /etc/sysctl.d/userns.conf
user.max_user_namespaces = 65636

Anschließend installiere ich wie in Kap. 1.3 [1] beschrieben die Container-Tools.

# yum module install -y container-tools
$ podman --version
podman version 2.0.5

Der Werkzeugkasten ist bestückt. Weiter zu Schritt 2.

Schritt 2: Container-Images suchen, inspizieren und herunterladen

Mit dem Kommando podman mache ich mich auf die Suche nach Containern für Kanboard.

$ podman search kanboard
INDEX       NAME                                            DESCRIPTION                                       STARS   OFFICIAL   AUTOMATED
docker.io   docker.io/kanboard/kanboard                     Official Docker image for Kanboard                34
docker.io   docker.io/webhippie/kanboard                    Docker images for Kanboard                        2                  [OK]
docker.io   docker.io/larueli/kanboard-nonroot              Safe image for Kanboard as Non Root / Suitab...   0
docker.io   docker.io/masker/kanboard                       use alpine linux build kanboard server            0
docker.io   docker.io/xoxys/kanboard                        Deprecated                                        0
docker.io   docker.io/dotriver/kanboard                     Kanboard on Alpine Linux + S6 Overlay             0
docker.io   docker.io/thegeeklab/kanboard                   Custom image for Kanboard Kanban project man...   0
docker.io   docker.io/jonats/kanboard-pi                    Raspberry Pi image for Kanboard                   0
docker.io   docker.io/bastilian/kanboard                                                                      0
docker.io   docker.io/oriaks/kanboard                       Kanboard                                          0                  [OK]
docker.io   docker.io/kanboard/tests                                                                          0
docker.io   docker.io/blufor/kanboard                       Kanboard with Postgres, SMTP and GitLab inte...   0                  [OK]
docker.io   docker.io/boomer/kanboard                       Kanboard is a simple visual task board web a...   0
docker.io   docker.io/joshuacox/kanboard-redmine            kanboard redmine importer                         0                  [OK]
docker.io   docker.io/janost/kanboard-unit                  Kanboard + nginx unit, running rootless with...   0
docker.io   docker.io/benoit/kanboard                                                                         0                  [OK]
docker.io   docker.io/lidstah/kanboard                      Kanboard armv71 debian (nginx/php7-fpm) base...   0
docker.io   docker.io/doc75/kanboard                                                                          0
docker.io   docker.io/witsec/kanboard                       Kanboard, with the option to filter (hide) s...   0                  [OK]
docker.io   docker.io/ionutalexandru97/kanboard-openshift   Kanboard ready to be deployed on OpenShift        0
docker.io   docker.io/hihouhou/kanboard                     simple kanboard                                   0                  [OK]
docker.io   docker.io/alxsdhm/kanboard                      kanboard image                                    0
docker.io   docker.io/papango/kanboard                                                                        0
docker.io   docker.io/mrtheduke/kanboard                    kanboard                                          0
docker.io   docker.io/kvorobyev/kanboard_app

Herzlichen Glückwunsch. Die Trefferliste stellt für mich als SysAdmin einen Alptraum dar. Sämtliche Treffer stammen vom Docker-Hub, einem riesigen Misthaufen für Software (welcher durchaus ein paar Perlen enthalten kann). Von den 26 Treffern ist keiner als OFFICIAL markiert, lediglich die Anzahl STARS bietet einen Anhaltspunkt, welcher Container den meisten Zuspruch findet. In einer Produktiv-Umgebung sollte man sich jedoch nicht allein auf diese Sterne verlassen. Ich inspiziere das Container-Image mit den meisten Sternen mit skopeo:

$ skopeo inspect docker://docker.io/kanboard/kanboard | less

Die vollständige Ausgabe spare ich hier aus. Sie ist wenig hilfreich. Mit ein wenig Internet-Recherche ([2], [3] und [4]) bin ich hinreichend sicher, das „offizielle“ Container-Image des Projekts gefunden zu haben.

Als nächstes mache ich mich auf die Suche nach Postgresql:

$ podman search postgresql | wc -l
64

Naja, zumindest an Auswahl scheint es auch diesmal nicht zu mangeln. Hier komme ich so jedoch nicht weiter. Also nehme ich einen Webbrowser zur Hand und recherchiere ein geeignetes Container-Image unter der URL: https://catalog.redhat.com/software/containers/explore

Da ich Red Hat bereits zutraue, eine stabile und hinreichend sichere Enterprise Linux Distribution zu bauen, traue ich ihnen auch zu, ordentliche Container-Images für Postgresql zu bauen. Daher fasse ich folgende drei Kandidaten ins Auge:

  1. rhel8/postgresql-96
  2. rhel8/postgresql-10
  3. rhel8/postgresql-12

Zu diesem Zeitpunkt (2020-12-27) fehlt Nr. 3 eine ordentliche Beschreibung. Dafür kommt dieses Image mit 6 offenen Sicherheitslücken daher. Nr. 2 besitzt nur 3 Schwachstellen und eine deutliche bessere Dokumentation zu dessen Verwendung. Und Nr. 1 ist zwar das Älteste, jedoch auch das mit einer guten Dokumentation und ohne Schwachstellen.

Kanboard erfordert Postgresql >= 9.4. Damit ist Nummer 1 mein Gewinner. Mit den beiden folgenden Kommandos hole ich mir die Kanboard- und Postgresql-Container-Images auf meinen Host.

$ podman pull docker.io/kanboard/kanboard
Trying to pull docker.io/kanboard/kanboard...
Getting image source signatures
Copying blob df20fa9351a1 done  
Copying blob 3108c8300796 done  
Copying blob b190b4dd9bb5 done  
Copying blob bb1f52abd628 done  
Copying blob e37ffd2cbe7b done  
Copying config c355188e0c done  
Writing manifest to image destination
Storing signatures
c355188e0c187bc891826d282cc850cbe0907ccd7df28d4487d024d831c4f9af

$ podman login --username=Joerg-Dev registry.redhat.io
Password: 
Login Succeeded!
$ podman pull registry.redhat.io/rhel8/postgresql-96
Trying to pull registry.redhat.io/rhel8/postgresql-96...
Getting image source signatures
Copying blob cca21acb641a done  
Copying blob 620696f92fec done  
Copying blob fca753c96be9 done  
Copying blob d9e72d058dc5 done  
Copying config f7266b012d done  
Writing manifest to image destination
Storing signatures
f7266b012db03478b858eba6af4264829b99ce9ac67d6bc8a7c273b5fc5c8e9a

Damit ist dieser Schritt abgeschlossen. In Schritt drei erstelle ich sogenannte Volumes, um Daten außerhalb der Container persistent im Dateisystem des Hosts speichern zu können.

Schritt 3: Persistenten Speicher für Container erzeugen

Nach dem Container-Mantra haben diese zustandslos zu sein. Dies bedeutet, dass in ihnen gespeicherte Daten verloren gehen, wenn der Container entfernt wird. Nun hat es die Elektronische Datenverarbeitung (EDV) so an sich, dass das Ergebnis der Verarbeitung häufig persistent zu speichern ist. Dies kann im Container-Universum mit sogenannten Volumes erledigt werden. Hierbei wird ein Verzeichnis vom Host in den Container eingehängt.

Für mein Projekt erstelle ich nach Kapitel 3.4 [1] folgende Volumes:

  • kanboard_data
  • kanboard_plugins
  • kanboard_ssl
  • pgsql_db
$ podman volume create VOLUMENAME

Um im Folgenden etwas leichter mit diesen Volumes arbeiten zu können, speichere ich den Einhängepfad in Variablen à la:

$ mntPoint=$(podman volume inspect VOLUMENAME --format {{.Mountpoint}})

Die obige Streichung erfolgte, da dieser Schritt nicht notwendig ist und im weiteren Artikel nicht mit entsprechenden Variablen gearbeitet wird.

Schritt 4: Kanboard konfigurieren

Um eine angepasste, persistente config.php-Datei für den Kanboard-Container zu schreiben, ist etwas Vorarbeit notwendig. Der Kanboard-Container wird gestartet und das Volume „kanboard_data“ wird dabei in den Pfad /var/www/app/data gemountet. Anschließend starte ich eine Shell im Container und kopiere die Datei /var/www/app/config.default.php nach /var/www/app/data/config.php.

$ podman run -d --name kanboard -v kanboard_data:/var/www/app/data:Z  kanboard/kanboard
93e6d7e3847fb94639b8fce89ddb93a3879a80522f95ed13dff91f6558594ac6
$ podman ps
CONTAINER ID  IMAGE                               COMMAND  CREATED        STATUS            PORTS   NAMES
93e6d7e3847f  docker.io/kanboard/kanboard:latest           5 seconds ago  Up 5 seconds ago          kanboard
$ podman exec -it 93e6d7e3847f /bin/bash
bash-5.0# cp /var/www/app/config.default.php /var/www/app/data/config.php
bash-5.0# exit
exit
$ podman stop 93e6d7e3847f && podman rm 93e6d7e3847f
$ vi $kanboard_data/config.php

Um Postgresql als Datenbank-Backend zu nutzen, werden folgende Werte in der config.php gesetzt:

// Run automatically database migrations
// If set to false, you will have to run manually the SQL migrations from the CLI during the next Kanboard upgrade
// Do not run the migrations from multiple processes at the same time (example: web page + background worker)
define('DB_RUN_MIGRATIONS', true);

// Database driver: sqlite, mysql or postgres (sqlite by default)
define('DB_DRIVER', 'postgres');

// Mysql/Postgres username
define('DB_USERNAME', 'root');

// Mysql/Postgres password
define('DB_PASSWORD', 'SuperSicheresPasswort');

// Mysql/Postgres hostname
define('DB_HOSTNAME', 'localhost');

// Mysql/Postgres database name
define('DB_NAME', 'kanboard');

// Mysql/Postgres custom port (null = default port)
define('DB_PORT', null);

Normalerweise würde man eine Anwendung niemals mit dem Datenbank-Root-User auf eine Datenbank zugreifen lassen. In dieser Umgebung ist es hingegen verschmerzbar, da nur die Daten des Kanboards in diesem Postgresql-Container gespeichert werden. Im Falle einer Kompromittierung verliere ich nur die zur Anwendung gehörende Datenbank.

Schritt 5: Pod erstellen und Container hinzufügen

Mit diesem Schritt habe ich etwas Mühe. Zuerst wollte ich einen Pod erstellen, den Kanboard- und Postgresql-Container zu diesem hinzufügen, um sie stets gemeinsam starten und stoppen zu können. Dies ist laut [1] und [7] der einfachste Weg. Allerdings habe ich dann in [5] und [7] gelesen, dass sich die Container eines Pods dessen IP, MAC und Port-Bindings teilen. Dies bedeutet, dass Portfreigaben für Kanboard (80 und 443 TCP) auch für den Postgresql-Container gültig sind. Dies möchte ich eigentlich nicht. Doch ist mir bisher nichts besseres eingefallen. Falls ihr Anregungen oder konkrete Beschreibungen habt, wie ich dies besser umsetzen kann, immer her damit.

Frickelpit hat mich in seinem Kommentar darauf hingewiesen, dass man den Zugriff auf den Port des Pods noch weiter beschränken kann, indem man diesen an 127.0.0.1 bindet. Ich habe unten stehenden Code-Block entsprechend aktualisiert.

Ich erstelle nun gemäß [7] einen neuen Pod, welcher den Kanboard-Container beinhaltet und für diesen Port-Bindings besitzt:

$ podman run -d --pod new:kanboardpod --name kanboard -p 127.0.0.1:8080:80 -v kanboard_data:/var/www/app/data:Z -v kanboard_plugins:/var/www/app/plugins:Z kanboard/kanboard
e62c7fa2ecf771f4085e788e9f0f7d24b7f87d487e9951a403847d8a7a2a6471

$ podman pod ps
POD ID        NAME         STATUS   CREATED        # OF CONTAINERS  INFRA ID
d7afa6821382  kanboardpod  Running  8 seconds ago  2                6b065fe7ecc7

$ podman ps
CONTAINER ID  IMAGE                               COMMAND  CREATED         STATUS             PORTS                 NAMES
6b065fe7ecc7  k8s.gcr.io/pause:3.2                         10 seconds ago  Up 10 seconds ago  0.0.0.0:8080->80/tcp  d7afa6821382-infra
e62c7fa2ecf7  docker.io/kanboard/kanboard:latest           10 seconds ago  Up 10 seconds ago  0.0.0.0:8080->80/tcp  kanboard

Im zweiten Schritt füge ich den Postgresql-Container hinzu:

$ podman run -d --pod kanboardpod --name pgsql_db -e POSTGRESQL_USER=root -e POSTGRESQL_PASSWORD=SuperGeheimesPasswort -e POSTGRESQL_DATABASE=kanboard -v pgsql_data:/var/lib/pgsql/data:Z rhel8/postgresql-96
c242a4b9b57d53a822585c9eb83d081d5abbd40cb2b5952aee4457fee041e128

$ podman ps
CONTAINER ID  IMAGE                                          COMMAND         CREATED        STATUS            PORTS                 NAMES
6b065fe7ecc7  k8s.gcr.io/pause:3.2                                           2 minutes ago  Up 2 minutes ago  0.0.0.0:8080->80/tcp  d7afa6821382-infra
c242a4b9b57d  registry.redhat.io/rhel8/postgresql-96:latest  run-postgresql  3 seconds ago  Up 3 seconds ago  0.0.0.0:8080->80/tcp  pgsql_db
e62c7fa2ecf7  docker.io/kanboard/kanboard:latest                             2 minutes ago  Up 2 minutes ago  0.0.0.0:8080->80/tcp  kanboard

Nun läuft ein Pod mit drei Containern (Infra-, Kanboard- und Postgresql-Container). Rufe ich http://IP-DES-HOSTS:8080 in einem Webbrowser auf, begrüßt mich bereits die Kanboard-Anmeldemaske (Bild 1).

Bild 1: Kanboard-Anmeldemaske

Schritt 6: Nacharbeiten

Der Start meines Postgresql-Containers wollte anfangs nicht glücken, da das Verzeichnis /var/lib/pgsql/data/userdata nicht erstellt werden konnte. Abhilfe für das Problem findet sich in der Red Hat Wissensdatenbank unter: https://access.redhat.com/solutions/3508731 (Login required)

Zwar konnte ich mich bereits an der Kanboard-Anwendung anmelden, neue Nutzer erstellen und Profileinstellungen verwalten, doch beim Dateiupload klemmte es noch. Hier musste ich noch das Verzeichnis $kanboard_data/files mit Dateimode ‚0777‘ erstellen. Anschließend habe ich in der config.php-Datei des Kanboard-Containers den folgenen Standardwert, wie im Codeblock gezeigt angepasst:

// Folder for uploaded files (must be writeable by the web server user)
// Folgende Zeilen wurden auskommentiert
// define('FILES_DIR', DATA_DIR.DIRECTORY_SEPARATOR.'files');

// Folgender Eintrag wurde hinzugefuegt
define('FILES_DIR', 'data/files');

Abschließend habe ich den Kanboard-Container mittels podman restart kanboard neugestartet.

Fazit

Bei der Internet-Recherche nach guter Dokumentation und der Arbeit mit einigen Container-Registries erinnere ich mich an ein Zitat:

Das Internet ist ein großer Misthaufen, in dem man allerdings auch kleine Schätze und Perlen finden kann.

Joseph Weizenbaum, Vortrag in Hamburg am 2. Mai 2001, heise.de

Bisher wurden die Ziele 1-3 erreicht. Die dabei verwendeten Befehlszeilen besitzen eine beachtliche Länge. Hier bietet es sich an, die Befehle in kurze Shell-Wrapper zu verpacken.

Die Ziele 4 und 5 werde ich in einem Folgeartikel, an einem anderen Wochenende, in Angriff nehmen. Und auch der Frage, wie man diesen Verhau am besten aktualisiert und Updates implementiert, werde ich noch nachgehen.

Ihr habt bis hierhin durchgehalten? Dann danke ich euch für euer Interesse. Was haltet ihr von diesem Wochend-Projekt? Wieviel Sinn bzw. Unsinn steckt darin? Bitte lasst es mich in den Kommentaren oder auch gern per E-Mail wissen.

Quellen und weiterführende Links

  1. Building, running, and managing Linux containers on Red Hat Enterprise Linux 8
  2. Kanban Project Management Software — Kanboard
  3. Running Kanboard with Docker
  4. Kaboard Releases
  5. https://podman.io/getting-started/network
  6. Error „mkdir cannot create directory /var/lib/pgsql/data/userdata : Permission denied“ when deploying Postgresql with persistent storage on Openshift Container Platform 3
  7. Podman: Managing pods and containers in a local container runtime; Brent Baude; January 15, 2019

Das war das Jahr 2020 auf My-IT-Brain

31. Dezember 2020 um 13:45

Das Jahr 2020 war schon ein paar Wochen alt, als ich verkündete, was euch 2020 hier erwartet. Ich glaube, ich habe mich an den Ausblick gehalten.

Das Jahr fing ruhig an, bevor es unser aller Leben radikal veränderte. War mein Berufsleben2019 noch vom Pendeln zur Dienststelle und zurück geprägt, hat die Pandemie auch meinen Arbeitsplatz radikal verändert. Seit Mitte März arbeite ich konsequent im heimischen Arbeitszimmer. Seither habe ich screen in den Ruhestand entlassen und arbeite konsequent mit tmux und xpanes.

Ich habe lange über die Anschaffung eines elektrisch höhenverstellbaren Schreibtischs für mein Arbeitszimmer nachgedacht, bevor ich knapp 5 Monate später einen solchen mein Eigen nannte. Ich denke, dies war in diesem Jahr meine sinnvollste Anschaffung.

Auch die berufliche Kommunikation hat sich stark verändert; in meinen Augen jedoch weder zum Positiven noch zum Negativen. Bisher bin ich im Home-Office sehr zufrieden. Eine Rückkehr in die Dienststelle kann ich mir aktuell hingegen nicht vorstellen.

Mitte des Jahres durfte ich mit einem Team rund um Mohit Goyal (Senior Principal Product Manager, Red Hat) zusammen arbeiten und habe Red Hat Insights unter die Lupe genommen. Dabei herausgekommen ist unter anderem folgende Artikelserie:

  1. Einführung in Red Hat Insights
  2. Erkundung von Red Hat Insights — Advisor
  3. Schwachstellen-Management mit Red Hat Insights
  4. Red Hat Insights – Compliance
  5. Red Hat Insights – Patch and Drift
  6. Persönliche Bewertung von Red Hat Insights

In der Kategorie Ansible gab es hingegen nicht so viel Neues. Ich habe in diesem Jahr eher ein wenig Projektpflege beim Spiegelserver für arme Admins und dem Patchmanagement für RHEL betrieben.

Zusammen mit einem Kollegen habe ich noch ein Tutorial zur Nutzung des DNS-Alias-Modus mit dem acme.sh-Client geschrieben. Wir haben einiges an positiven Rückmeldungen dafür bekommen, was mich persönlich sehr gefreut hat.

Wie an den Artikeln zu erkennen ist, lag der Fokus in diesem Jahr auf Technologien und Produkten von Red Hat. Dies wird sich in 2021 vermutlich in Teilen fortsetzen. Vermutlich wird hier dann vermehrt etwas zu Linux-Containern zu lesen sein, mit denen ich mich etwas ausführlicher beschäftigen möchte.

Darüber hinaus plane ich die Einführung einer neuen Kategorie, deren Name noch nicht feststeht. In dieser möchte ich technische Sachverhalte möglichst einfach erklären, so dass auch Menschen ohne IT-Ausbildung verstehen können, wie das Internet und unsere digitale Welt funktionieren.

Ich wünsche euch allen einen guten Rutsch ins Jahr 2021!

Freie Software und Open Source…

28. Dezember 2020 um 08:00

… was ist das eigentlich? Und wie wirkt sich die Nutzung für den einzelnen Nutzer oder eine Organisation wie ein Unternehmen oder eine Behörde aus? Zu diesen Fragen mache ich mir in diesem Beitrag ein paar Gedanken, die ich gern mit euch diskutieren möchte.

Die Antwort auf die erste Frage fällt mir dabei noch leicht. Freie Software bzw. Open Source Software (FLOSS) sind Anwendungen, die unter einer freien bzw. freizügigen Lizenz stehen. Dabei orientiere ich mich an den Debian-Richtlinien für Freie Software (DFSG), welche u. a. bestimmen:

  1. Die Software darf uneingeschränkt weitergegeben oder verkauft werden.
  2. Der Quelltext der Software muss offen und für jeden frei zugänglich sein. Eine Weitergabe der Software muss sowohl als Quelltext als auch in kompilierter Form erlaubt sein.
  3. Es muss erlaubt sein, die Software zu untersuchen, zu ändern, zu erweitern und unter den gleichen Lizenzbedingungen wie die Original-Software weiterzugeben.
  4. Die Lizenz darf keine Person oder Gruppe von Personen diskriminieren.
  5. Die Lizenz darf keine Einschränkungen hinsichtlich des Einsatzbereichs vornehmen. Beispielsweise darf sie nicht verhindern, dass das Programm geschäftlich oder für genetische Forschungen verwendet wird.

Was habe ich als (privater) Nutzer davon?

Auch wenn es schön ist, den Quelltext bei Interesse studieren zu können, glaube ich persönlich nicht, dass viele Nutzer von dieser Möglichkeit Gebrauch machen. Und wenn doch, haben sie den Text vermutlich schnell wieder von ihrem Bildschirm verbannt.

Nun sind viele FLOSS-Anwendungen kostenlos erhältlich und nutzbar. Und obwohl ich die Geiz-ist-geil-Mentalität nicht mag, ist dies für den Anwender tatsächlich ein großer Vorteil.

Zu meinen Schul- und Ausbildungszeiten kostete professionelle und oftmals proprietäre Bürosoftware verdammt viel Geld. Teilweise waren dies mehrere hundert DM bzw. EUR. Und dafür durfte man die entsprechenden Anwendungen nur auf einem einzigen PC installieren. Nun hatte ich damals weder die Bereitschaft noch die Mittel, so viel Geld für ein Office-Paket aufzubringen, von dessen Funktionsumfang ich nur einen Bruchteil benötigte und nutzen würde.

Daher war ich hoch erfreut, dass es OpenOffice gab. Entstanden aus den offengelegten Quelltexten von StarOffice bot sich mir hiermit die Möglichkeit, meine Briefe, Aufsätze, Tabellen und Präsentationen zu gestalten, ohne mich dafür in Unkosten zu stürzen. Zugegeben sahen die Präsentationsvorlagen damals schon wie Tapeten aus den siebziger Jahren aus. Aber die proprietären Alternativen waren damals nicht viel besser.

Viele unter euch kennen sicherlich die Überraschungen, die man erleben kann, wenn man Text- und Tabellen-Dokumente zwischen freien und proprietären Office-Suiten austauscht. Aber glaubt mir, diese Problemchen sind nicht mit denen vergleichbar, als ich meinem Lehrer den Aufsatz, verfasst auf einem C64, auf einer 5,25-Zoll-Diskette überreicht habe. Zum Glück hatte ich noch die auf Endlospapier gedruckte Fassung dabei, erstellt auf einem 9-Düsen-Tintenstrahl-Drucker, welche mir die Note rettete.

Ein ärgerliches Problem jedoch bleibt. Es nützt dem Bürger nichts, wenn seine mit freier Software erstellten Dokumente von Behörden nicht angenommen bzw. verarbeitet werden können. Genauso doof ist die Situation anders herum. Wenn man von Behörden Dateien übermittelt bekommt, welche sich nur mit der proprietären Software anzeigen lassen, mit der sie erstellt wurden. Hier ist in den letzten zwanzig Jahren schon vieles besser und einfacher geworden. Und als Optimist glaube ich daran, so lange zu leben, dass ich noch erleben werde, dass es noch besser wird.

Habt ihr ähnliche Erfahrungen gemacht? Wie seht ihr die Situation heute?

Mit den Jahren hat sich die Situation bei der Bürosoftware geändert. So gab es zwischenzeitlich für private Nutzung und für Schüler/Studenten eine proprietäre Office-Suite für 99 EUR, welche gleichzeitig auf bis zu drei Geräten installiert und genutzt werden durfte. Hier stimmt für meinen Geschmack das Preis-Leistungsverhältnis. Nur war diese Software nicht für mein Betriebssystem erhältlich und kam somit nicht in Frage. Ich glaube jedoch bis heute, dass es entsprechende Angebote nicht gegeben hätte, ohne dass freie Alternativen verfügbar gewesen wären und es heute noch sind.

Ein weiteres Beispiel für FLOSS ist die in diesem Beitrag schon für einige Links verwendete Wikipedia. Früher hatte man vielleicht ein Lexikon oder den Brockhaus daheim. Wobei letzterer sogar eine echte Geldanlage war. Das Wissen in den Büchern verstaubte, wie die Bücher selbst auch. Heute haben dank Wikipedia sehr viele Menschen dieser Welt freien Zugang zu nahezu unbegrenztem Wissen. Ich finde dies großartig.

Ich schrieb eingangs, dass ich kein Freund der Geiz-ist-geil-Mentalität bin. Dies liegt in der Annahme begründet, dass gute Software nicht nur in der Freizeit von Entwicklern zwischen 22:00-23:50 Uhr entsteht. Wenn viele Entwickler gute Anwendungen programmieren, sollten sie dafür auch bezahlt werden. Doch scheint es wider der Natur des Menschen zu sein, für eine Leistung zu bezahlen, die er auch kostenlos erhalten kann. Dies missfällt mir und ich habe beschlossen, da nicht mitzumachen.

Ich selbst bin mittleren Alters, habe Familie, stehe mitten im Berufsleben und beziehe ein Einkommen, welches meiner Familie und mir ein gutes Auskommen ermöglicht. Und ich habe beschlossen, einen kleinen unbedeutenden Teil meines Einkommens für FLOSS-Projekte zu spenden.

Dabei überlege ich mir einmal im Jahr, welchen Betrag ich insgesamt spenden möchte und welche Anwendungen oder Projekte ich besonders häufig genutzt habe; bzw. welche Anwendungen/Projekte mir besonders wichtig waren. Anschließend entscheide ich, wie ich den von mir festgelegten Betrag aufteile und überweise die einzelnen Summen. Mir ist bewusst, dass der gespendete Betrag nichtmal einem Monatsgehalt eines professionellen Software-Entwicklers entspricht. Doch ich denke, Kleinvieh macht auch Mist und habe ein gutes Gefühl dabei.

Heute nutze ich fast ausschließlich freie Software. E-Mail-Client, Textverarbeitung, Editoren und Betriebssystem; alles FLOSS. Dabei bin ich der Nutzung proprietärer Software gar nicht abgeneigt. So würde ich auch heute noch zu proprietären Anwendungen für die Steuererklärung oder das Online-Banking greifen, bevor ich mich mit den freien Alternativen abquäle.

Zwar existieren einige liebgewonnene Anwendungen heute nicht mehr, weil die Hersteller sie abgekündigt oder zur Unbenutzbarkeit weiterentwickelt haben. Doch habe ich das gleiche auch schon mit FLOSS-Anwendungen durchgemacht.

Wie ist das bei euch? Verwendet ihr freie bzw. quell-offene Software in eurem Alltag? Wenn ja, in welchem Umfang? Und wie zufrieden seid ihr damit? In welchen Bereichen fehlt es eurer Meinung nach an freien Alternativen? Nutzt gern die Kommentarfunktion oder schreibt mir per E-Mail, wenn ihr mögt.

Was tun, wenn’s klemmt?

FLOSS und proprietäre Software haben gemein, dass sie fehlerbehaftet sind. Ohne eine Gewährleistungspflicht auf Software wird sich dieser Umstand auch nie ändern. Doch was kann man als Privatanwender tun, wenn eine Anwendung mal nicht so will, wie sie soll? Oder man einfach nicht weiß, wie man sein gewünschtes Ziel erreicht?

In meinen Augen gehört zu jeder Anwendung auch ein Handbuch, eine Anleitung und eine Befehlsreferenz als Dokumentation. Je nach Hersteller, Projekt bzw. Anwendung schwankt die Qualität von Dokumentation von „nicht vorhanden“ über „beschissen ist geprahlt“ bis „erfreulich gut“. Hier lohnt sich ein erster Blick. Kommt man mit der vorhandenen Dokumentation nicht weiter, findet man häufig Hilfe in den unzähligen Internetforen, wo freiwillige, engagierte Nutzer anderen Nutzern bei Sorgen, Nöten und Problemen weiterhelfen.

Um nicht ständig die gleichen Fragen aufs neue zu beantworten, wird lediglich verlangt, das verdammte Handbuch (RTFM) gelesen und die Suchfunktion verwendet zu haben, bevor man ein neues Thema eröffnet. Wer sich an diese einfachen, grundlegenden Regeln hält und darüber hinaus stets freundlich bleibt, dem wird mit großer Wahrscheinlichkeit geholfen.

Wer hingegen rüpelhaft, in rauhem Ton sofortige Unterstützung und Lösungen für ein Problem mit einer Anwendung einfordert, für die man nichtmal einen Cent zu spenden/zahlen bereit war, darf sich nicht wundern, am langen Arm zu verhungern. Und das ist in meinen Augen vollkommen in Ordnung.

Neben der Dokumentation und den Internetforen gibt es natürlich noch die technisch begabten Verwandten. Diese reisen meist an Wochenenden und hohen Feiertagen an, um die IT-Probleme ihrer Familie und Nachbarn zu fixen. Doch bitte nutzt die Hilfe dieser edlen Ritter ohne Rüstung nicht schamlos aus. Sie kommen euch unter Umständen viel häufiger besuchen, wenn sie für den Kaffee nicht drei Laptops und zwei Handys neuinstallieren müssen.

Damit sind die Möglichkeiten eigentlich auch ausgeschöpft. Kommerzielle und finanziell interessante Support-Angebote für Privatanwender existieren meines Wissens nach so gut wie nicht.

FLOSS lebt vom Mitmachen, nicht vom Meckern

Freie Software wird meist unentgeltlich zur Nutzung angeboten. Diese wird nicht selten von Freiwilligen in deren Freizeit geschaffen. Auch Unternehmen, welche der Gemeinschaft etwas zurückgeben möchten, beschäftigen Entwickler, die einen Teil ihrer Arbeitszeit an Open Source Software arbeiten können.

Fehler werden höchstwahrscheinlich nicht mit Absicht eingebaut. Und nicht jeder erdenkliche Anwendungsfall wird von Beginn an in der Entwicklung berücksichtigt. Darüber zu meckern und Forderungen für etwas zu stellen, was man kostenlos nutzen darf, hat bisher in den seltensten Fällen geholfen.

Hat man Wünsche den Funktionsumfang einer Anwendung betreffend, kann man diese an das jeweilige Projekt richten. Liest man zuvor die sog. Contribution guidelines (zu Deutsch in etwa: Beitragsleitlinie), erhöht dies die Chancen, dass ein Beitrag Berücksichtigung findet.

Unterstützung und Hilfe ist an allen Ecken und Enden des FLOSS-Universums von Nöten und oft herzlich willkommen. Dabei muss man kein Software-Entwickler sein. Denn oft mangelt es an Dingen, die mit dem Code nicht viel zu tun haben. So kann man zum Beispiel:

  • Dokumentationen schreiben, erweitern und verbessern
  • Dokumentationen in andere Sprachen übersetzen
  • Nutzern in Internetforen und auf Maillinglisten bei der Lösung ihrer Probleme helfen
  • Fehlerbilder verifizieren und Patches testen

FLOSS ist Software von der Gemeinschaft für die Gemeinschaft. Bring dich ein, mach mit!

Ein (paar) Wort(e) an Entwickler und Paket-Betreuer

Ihr habt zum Teil großartige Anwendungen geschaffen und stellt sie der Gemeinschaft zur Verfügung. Ihr seid auf Hilfe angewiesen und braucht/sucht Nachwuchs, der bereit ist, zu lernen, wie man Software erstellt, pflegt, pakettiert und verteilt? Dann denkt bitte daran, dass jeder mal klein anfängt und man dem Nachwuchs aufs Pferd helfen muss, bevor dieser losreiten kann.

Zum Teil habt ihr rund um eure Software Ökosysteme aus Versionskontrollsystemen, Build-Umgebungen, CI/CD und Kommunikationskanäle geschaffen, die für Anfänger und technisch interessierte Laien nur schwer zu durchdringen sind. Wer sich bei der Beantwortung der Frage, wie man ein Distributions-Paket betreuen kann, tagelang durch verschiedenste Wiki-Seiten und gefühlt das halbe Internet gewühlt hat, gibt danach oft frustriert auf.

Ich habe kein Patentrezept, wie man es optimal gestalten kann. Doch klafft IMHO zwischen Tutorials wie „Wie baut man ein {DEB,RPM}-Paket“ und „So baut und betreut man Pakete für Distribution XY“ eine große Lücke, durch welche potenzieller Nachwuchs durchfällt.

Hier ist eventuell eine Diskussion innerhalb der einzelnen Communities notwendig, wie der Prozess der Nachwuchsgewinnung verbessert werden kann.

Oder habe ich hier ein falsches Bild von der FLOSS-Welt und es gibt kein Nachwuchsproblem, weil man sich vor neuen Paketbetreuern kaum retten kann?

Was haben Unternehmen und Behörden von FLOSS?

TL;DR: Mehr Souveränität. Keine starke Abhängigkeit von einem einzelnen Anbieter. Und Freiheit.

Ich habe in vorstehendem Absatz ganz bewusst auf Begriffe wie „kostenlos“, „unentgeltlich“ und „Kostenreduzierung“ verzichtet. In meinen Augen greift die Reduzierung von FLOSS auf vermeintliche Kostenvorteile zu kurz und ist nicht selten mit ein Grund für das Scheitern von Migrationsprojekten hin zu FLOSS. Statt dessen möchte ich in diesem Beitrag Aspekte hervorheben, die IMHO häufig zu kurz kommen.

Dazu beginne ich mit einem Beispiel aus der Closed Source Welt. Es wird ein Produkt wie zum Beispiel ein Betriebssystem oder eine Anwendung eines proprietären Herstellers erworben und in die eigenen Geschäftsprozesse integriert. Nicht selten zahlt man einmal für die Lizenz, um das Produkt überhaupt nutzen zu dürfen und darüber hinaus für ein Abonnement, über welches man Updates, Sicherheits-Patches und Unterstützung durch den Hersteller-Support bekommt. Der Hersteller kann beliebig darüber entscheiden, wie lange er ein Produkt unterstützt und wann er es abkündigt, so dass der Kunde ggf. ein Nachfolgeprodukt erneut kaufen muss. Wenn es ganz dumm läuft, stellt der Anbieter ein Produkt komplett ein, ohne dass es ein Nachfolgeprodukt gibt. Als Kunde guckt man dann halt in die Röhre und kann sich erneut auf die Suche nach einem Produkt machen, das man ggf. unter Anpassung der eigenen Prozesse integriert. Damit einher geht häufig die Anpassung weiterer Systeme und Prozesse, sowie der Austausch von Client-Anwendungen und Anwenderschulungen.

Die schlechte Nachricht ist, dies alles kann beim Einsatz von FLOSS ebenfalls passieren. Doch gibt es bei FLOSS noch eine weitere Option, die sich als vorteilhaft erweisen kann. Auch dazu möchte ich euch ein Beispiel geben.

Angenommen es wird eine Software genutzt, die ein engagierter FLOSS-Entwickler als Hobby-Projekt in seiner Freizeit erstellt hat. Die Software besitzt ausschließlich Abhängigkeiten zu anderen FLOSS-Technologien und deckt alle Anforderung des Unternehmens bzw. der Behörde ab. Die Nutzung ist unbeschränkt und kostenlos möglich. Mittlerweile ist die Anwendung tief in die eigenen Prozesse integriert und elementarer Bestandteil der Wertschöpfungskette. Alle sind glücklich und alle sind froh.

Doch dann endet eines Jahres die Unterstützung für eine FLOSS-Technologie von der diese Anwendung abhängt. Es gibt ein Major-Release-Upgrade für diese Technologie. Die FLOSS-Anwendung muss jedoch angepasst werden, um weiterhin lauffähig zu sein.

Nun kann man den bzw. die Entwickler der Anwendung ganz lieb fragen, ob sie die notwendigen Anpassungen vornehmen mögen. Vielleicht hat man Glück und dies geschieht innerhalb weniger Tage. Vielleicht hat man auch Pech und sie haben einfach keine Lust.

Wenn es an der Motivation fehlt, kann man auf die verrückte Idee kommen und den Entwicklern anbieten, sie für die notwendigen Anpassungen zu bezahlen und einen Preis mit ihnen aushandeln. Für mich liegt dieser Gedanke nahe, würde man einen proprietären Hersteller doch auch bezahlen. Und das häufig sogar für Änderungen, die man gar nicht wollte/brauchte.

Nun kann es durchaus immer noch passieren, dass der/die Entwickler das Angebot ablehnen. Sie haben einfach keine Lust, sich weiterhin um ihre alte Anwendung zu kümmern. Was bleibt nun übrig, außer eine Markterkundung durchzuführen, eine Alternative zu eruieren und Himmel und Hölle in Bewegung zu setzen, um diese zu implementieren?

Halt! Stopp! Es gibt noch eine weitere Alternative. Die Anwendung ist quell-offen und der Quelltext liegt euch vor. Die Anwendung kann jederzeit aus diesem neu erstellt werden und ihr habt das Recht, beliebige Anpassungen am Quelltext vorzunehmen. Wenn euch die Anwendung wichtig genug ist, hindert euch nichts und niemand daran, eigene Entwickler einzustellen, welche den Quelltext studieren und notwendige Anpassungen vornehmen. Und da ihr diese Entwickler selbst bezahlt, könnt ihr sie auch mit Priorität an euren Wunsch-Funktionen arbeiten lassen.

Jetzt wurde auch schon deutlich, warum ich das Argument, FLOSS sei kostenlos bzw. günstig, doof finde. Es trifft nicht zu. Spätestens wenn ich eigene Entwickler beschäftige und hoffentlich auch bezahle, kostet dies ebenfalls Geld; nur investiert man das Geld hierbei in eigene Ressourcen. Ähnlich ist es, wenn man sich Funktionen im Auftrag entwickeln lässt. Nur behält man hierbei die Souveränität über die Software, im Gegensatz zum Produkt eines proprietären Anbieters.

Selbstverständlich mag dies nicht in jedem Fall möglich sein. Doch in vielen Fällen ist dies ein gangbarer Weg und einer der großen Vorteile des FLOSS-Entwicklungsmodells. Ein weiterer Vorteil besteht darin, dass man nicht die gesamte Entwicklungsarbeit allein bewältigen muss. Die Last kann auf viele Schultern weltweit verteilt werden. So arbeiten Entwickler aus verschiedensten Branchen mit am Linux-Kernel. Gleiches gilt für den BSD-Kern und unzählige andere Projekte.

Wer hilft wenn’s klemmt?

Grundsätzlich stehen die gleichen Optionen zur Verfügung, die auch Privatnutzern offen stehen. Darüber hinaus bietet sich häufig die Möglichkeit, Support-Verträge mit Herstellern oder Systemhäusern abzuschließen.

So bieten z.B. Red Hat, SUSE, Canonical und Oracle verschiedene Support-Optionen für das jeweilige Portfolio an. Darüber hinaus haben sich auch im deutschsprachigen Raum einige Firmen etabliert, welche Support-Dienstleistungen für vielfältige FLOSS-Projekte/Produkte anbieten.

Diese Firmen verdienen nicht nur Geld mit Dienstleistungen rund um FLOSS. Sie beteiligen sich häufig mit eigenem Personal und/oder finanziell an der Weiterentwicklung diverser Projekte.

Die Qualität des Supports ist meiner Erfahrung nach mit dem proprietärer Anbieter vergleichbar. Das gilt sowohl im positiven wie negativen Sinne.

Nutzt einfach die Suchmaschine eures geringsten Misstrauens und ihr werdet bestimmt einen passenden Dienstleister finden.

Auch hier gilt, nicht meckern, mitmachen!

Ich möchte mich wiederholen: „FLOSS ist Software von der Gemeinschaft für die Gemeinschaft. Bring dich ein, mach mit!“

Dies sollte in meinen Augen besonders für Behörden und Organisationen gelten, die den Betrieb und die Entwicklung ihrer Anwendungen mit dem Steuergeld von Bürgerinnen und Bürgern finanzieren. Deshalb unterstütze ich die Kampagne „Public Money, Public Code“. Innovationen und Investitionen in Freie Software verschwinden nicht hinter verschlossenen Türen zum Nutzen Weniger; statt dessen können alle Nutzer davon profitieren. So z.B. auch Bürgerinnen und Bürger, die daheim evtl. die gleichen FLOSS-Anwendungen nutzen, die auch der Staat nutzt und mit weiterentwickelt.

Bisher ist vieles davon noch bloße Utopie. Scheitert es doch im öffentlichen Dienst schon oft genug daran, an Open Source Projekte zu spenden. Geld für Berater-Verträge auszugeben ist da schon einfacher möglich. Doch auch auf diesem Weg kann man ja FLOSS-Projekte unterstützen. Ich glaube da wo ein Wille ist, ist auch ein Weg.

Schlussworte

Freie Software und Open Source Software sind frei im Sinne von:

  • Der Quelltext liegt offen vor und kann von jedem Menschen eingesehen, studiert und weitergegeben werden.
  • Jeder Mensch hat das Recht den Quelltext zu verändern.
  • Die Verwendung der Software ist in keiner Weise beschränkt.

Wer einfach nur seine Arbeit erledigen möchte, mag dabei mit FLOSS-Software genau so viel Glück oder Pech wie mit proprietärer Software haben. FLOSS bietet hingegen Souveränität und Freiheit; mit allen Vor- und Nachteilen, die das mit sich bringen mag. Technisch interessierte Menschen können sich mit ihr vertraut machen, dazulernen und Teil einer Gemeinschaft werden.

Ich mag FLOSS und glaube Open Source Entwicklungsmodelle sind auch in Zukunft nicht mehr aus unserer Welt wegzudenken.

My 2 Cents on CentOS

16. Dezember 2020 um 20:00

In den letzten Tagen dreht sich meine Internet-Blase zu einem großen Teil rund um das nahende Ende von CentOS-Linux. Um nicht in mehreren Blogs die gleichen oder ähnliche Kommentare zu hinterlassen, habe ich mich entschieden, in diesem einen Artikel meinen Senf dazu zugeben.

Aus Transparenzgründen weise ich ausdrücklich darauf hin, dass ich Mitglied der Red Hat Accelerators bin (siehe „Zu meiner Person„). Meine Meinung ist jedoch grundsätzlich meine eigene. Diese kann mit den Ansichten von Red Hat übereinstimmen, muss es aber nicht und tut es auch nicht immer.

Die Meldungen, dass das Ende von CentOS Linux naht, haben mich weder überrascht, noch enttäuscht. Überrascht bin ich nicht, da ich mich schon bei der Ankündigung von CentOS Stream gefragt habe, wie lange beide Projekte parallel existieren können bzw. wann Red Hat die Unterstützung des einen Projekts zu Gunsten des anderen beendet. Und um enttäuscht zu sein, habe ich CentOS nicht lange genug verwendet und mich nicht in der Gemeinschaft organisiert. Freuen tut es mich allerdings auch nicht, wenn ein so robustes Projekt ein Ende hat.

Ziemlich unglücklich fand ich die Kommunikation durch Red Hat. Dabei ist denke ich mehr Porzellan kaputt gegangen, als nötig war. So ist es wenig verwunderlich, dass die CentOS-Community aufgebracht ist und sich in den Kommentarspalten in Rage schreibt.

So ist die Rede davon, dass Red Hat auf Weisung von IBM bei CentOS das Licht ausgemacht hat; dass CentOS auf dem Altar der Kommerzialisierung geopfert wird, um die Profite von Red Hat und IBM zu steigern. Ja, man könnte fast meinen, die Welt geht unter. Ich finde, das ist alles Quatsch.

Zumal ich nicht glaube, dass Nutzer des kostenlosen CentOS jetzt alle RHEL-Subkriptionen kaufen werden. Für viel wahrscheinlicher halte ich es, dass sich diese Nutzer den zukünftigen kostenlosen RHEL-Klonen zuwenden oder zu anderen kostenlosen Linux-Distributionen wechseln werden.

In meiner Wahrnehmung hat Red Hat bisher seine Eigenständigkeit nach dem Kauf durch IBM behalten. Ob IBM etwas mit der Entscheidung zu tun hatte, weiß ich nicht. Glauben tue ich es jedenfalls nicht. Letztendlich hat das CentOS-Projekt im hauseigenen Blog bekannt gegeben, den Fokus auf CentOS Stream zu verlagern. Übrigens sind nur 4 von 10 Sitzen im CentOS Governing Board von Red Hattern besetzt.

Etliche Kommentare hinterlassen bei mir den Eindruck, die dazugehörigen Autoren würden glauben, sie hätten ein Recht auf kostenlose Software der Enterprise-Klasse. Dabei beinhaltet Open Source nach meinem Verständnis die Freiheit der Quelltexte und das Recht, aus diesen ausführbare Programme zu erstellen. Eine Pflicht, dass ein Unternehmen für den ganzen Spaß bezahlt und diese Aufgabe für mich übernimmt, kann ich hingegen nicht daraus ableiten. Von daher kann ich die Empörung nur teilweise nachvollziehen.

Dabei ist die Binärkompatibilität von CentOS, Oracle Linux, CloudLinux OS, Centos Stream und evtl. bald Rocky Linux zu RHEL doch auch ein Vorteil. Sollten sich Anwendungen, die auf einer dieser Distributionen laufen, sich doch selbst im Binärformat ohne großen Aufwand auf die jeweils anderen übertragen lassen. Ganz ehrlich, einen Wechsel von Debian zu OpenSUSE stelle ich mich schwieriger vor.

In meinen Augen stehen ausreichend gute und stabile Alternativen für Menschen zur Verfügung, die es sich nicht leisten können, für Enterprise-Software zu bezahlen.

Also CentOS, mach es gut. Es war schön mit dir. Mit deinen Nachfolgern wird es sicherlich auch wieder viel zu erleben geben.

Links und Quellen zum Thema

SSH ForwardAgent ja oder nein?

25. November 2020 um 07:00

In diesem Artikel möchte ich diskutieren, ob die Nutzung der SSH-Client-Option ForwardAgent sicher und sinnvoll ist. Wie so häufig bei Themen der IT-Sicherheit geht es auch hier um die Abwägung zwischen Sicherheit und Bequemlichkeit.

Der SSH-Agent nimmt den privaten SSH-Schlüssel auf und stellt diesen für SSH-Verbindungen bereit, so dass nicht bei jeder neuen SSH-Verbindung die Passphrase eingegeben werden muss.

Dabei wird ein UNIX-Socket erstellt und in der Variablen SSH_AUTH_SOCK gespeichert. Der folgende Code zeigt dies beispielhaft:

$ echo $SSH_AUTH_SOCK
/run/user/1000/keyring/ssh

In der ssh_config(5) findet sich die Option ForwardAgent, mit deren Hilfe der SSH-Agent auf einen entfernten Rechner weitergeleitet werden kann. Ist diese Funktionalität aktiv, kann man sich mit dem im SSH-Agenten gespeicherten privaten SSH-Schlüssel zu einem entfernten Rechner verbinden und von dort aus unter Nutzung des gleichen Schlüssels Verbindungen zu weiteren Rechnern aufbauen.

In den meisten Linux-Distributionen ist diese Option standardmäßig deaktiviert, da sie ein potenzielles Sicherheitsrisiko darstellt. Gelingt es einem Benutzer, die Dateiberechtigungen auf dem entfernten Rechner zu umgehen, kann er den lokalen Agenten benutzen, um Operationen durchzuführen, die nur mit dem im SSH-Agenten gespeicherten SSH-Schlüssel möglich sind. Ich möchte dies im Folgenden an einem Beispiel veranschaulichen.

Die Umgebung

Für den Versuch kommen die drei Linux-Rechner host-a, host-b und host-c zum Einsatz. Auf allen drei Hosts existiert der User foo, welcher mittels sudo zum root werden kann. Darüber hinaus existiert auf host-b User bar, welcher ebenfalls mittels sudo zum root werden darf.

Gezeigt wird, wie bar durch Wechsel in den Kontext des Users root die Dateiberechtigungen für den Unix-Socket des SSH-Agenten von foo umgehen kann, um mit dessen Informationen eine SSH-Verbindung zu host-c herzustellen, was ihm sonst nicht gestattet ist.

Der Versuchsablauf

In diesem Abschnitt wird der Ablauf wiedergegeben, der dazu führt, dass bar Zugriff als foo auf host-c bekommt.

host-a

Auf host-a existiert ein Unix-Socket für den SSH-Agenten. Der User foo nutzt diesen, um eine Verbindung zu host-b aufzubauen. Dabei wird die Option ForwardAgent aktiviert:

foo@host-a:~$ echo $SSH_AUTH_SOCK
/run/user/1000/keyring/ssh
foo@host-a:~$ ssh -o ForwardAgent=yes  host-b
[...]
foo@host-b:~$

host-b

Wir sind jetzt via SSH als User foo auf dem host-b eingeloggt. Da wir die Weiterleitung des SSH-Agenten aktiviert haben, existiert jetzt auch hier ein entsprechender Unix-Socket. Die Dateiberechtigungen sind so gesetzt, dass nur foo darauf zugreifen darf. Der folgende Codeblock veranschaulicht dies.

foo@host-b:~$ echo $SSH_AUTH_SOCK
/tmp/ssh-fxwQXNlZrS/agent.32579
foo@host-b:~$ ls -ld /tmp/ssh-fxwQXNlZrS
drwx------ 2 foo foo 4096 Nov 24 14:47 /tmp/ssh-fxwQXNlZrS
foo@host-b:~$ ls -l /tmp/ssh-fxwQXNlZrS/agent.32579
srwxr-xr-x 1 foo foo 0 Nov 24 14:47 /tmp/ssh-fxwQXNlZrS/agent.32579

Neben foo ist auch User bar auf host-b eingeloggt. Die Variable SSH_AUTH_SOCK dieses Users ist leer und bar wird beim Versuch, sich mit host-c zu verbinden, zur Eingabe eines Passworts aufgefordert.

bar@host-b:~$ echo $SSH_AUTH_SOCK

bar@host-b:~$ ssh foo@host-c
foo@host-c's password:

bar@host-b:~$ ls -l /tmp
drwx------ 2 foo   foo   4096 Nov 24 14:56 ssh-fxwQXNlZrS
bar@host-b:~$ ls -l /tmp/ssh-fxwQXNlZrS
ls: cannot open directory '/tmp/ssh-fxwQXNlZrS/': Permission denied

Da bar das Kennwort von foo unbekannt ist, geht es auf diesem Weg nicht weiter. Jedoch kann bar erkennen, dass auf dem System ein Unix-Socket mit einem SSH-Agenten für foo existiert. Der nun folgende Codeblock zeigt, wie bar über einen Umweg den SSH-Agenten von foo nutzt, um sich mit host-c zu verbinden.

bar@host-b:~$ sudo -i
[sudo] password for bar:
root@host-b:~# ssh foo@host-c
foo@host-c's password:

root@host-b:~# SSH_AUTH_SOCK=/tmp/ssh-fxwQXNlZrS/agent.32579
root@host-b:~# export SSH_AUTH_SOCK
root@host-b:~# ssh foo@host-c
[...]
foo@host-c:~$

Der User bar hat es geschafft, sich als foo an host-c zu authentifizieren. Das ist foobar!

Schlussfolgerung

Der hier durchgeführte Versuch zeigt, dass die Option ForwardAgent ein Sicherheitsrisiko birgt, wenn es auf einem entfernten System Benutzer gibt, welche die Dateiberechtigungen, wie in diesem Artikel gezeigt, umgehen können.

Ich empfinde es daher als gut und sinnvoll, dass diese Option standardmäßig deaktiviert ist.

Kann man jedoch ausschließen, dass die Dateiberechtigungen umgangen werden, z. B. weil keine weiteren Nutzer auf dem entfernten Rechner existieren bzw. auf diesen zugreifen können, spricht in meinen Augen nichts dagegen, diese Option zu nutzen und sich den Alltag etwas komfortabler zu gestalten.

❌