Sichere Kubernetes Cluster

arrow

Container und Kubernetes haben die Art und Weise, wie wir Software in Produktion bringen stark vereinfacht. Anwendungen lassen sich in Container Images verpacken und auf einem Kubernetes-Cluster mit mehreren Knoten betreiben. Bei all der Einfachheit sollte aber nicht vergessen werden, dass trotz der Kapselung in Container verschiedene Aspekte der Sicherheit noch immer eine wichtige Rolle spielen müssen.

Das ist unter anderem so, weil Container schlussendlich normale Prozesse sind, die auf einem Linux-Host laufen. Sie sind nicht virtualisiert, sondern nur isoliert. Erreicht wird das durch Funktionen des Linux Kernels zur Isolation von Prozessen, wie Kernel-Namespaces, Chroots, uid_map, gid_map oder cgroups. Dennoch verwenden Container, trotz Isolation, direkt den Kernel des Hosts. Sollte der in einem Container ausgeführte Code also bösartig oder kompromittiert worden sein, könnte er zum Beispiel Schwachstellen des Kernels ausnutzen, um sich mehr Privilegien als erlaubt zu verschaffen.

Ein Container ist aber auch eine Applikation, die zusammen mit ihrer Laufzeitumgebung ausgeliefert wird. Verwendet man dazu eine der üblichen Linux Distributionen, könnten auch dort Schwachstellen existieren. Je nachdem, welche Teile daraus von der eigenen Applikation wirklich verwendet werden, ist dies mehr oder weniger problematisch.

Verwendet man den Container Manager Kubernetes, kommen weitere Dinge hinzu, die im Kontext Sicherheit betrachtet werden müssen. Dies sind einerseits die Prozesse von Kubernetes selbst, andererseits aber auch die Konfiguration dessen, was man Container auf dem Hostsystem erlaubt und was nicht.

Allgemein lassen sich Fragen nach der Sicherheit auf einem Kubernetes Cluster in folgende Bereiche unterteilen:


Host / Kubernetes

  • Verschlüsselte und authentifizierte Kommunikation der Prozesse des Kubernetes Clusters selbst (API-Server, ETCD, …)
  • Kernel-Schwachstellen des Hosts
  • Autorisierte Kommunikation durch Role Based Access Control
  • Durch den Nutzer mit kubectl
  • Durch  die PODs über Service Accounts

Container

  • Sicherheitsrelevanten Aspekte der Pod-Spezifikation (YAML)
  • Schwachstellen des Container Images

Applikation

  • Kontrolle der IP-Kommunikation der Applikation durch eine verteilte Firewall (innerhalb des VLAN)
  • Verschlüsselung, Authentifizierung und Autorisierung der Services der Applikation untereinander (siehe zum Beispiel SPIFFE)

Dieser Artikel soll eine kurze Übersicht über einige der wichtigsten Punkte geben.


Kubernetes Process Security

Ein Kubernetes Cluster besteht aus 5 Prozessen (kubelet, kube-proxy, API Server, Scheduler, Controller Manager ) und einem ETCD Cluster. Die Nutzer kommunizieren mit dem API-Server über die CLI kubectl. Verwendet man keinen managed Cluster sondern setzt den Cluster selbst auf und/oder implementiert eine eigene Nutzerverwaltung, sollten folgende Punkte beachtet werden:

  • Verwendung von Transport Level Security (TLS) für die gesamten Kommunikation mit dem API-Server und des ETCD Clusters
  • API-Server Authentication
  • Kleine Cluster verwenden ein einfaches Zertifikat oder einen statischen Bearer-Token. Grössere Cluster können einen bestehenden OIDC- oder LDAP-Server integrieren.
  • Alle API-Clients müssen authentifiziert werden. Auch diejenigen, die Teil der Kubernetes Infrastruktur sind, wie Nodes, Kube Proxy, Kubelet oder auch Volume-Plugins.
  • Zugriff auf ETCD einschränken
  • Mögliche Lese- oder Schreibzugriff anderer Komponenten auf ETCD ist gleichbedeutend mit der Gewährung von Cluster-Admin Rechten.

Role Based Access Control

Zur Autorisierung mit dem API-Server besitzt Kubernetes ein integriertes Role-Based Access Control (RBAC), das Benutzer oder eine Gruppe mit einer Reihe von Berechtigungen in Rollen zusammenfasst. Diese Berechtigungen kombinieren Verben (get, create, delete, update, ...) mit Ressourcen (Pods, Ingress, Deployment, ...) und können sich auf einen Namespace oder den gesamten Cluster beziehen.

RBAC regelt nicht nur die Rechte der Nutzer, sondern auch die von PODs die, z.B. nach dem Operator bzw. Controller Pattern, mit dem API-Server kommunizieren.


Wann ist RBAC notwendig?

Ohne RBAC hat jeder Nutzer mit einer gültigen kubeconfig vollen Zugriff, d.h. Cluster-Admin Rechte, auf dem Cluster. Aber nicht nur das, denn jeder deployte POD im System hat dieselben vollen Rechte, wenn er mit dem API-Server kommuniziert und könnte andere PODs überwachen, dort z.B. weitere Prozesse starten oder Daten auslesen. Cluster ohne RBAC sind somit allenfalls für Demo- oder Testinstallationen empfehlenswert.

Network Policies

Eine Network Policy ist eine Spezifikation, wie Gruppen von Pods miteinander und mit anderen Netzwerk-Endpunkten kommunizieren dürfen. Dabei realisieren sie keine Firewall im klassischen Sinne auf Node Ebene, sondern auf logischer Ebene für PODs und Namespaces. Üblicherweise werden Network Policies durch das VLAN realisiert, dass bei der Installation des Clusters durch ein Netzwerk-Plugin bestimmt wird (z.B. Canal)

Eine sehr gute Übersicht über verschiedene UseCases und die Rezepte dazu bietet das Projekt Kubernetes Network Policy Recipes. Zum Beispiel lässt sich durch die folgende Policy der Netzzugriff von anderen Namespaces (z.B. “other”) auf alle PODs im Namespace “my-app” verhindern.



Wann sind Network Policies notwendig?

Kubernetes lässt sich um so gewinnbringender einsetzten, je weniger verschiedene Cluster man verwendet. Dadurch lassen sich Ressourcen, wie Hardware oder Personal für die Cluster-Administration am effektivsten nutzen. Folgt man diesem Ansatz, muss man die laufenden PODs vor Zugriffen schützen oder sie ggf. am Aufbau von Verbindungen nach aussen hindern.


Use Cases für den Einsatz von Network Policies können unter anderem sein:

  • Isolation unterschiedlicher Mandanten-Systeme auf einem gemeinsamen Cluster
  • Isolation eines Produktions-Namespaces von diversen Test-Namespaces (die dieselben Komponenten enthalten und nicht unbeabsichtigterweise auf die falsche Persistenz zugreifen sollen)
  • Whitelisting von eingehenden Netzzugriffen
  • Blockierung von Verbindungsversuchen einer Anwendung nach aussen

Pod Security Policies

Container sind nichts anderes als auf einem Host laufende, allerdings isolierte, Prozesse. Was ein solcher Container darf und was nicht, wird wesentlich von den Einstellungen der Pod-Spezifikation (der YAML) bestimmt. So kann man dort einem Container Zugriff auf das Host-Dateisystem und sämtliche Devices geben. Da für eine solche YAML normalerweise der Softwareentwickler verantwortlich ist, kann man die Einstellungen dort nicht immer kontrollieren. Dies trifft insbesondere auf die Installation von fremden Komponenten per HELM Charts oder ksonnet zu.

Dem Zweck solche Deployments sicherer zu gestalten dienen die Pod Security Policies. Sie kontrollieren sicherheitsrelevante Aspekte der Pod-Spezifikation und definieren eine Reihe von Bedingungen (für eine gute Übersicht der Sicherheitsfunktionen des Linux Kernels siehe auch hier), unter denen ein Pod laufen muss, um in das System aufgenommen zu werden.

Realisiert wird das durch spezielle Pod Security Policy Ressourcen, die über Role- und Rolebinding-Objekte an Service Accounts gebunden werden. Damit werden die über die Service Accounts erstellten PODs durch Policies geprüft. Eine Pod Security Policy erlaubt eine sehr umfangreiche und feingranulare Konfiguration der Möglichkeiten eines Containers, z.B. durch die folgenden Parameter:



Die wichtigsten Security Policies

  • Privileged - bestimmt, ob ein Container in einem Pod den privileged Mode aktivieren kann. Standardmässig darf ein Container auf keine Devices auf dem Host zugreifen. Ein privilegierter Container darf das und erhält somit nahezu die gleichen Zugriffsmöglichkeiten, wie ein auf dem Host laufender Prozess.
  • Host Network: Steuert, ob der Pod das Node Network verwenden darf. Container eines solchen PODs haben Zugriff auf das Loopback Device, auf die Prozesse die an localhost gebunden sind, können den Netzwerkverkehr anderer PODs auf dem selben Knoten abgreifen und sind ggf. nicht an die Network Policies eines VLANs gebunden.
  • Volumes: Ermöglicht die Konfiguration einer Whitelist für erlaubte Volume-Typen. Auf diese Weise ist es möglich z.B. hostPath-Volumes generell auszuschliessen.
  • Allowed Host Paths: Sollte ein hostPath-Volume notwendig sein, kann eine Whitelist von Pfaden angegeben werden, die verwendet werden dürfen.
  • Capabilities: Linux teilt die Privilegien, die traditionell mit dem Superuser verbunden sind, in verschiedene Einheiten auf, die als Capabilities bezeichnet werden. Sie können unabhängig voneinander aktiviert oder deaktiviert werden.


Weitere Informationen zum Thema Pod Security Policies sind hier zu finden.


Wann sind Security Policies notwendig?

Erlaubt man einem Container uneingeschränktem Zugriff auf das Dateisystem eines Hosts, ergeben sich viele Möglichkeiten zur Eskalation von Privilegien. So können sensible Daten (z.B. Logs, Anmeldeinformationen etc.) von anderen Containern bzw. Prozessen oder des Hosts selbst ausgelesen werden. HostPath-Volumes generell auszuschliessen oder Pfade zumindest zu whitelisten ist sicher eine gute Idee.

Ebenso wie das Host-Dateisystem, wird man die Devices des Hosts und das Host Network (PODs dürfen nur das VLAN des Network Plugins verwenden) schützen wollen. Dies nur spezifischen PODs zu erlauben, z.B. allen PODs im Namespace kube-system, ist immer empfehlenswert.

Viele existierende Container laufen als Root oder benötigen die Capabilities die Docker standardmässig für seine Container hinzugefügt hat (siehe auch die Docker Dokumentation). Dazu gehören zum Beispiel NET_BIND_SERVICE (erlaubt das Binden eines Sockets an einen privilegierten Port unter 1024) oder SETUID (erlaubt das beliebige Manipulieren der Prozess UIDs). Wann es sinnvoll ist, einem Container eine Capability zu entziehen oder ihm einzelne hinzuzufügen, hängt natürlich stark von der Applikation ab, die betrieben werden soll. Generell gilt aber, dass weniger Capabilities immer besser sind als mehr davon. Pod Security Policies sind ein gutes Mittel einen ausgewählten Satz von Capabilities als verwendbar vorzuschreiben oder sie generell zu verbieten (wobei in diesem radikalen Fall, die meisten komplexeren Applikationen nicht mehr starten dürften).

Zusammenfassung

Kubernetes Prozesse untereinander abzusichern ist ebenso üblich, wie eine zuverlässige Authentifizierung (sei es über einfache Zertifikate, Token oder einen OIDC Server) oder Autorisierung (RBAC für Nutzer oder PODs) bezüglich des API-Servers sicherzustellen. Vergessen wird dabei jedoch oft, dass Container ihre Laufzeitumgebung beinhalten und es sich dabei um normale Prozesse handelt, die ohne Virtualisierung auf einem Hostsystem laufen. Nicht nur die Container Images müssen kontinuierlichen erneuert werden, sondern auch der Kernel bzw. die Distribution des Hosts, um Schwachstellen zu beseitigen.

Kubernetes (resp. Docker) erlaubt es die Rechte eines Containers in der POD-Spezifikation zu erweitern. Je weniger Kontrolle man als Verantwortlicher über die POD-Spezifikationen oder die deployten Container hat, desto mehr möchte man hier generelle Einschränkungen machen. Dazu sind Pod Security Policies eine recht einfache Möglichkeit das sicherzustellen.

Aber auch die Applikationen selbst müssen gesichert werden. Wer möchte schon, dass sich die Applikationen eines Test-Namespaces mit der Produktionsdatenbank unterhält oder dass die HTTP UI von Mandant A versehentlich auf den Backend Service von Mandant B zugreift. Allerdings, für jeden Mandanten, jedes Team, jedes Projekt, für jeden Test/QA/Staging einen eigenen Cluster zu verwenden ist nicht immer ein praktikabler und produktiver Weg. Die Network Policies erlauben es hier, die notwendigen Einschränkungen für Egress oder Ingress zu konfigurieren, um nicht notwendigerweise in den Aufwand mehrerer Cluster investieren zu müssen.

Docker und Kubernetes vollbringen keine Wunder und noch immer sind zum Thema Sicherheit einige Überlegungen zu investieren. Beide Tools bieten aber genügend Möglichkeiten Container und Cluster auf verschiedenen Ebenen so sicher wie möglich zu machen.

Helft mir die Reise zu beginnen

Sprechen Sie mit uns!

Wir möchten mehr über Ihr Migrationsvorhaben erfahren! Gemeinsam entwickeln wir einen Plan, wie wir Sie dabei unterstützen können.

Wir verwenden Ihre Daten zur Kontaktaufnahme.
Datenschutzhinweise
Danke!

Du erhältst bald Deine erste Ausgabe von Published.
Oh nein, da ist ein Fehler passiert. Bitte versuche es nochmal.