Podman: Linux-Container einfach gemacht, Teil 2

Podman kann als root oder eben nicht ausgeführt werden: Das kommt nicht nur Benutzerfreundlichkeit und breiten Anwendungsmöglichkeiten, sondern auch der Sicherheit zugute.

In Pocket speichern vorlesen Druckansicht 5 Kommentare lesen
Podman: Linux-Container einfach gemacht, Teil 2

(Bild: stock.xchng)

Lesezeit: 22 Min.
Von
  • Valentin Rothberg
  • Daniel Walsh
Inhaltsverzeichnis

Nachdem der erste Teil der Artikelserie einen grundlegenden Überblick über Podman vermittelt hat, geht der zweite Teil auf verschiedene Sicherheitskonzepte von Podman und die Bausteine eines Containers ein. Praktische Beispiele sollen zeigen, wie sie in der Praxis Anwendung finden.

Das Podman-Logo

(Bild: Podman)

Oftmals verstehen Entwickler Container als einen Überbegriff für verschiedene Arten von Virtualisierungstechniken, die von Solaris Zones über virtuelle Maschinen wie Amazons Firecracker bis hin zu Windows-Containern reichen. In den meisten Fällen bezieht sich das Wort jedoch auf Linux-Container.

Mehr Infos

Im Grunde handelt es sich bei einem Linux-Container um eine Gruppe von Prozessen, die sich bestimmte Ressourcen teilen und in Beziehung zueinander stehen. Das klingt zunächst nach einem ganz normalen Linux-System und genau das möchte der viel verwendete Spruch "Containers are Linux" aussagen. Doch was unterscheidet einen Container nun von einem herkömmlichen Prozess eines Linux-Systems? Darauf gibt es viele Antworten, denn der Linux-Kern bietet eine Vielzahl von Mechanismen, um einen Container vom Rest des Systems zu isolieren, um Berechtigungen zu erteilen oder zu entziehen und um Ressourcen zuzuweisen, zu beschränken und zu multiplexen. Ähnlich wie einen Lego-Baukasten können Container-Tools wie Podman den Linux-Kern verwenden, um den Container den Wünschen und Anforderungen entsprechend zusammenzubauen. Der Rest des Artikels bietet nun einen Überblick über die wichtigsten Bausteine.

Das sogenannte Root File System (RootFS) ist das sichtbare Wurzelverzeichnis eines Prozesses und kann über unterschiedliche Systemaufrufe (zum Beispiel pivot_root(2)) verändert werden. Der Wechsel des Wurzelverzeichnisses ist ein altbewährtes Mittel und steht mit dem chroot(2)-Systemaufruf seit den 1970er-Jahren auf Unix-Systemen zur Verfügung. Das ist der wohl offensichtlichste Baustein eines Containers, da man sich durch ein neues RootFS auf einem scheinbar neuen System befindet. Das folgende Beispiel illustriert das genauer.

Zunächst laden Anwender das für Container verwendete RootFS von Alpine Linux 3.9.3 herunter, entpacken es und wechseln mit chroot(1) das Wurzelverzeichnis:

$ wget -q http://dl-cdn.alpinelinux.org/alpine/v3.9/releases/x86_64/alpine-minirootfs-3.9.3-x86_64.tar.gz
$ tar -xzf alpine-minirootfs-3.9.3-x86_64.tar.gz
$ sudo chroot `pwd` /bin/sh
$ cat /etc/os-release | head -n1
NAME="Alpine Linux"
$ ls /
alpine-minirootfs-3.9.3-x86_64.tar.gz media sbin
bin mnt srv
dev opt sys
etc proc tmp
home root usr
lib run var

Das Dateisystem lässt augenscheinlich darauf schließen, dass man sich auf einem Alpine Linux befindet. Nimmt man das System jedoch genauer unter die Lupe, fällt schnell auf, dass ein einfacher Wechsel des RootFS nicht vom Rest des Systems isolieren kann oder gar die Ressourcen beschränkt. Beispielsweise sind alle alten Prozesse nach wie vor sichtbar.

$ whoami
root
$ mount -t proc proc /proc
$ ps -eo user | sort -u
1000
172
193
root

Der Einsatz des RootFS bietet Nutzern also eine gewisse Portabilität, da sie beliebige Container-Images entpacken und deren Programme ausführen können. Um die Ausführung abzusichern, sind jedoch etwas größere Geschütze notwendig.

Namespaces dienen der Isolation von systemweiten Ressourcen. Prozesse innerhalb eines Namespace haben eine andere Sicht und scheinbar eigene Instanzen der Ressourcen. Dabei bietet Linux verschiedene Arten von Namespaces an. Ein beliebtes Anwendungsbeispiel ist der PID Namespace, wodurch über mehrere Namespaces die gleiche Prozess-ID (PID) mehrfach vergeben werden kann. Dadurch hat zum Beispiel jeder Container einen eigenen Init-Prozess mit der PID 1.

Namespaces können Entwickler mit unshare(1) verlassen beziehungsweise erstellen, um zum Beispiel in einen neuen PID Namespace zu wechseln, welcher von Prozessen außerhalb des Namespace isoliert ist und damit keine Sicht auf sie hat.

$ sudo unshare --fork --pid --mount-proc
$ ps
PID TTY TIME CMD
96 pts/27 00:00:00 bash
142 pts/27 00:00:00 ps

Insgesamt gibt es sieben Namespaces, um neben den PIDs auch den Netzwerk-Stack, den Hostnamen, die Mountpoints, Inter-Prozess-Kommunikation (zum Beispiel POSIX Message Queues) und weitere Ressourcen isolieren zu können.

In manchen Anwendungsfällen müssen sich Container bestimmte Ressourcen und damit die zugrunde liegenden Namespaces teilen. Dafür bietet Podman entsprechende Optionen an. Zum Beispiel kann ein Container dem Network Namespace eines anderen Containers mit podman run --network=container:name/id beitreten.

User Namespaces verdienen besondere Erwähnung, da deren Verwendung sowohl der Sicherheit als auch der Portabilität dient. User Namespaces erlauben es, die User ID (UID) und Group ID (GID) innerhalb des Containers neu zuzuordnen. Damit sind die UID und GID innerhalb des Containers eine andere als außerhalb. Wie dient das der Sicherheit?

Um das zu erläutern, erstellt man zunächst eine Datei, die Anwender ausschließlich mit Root-Zugriff lesen und schreiben dürfen.

$ sudo bash -c "echo Heise > /tmp/heise.txt"
$ sudo chmod 600 /tmp/heise.txt
$ sudo ls -l /tmp/heise.txt
-rw-------. 1 root root 6 May 2 13:52 /tmp/heise.txt

Nun mountet man die zuvor erstellte Datei in einen neuen Container und User Namespace.

$ sudo podman run -it -v /tmp/heise.txt:/tmp/heise.txt:Z --uidmap 0:100000:5000 alpine sh
/ # whoami
root
/ # ls -l /tmp/heise.txt
-rw------- 1 nobody nobody 6 May 2 11:52 /tmp/heise.txt
/ # cat /tmp/heise.txt
cat: can't open '/tmp/heise.txt': Permission denied

Hier gibt es ein paar Sachen zu verdauen, angefangen beim Aufruf von Podman. Die Option --uidmap 0:100000:5000 instruiert Podman, einen neuen User Namespace für den Container mit der Zuordnung 0:100000:5000 anzulegen. Die Zuordnung legt fest, dass ab der Host UID 100000 insgesamt 5000 UIDs dem Container zugeordnet werden, beginnend bei UID 0. Damit ist die UID 1 innerhalb des Containers die UID 100001 außerhalb. Wie im whoami-Aufruf zu sehen, hat man trotz Aufenthalts innerhalb des Containers root und dennoch keinen Zugriff auf die /tmp/heise.txt-Datei. Das liegt daran, dass Linux jedes Objekt einer UID die nicht in dem User Namespace zugeordnet ist als UID "nobody" betrachtet. Damit hat root innerhalb des Containers und damit innerhalb des User Namespace keinen Zugriff auf die gemountete Datei.

Am Beispiel lassen sich die zwei Eigenschaften von User Namespaces ableiten. Zum einen gewinnen Nutzer an Sicherheit, da der Root-Container-Prozess auf dem Host keine Root-Rechte innehat und selbst bei Ausbruch aus dem Container nur begrenzt Schaden anrichten kann. Zum anderen gewinnt man an Portabilität, da viele Anwendungen voraussetzen, root ausgeführt zu werden. Das ist damit nach wie vor möglich – nur wesentlich sicherer.

Control Groups oder kurz Cgroups sind ein Mechanismus des Linux-Kerns, um Gruppen von Prozessen hierarchisch zu organisieren und deren Ressourcen zu limitieren und zu überwachen. Cgroups umfasst verschiedene Ressourcen wie den Arbeitsspeicher, CPU-Nutzung, Netzwerk, die Anzahl von Prozessen und vieles andere mehr. Prozesse innerhalb einer Cgroup unterliegen den gleichen Bedingungen, zum Beispiel einer maximalen Arbeitsspeichernutzung von 4 GByte. Die hierarchische Struktur ermöglicht eine feinere Verteilung der Ressourcen, sodass Prozesse in Gruppe A mehr relative CPU-Zeit bekommen als in Gruppe B.

Podman bietet einige Optionen über die Podman-API und über die Kommandozeile an, um mit Cgroups die Ressourcen eines Containers zu kontrollieren: Zum Beispiel --cpu-count=n, um die Anzahl der zur Verfügung stehenden CPUs auf n zu beschränken, oder --memory für den zur Verfügung stehenden Arbeitsspeicher.

Während Namespaces die Ressourcen und deren Sichtbarkeit isolieren, können Anwender mit Cgroups die zur Verfügung stehenden Ressourcen weiter limitieren, kontrollieren und zuweisen. Für die Sicherheit eines Containers ist das Zusammenspiel von Namespaces und Cgroups der springende Punkt. So kann ein kompromittierter Container nur begrenzt Schaden anrichten, da bestimmte Ressourcen gar nicht zur Verfügung stehen (zum Beispiel laufende Prozesse oder Benutzer außerhalb des Containers) und die zur Verfügung stehende Ressourcen begrenzt sind.

Ein berühmtes Angriffsszenario, um einen laufenden Dienst, zum Beispiel einen Webserver, in die Knie zu zwingen, ist die sogenannte Forkbomb. Sobald ein Angreifer die Kontrolle über einen Prozess gewonnen hat, versucht er so viele Kopien des Prozesses wie möglich anzufertigen, um alle Systemressourcen zu verbrauchen und somit das System zu blockieren. Mit Cgroups ist eine Forkbomb nicht möglich, da die maximale Anzahl an Prozessen innerhalb eines Containers stets begrenzt ist.

Capabilities sind ein rechtebasiertes Sicherheitskonzept von Linux. Die Capabilities (Fähigkeiten) eines Prozesses können Leser sich als eine Liste von Befugnissen vorstellen, die bestimmt, ob ein Prozess eine bestimmte Operation ausführen darf oder auf bestimmte Ressourcen zugreifen kann.

Vor Linux 2.2 gab es zwei Klassen von Prozessen: privilegierte Prozesse mit der User ID von 0 und nicht privilegierte Prozesse. Doch diese "Alles oder nichts"-Einteilung schlägt schnell an ihre Grenzen, da ein ordentliches, rechtebasiertes Sicherheitskonzept eine feingranulare Verteilung von Befugnissen bedarf. So soll ein bestimmter Benutzer zum Beispiel auf den Drucker zugreifen dürfen, aber nicht die Konten anderer Benutzer löschen können.

Capabilities spielen für die Sicherheit eines Containers eine entscheidende Rolle, da dadurch die Befugnisse eines Containers start beschränkt werden können, um den potenziellen Schaden eines kompromittierten Containers noch weiter einzudämmen. Standardmäßig setzt Podman nur 14 der knapp 40 Capabilities ein, die man bequem über --cap-add hinzufügen oder --cap-drop entfernen kann. Zum Beispiel ist die SYS_NICE-Capability nicht gesetzt, sodass ein Prozess die Prioritäten nicht erhöhen kann.

$ sudo podman run alpine nice -n -20 echo "Hallo Heise"
nice: setpriority(-20): Permission denied

Mit der --cap-add-Optionen können Entwickler dem Container die Befugnis zuweisen.

$ sudo podman run --cap-add SYS_NICE fedora nice -n -20 echo "Hallo Heise"

SECCOMP ist ein weiterer Sicherheitsmechanismus des Linux-Kerns, um festzulegen, welche Systemaufrufe ein Prozess verwenden darf. SECCOMP ist ebenso mächtig und effektiv wie komplex, da es in vielen Fällen nicht trivial und schon gar nicht offensichtlich ist, welche Systemaufrufe ein bestimmter Container und dessen Anwendung benötigt. Der Filtermechanismus von SECCOMP ist feingranular und erlaubt es, Systemaufrufe nach Namen beziehungsweise nach Nummern zu blockieren, nach bestimmten Argumenten, der Prozessorarchitektur und weiteren Eigenschaften. Viele Projekte wie Firefox, Chromium und OpenSSH greifen direkt auf SECCOMP zurück, um sich vor Angriffen zu schützen beziehungsweise um den potenziellen Schaden eines Angriffs einzudämmen.

Die meisten Container-Tools wie Docker und Podman, verwenden ein Whitelist-Profil, das festlegt, welche Systemaufrufe aufgerufen werden dürfen. Alle nicht genannten Aufrufe sind damit verboten. Dieses Standardprofil entspringt der Feder von Jessie Frazelle, einer Maintainerin des Docker-Projekts, und ist einer Herkules-Aufgabe gleichzusetzen – schließlich sollen möglichst alle Programme innerhalb eines Containers lauffähig bleiben und doch so viele Systemaufrufe wie möglich blockiert werden.

Bei Bedarf können Anwender ein eigenes SECCOMP-Profil im JSON-Format erstellen. Das folgende Beispiel erlaubt alle Systemaufrufe außer mkdir(2), sodass man keine neuen Verzeichnisse mehr anlegen kann.

$ cat seccomp.json
{
"defaultAction": "SCMP_ACT_ALLOW",
"architectures": [
"SCMP_ARCH_X86_64"
],
"syscalls": [
{
"names": [
"mkdir"
],
"action": "SCMP_ACT_ERRNO"
}
]
}
$ podman run --security-opt seccomp=seccomp.json alpine mkdir /neuesVerzeichnis
mkdir: can't create directory '/neuesVerzeichnis': Operation not permitted

Das obige Beispiel soll selbstverständlich lediglich SECCOMP demonstrieren. Aus Sicherheitsgründen sollte man stets Whitelist-Profile verwenden, die genau festlegen, welche Systemaufrufe erlaubt sind. Damit bleibt das Profil portabel, da die Anzahl der Systemaufrufe mit nahezu jeder neuen Version von Linux wächst. Momentan ist die Erstellung eines solchen Profils mit viel Handarbeit verbunden und damit fehleranfällig und für viele Anwender nicht umsetzbar.

Dessen sind sich die Podman-Entwickler durchaus bewusst und beteiligen sich deshalb am Google Summer of Code 2019. Sie arbeiten zusammen mit Studenten an einer Funktion, die dafür sorgen soll, dass Podman die Systemaufrufe innerhalb eines Containers mitliest, um anschließend ein passendes Profil zu generieren. Damit können Benutzer komfortabel auf Anwendungen spezialisierte SECCOMP-Profile generieren, um die Container noch weiter abzuriegeln.

Das Linux Security Module (LSM) ist ein Framework des Linux-Kerns, um verschiedene Sicherheitsmodelle zu unterstützen. Im Kontext von Containern spielen SELinux und AppArmor eine entscheidende Rolle. Abhängig von der Linux-Distribution wird in der Regel entweder SELinux (zum Beispiel auf Fedora) oder AppArmor (zum Beispiel auf Ubuntu) eingesetzt, um die Zwiebelschale an Sicherheitsmechanismen noch weiter zu vergrößern. In beiden Fällen handelt es sich um Zugriffskontrollen, die genau festlegen können, welcher Prozess mit welchen Rechten auf bestimmte Ressourcen, zum Beispiel auf ein Verzeichnis oder eine Datei, zugreifen kann.

Eine genaue Beschreibung von SELinux und AppArmor und wie sie im Kontext von Containern Verwendung finden, werden hier nur der Vollständigkeit halber erwähnt. Beide Module sind jedoch hinreichend komplex, um deren Konfiguration den jeweiligen Spezialisten der Linux-Distributionen zu überlassen. Podman unterstützt wie Docker sowohl AppArmor als auch SELinux.

Wie in (LB2616181:Teil 1 der Artikelserie) beschrieben, ist Podman besonders bekannt für die Rootless-Unterstützung, also das Ausführen von Containern, ohne Root-Rechte zu besitzen. Ein klassischer Anwendungsfall dafür ist ein Universitätslabor, in welchem Studenten aus Sicherheitsgründen keine Root-Rechte besitzen dürfen. Mit Podman können Studenten dennoch Container ausführen und ihrer Arbeit nachgehen. Das klingt zunächst nach einer Kleinigkeit, doch hinderte es für lange Zeit die Verbreitung und Anwendung von Containern in vielen Umgebungen.

User Namespaces spielen hierbei eine zentrale Rolle – da der Artikel sie bereits genauer beleuchtet hat, kann man Rootless-Podman nun am Beispiel von Fedora genauer betrachten. Wie ist das System genau konfiguriert und welche Teile spielen zusammen, um Rootless-Podman möglichst benutzerfreundlich zu halten?

Zeitgemäße Linux-Distributionen, wie das vor kurzem veröffentlichte Fedora 30, kommen mit einer Version von shadow-utils, die auf die /etc/subuid und /etc/subgid zurückgreift. Die beiden Dateien werden verwendet um herauszufinden, welche UIDs und GIDs Benutzern in einem User Namespace zur Verfügung stehen.

$ cat /etc/subuid /etc/subgid
valentin:100000:65536
valentin:100000:65536

Das Programm useradd(8) fügt für jeden neuen Benutzer einen Eintrag in die beiden Dateien ein. Sofern nicht auf der Kommandozeile weiter angegeben, verwendet Podman /etc/subuid und /etc/subgid für die Zuordnung von UIDs und GIDs von Host und Container User Namespace.

$ id -u
1000
$ podman run alpine cat /proc/self/uid_map
0 1000 1
1 100000 65536

Das obige Beispiel zeigt, dass der Host Benutzer mit der UID 1000 die UID 0 innerhalb des Containers hat. Die folgenden 65536 werden beginnend ab Host UID 100000 der Container UID 1 ff. entsprechend zugewiesen.

Ein wichtiger Punkt beim Einsatz von Rootless-Podman fand bisher noch keine Erwähnung: die Berechtigungen des Dateisystems. Alle Dateien und Verzeichnisse von Root eines Container-Images müssen schließlich dem Root innerhalb des User Namespace gehören. Andernfalls gelten sie als zu "nobody" gehörig und Anwender hätten keinerlei Zugriff. Die github.com/containers/storage-Bibliothek, auf der Podman aufbaut, unterstützt momentan zwei rootless-storage-Treiber, vfs und Overlay. Im Vergleich zu Overlay ist vfs langsam und speicherhungrig, da das gesamte RootFS für das Ausführen des Containers kopiert und die Berechtigungen angepasst werden müssen. Overlay ist wesentlich performanter, setzt für rootless aber voraus, dass das Programm fuse-overlayfs installiert ist.

Linux hat ein weiteres Sicherheitskonzept, das das Herz eines jeden Administrators höher schlagen lässt: das Audit-Subsystem. Audit erlaubt es, über bestimmte Ereignisse auf dem System genau Buch zu führen, um nachzuvollziehen, welche sicherheitsrelevanten Aktivitäten von welchem Benutzer zu einem bestimmten Zeitpunkt ausgeführt wurden. Audit ist hinreichend umfangreich und komplex, um eine Artikelserie nur diesem Thema zu widmen. Für die Zwecke des Artikels genügt es zu wissen, dass Audit ein zentraler Bestandteil vieler Linux-Systeme und beliebtes Mittel von Administratoren ist. Darüber hinaus setzen viele Sicherheitszertifizierungen Audit voraus. Es ist aus dem Alltag nicht mehr wegzudenken.

Bei jedem Login eines Benutzers weist Audit dem Prozess eine eindeutige ID zu, die man über das /proc-Dateisystem einsehen kann.

$ cat /proc/self/loginuid
1000

Eine wichtige Eigenschaft der LoginUID ist, dass sie auch allen Kindprozessen zugewiesen wird, selbst wenn sie als Root laufen.

$ sudo cat /proc/self/loginuid
1000

Die Eindeutigkeit der LoginUID und deren Unveränderbarkeit nach dem Login ist die Kerneigenschaft von Audit, denn damit können Anwender genau nachvollziehen, welche Aktivität von welchem Benutzer ausging.

Genau hier spielt die Architektur von Podman eine große Rolle. Wie im Teil 1 der Artikelserie beschrieben, setzt Podman auf eine klassische Fork-Exec-Architektur, wodurch jeder Container ein Kind-Prozess von Podman ist.

$ sudo podman run alpine cat /proc/self/loginuid
1000
$ sudo docker run alpine cat /proc/self/loginuid
4294967295

Im Beispiel hat der Docker-Container eine LoginUID von 4294967295, obwohl der ausführende Benutzer eine ID von 1000 hat. Grund dafür ist die Client-Server-Architektur von Docker. Der Docker-Client selbst wird mit der ID von 1000 ausgeführt, jedoch kommuniziert er über einen Unix-Socket mit dem Docker-Daemon, den wiederum Systemd gestartet hat.

$ sudo cat /proc/1/loginuid
4294967295

Damit erbt der Docker-Container die LoginUID von Systemd und kann sich somit dem Audit-System teilweise entziehen. Über Aktivitäten wird zwar nach wie vor Buch geführt, jedoch wissen Entwickler nicht, von welchem Benutzer sie ausgingen. Es folgt ein praktisches Beispiel.

Zunächst befiehlt man Audit, die /etc/shadow-Datei zu überwachen und führt einen Docker-Container aus, der die Datei mountet und den Zeitstempel verändert.

$ sudo auditctl -w /etc/shadow
$ sudo docker run -v /etc:/etc alpine touch /etc/shadow
$ sudo ausearch -f /etc/shadow -i
type=SYSCALL msg=audit(05/01/2019 14:23:14.322:1819) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffff9c a1=0x7ffd81a2bf55 a2=O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK a3=0x1b6 items=2 ppid=19876 pid=19895 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=touch exe=/usr/bin/touch subj=system_u:system_r:spc_t:s0 key=(null)

Die Ausgabe listet viele Details, wobei auid=unset die relevante Information ist. Audit ist nicht in der Lage, die Aktivität einer LoginUID zu bestimmen, da Systemd zum Systemstart als Prozess 1 ausgeführt wird und damit keine LoginUID zugewiesen bekommt.

$ sudo podman run -v /etc:/etc alpine touch /etc/shadow
$ sudo ausearch -f /etc/shadow -i
type=SYSCALL msg=audit(05/01/2019 14:23:17.353:1823) : arch=x86_64 syscall=openat success=yes exit=4 a0=0xffffff9c a1=0x7fec7a334181 a2=O_RDONLY|O_CLOEXEC a3=0x0 items=1 ppid=19984 pid=19986 auid=valentin uid=root gid=valentin euid=root suid=root fsuid=root egid=valentin sgid=valentin fsgid=valentin tty=pts19 ses=3 comm=unix_chkpwd
exe=/usr/sbin/unix_chkpwd subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)

Das Ausführen mit Podman liefert das gewünschte Ergebnis und zeigt eindeutig, von welchem Benutzer die Aktivität ausging (siehe auid=valentin): eines von vielen Beispielen der Vorteile von Podmans Fork-Exec-Architektur.

Die Podman-Entwickler pflegen den Satz "Containers are Linux". Dieser Teil des Artikels hat genauer beleuchtet, was hinter dem Satz steckt, denn Linux kennt als solches keinen Container. Ein Container ist vielmehr ein herkömmlicher Prozess auf dem System mit einem bestimmten RootFS, was über viele Zwiebelschalen vom Rest des Systems abgeschottet wird, um Angreifern das Leben zu erschweren. Die Fork-Exec-Architektur von Podman unterstreicht das Credo, denn Podman ist ein herkömmlicher Prozess auf dem Linux-System und kann sowohl als Root als auch Nicht-Root ausgeführt werden und untersteht dem Audit-Subsystem. All das kommt nicht nur Benutzerfreundlichkeit und breiten Anwendungsmöglichkeiten, sondern auch der Sicherheit zugute.

Valentin Rothberg
ist Softwareentwickler in Red Hats Container-Runtimes-Team und arbeitet an Container-Tools wie CRI-O, Podman, Buildah und Skopeo und den zugrunde liegenden Techniken und Bibliotheken.

Daniel Walsh
ist seit mehr als 35 Jahren in der IT-Sicherheit tätig. Seit 2001 arbeitet Daniel bei Red Hat und leitet seit 2013 das Container-Engineering-Team, arbeitete aber schon Jahre zuvor an Container-Technologien und trug wesentlich zum Docker Open-Source Projekt bei. Seine Aufmerksamkeit gilt der CRI-O Container-Runtime für Kubernetes, Buildah zum Bauen von Container-Images, Podman, sowie den zugrundeliegenden Bibiliotheken. Zuvor leitete er das SELinux Projekt, und arbeitete an Secure Virtualization sowie an SELinux Sandbox, einem frühen Container-Tool für Desktops.
(bbo)