Kubernetes-Sicherheit

Durchgängige, proaktive Kubernetes-Sicherheit realisieren

Durchgängige, proaktive Kubernetes-Sicherheit realisieren

Von Daniel Virassamy, Principal Solutions Architect bei Mirantis

Die Absicherung von Kubernetes (und der zugrunde liegenden Infrastruktur) ist kein leichtes Unterfangen. Noch schwieriger ist es, die gesamte Software-Lieferkette abzusichern. Die eigentliche Herausforderung allerdings ist, die End-to-End-Security für all dies in Echtzeit zu gewährleisten, während sich Dinge laufend verändern.

Daniel Virassamy, Principal Solutions Architect bei Mirantis

Entwickler möchten sich auf die Entwicklung von Anwendungen konzentrieren. Sie sind daher naturgemäß von der Grundidee begeistert, dass Kubernetes ein Standard-Substrat für das Hosting und den Betrieb von Anwendungen in unterschiedlichen Umgebungen sein kann.

Aber es gibt einen Haken. Zwar besitzt Kubernetes durchaus das reale Potenzial, gewissermaßen als “Commodity-Substrat” genutzt zu werden. Um aber tatsächlich zu erreichen, dass sich Entwickler einfach ausschließlich und allein um ihren Code kümmern können, sind viel Know-how, intelligente Automatisierung und Vorsicht erforderlich. Dies gilt ganz besonders für die Absicherung der Software-Lieferkette: CI/CD und Workflows, die Entwickler für das Erstellen und den Betrieb von Cloud-nativen, containerisierten Anwendungen verwenden.

Schnell ist gut (aber nicht immer)

Beim Thema Software-Lieferkette geht es darum, Technologie zu beschleunigen. Hand in Hand mit einem modernen, containerorientierten Anwendungsdesign und ebensolchen Entwicklungsmethoden kann ein solides Automatisierungs-Framework für CI/CD und den Betrieb von Anwendungen dazu beitragen, dass ein Unternehmen von eher seltenen Releases zu täglichen oder gar stündlichen Releases übergeht.

Eine schnellere Bereitstellung von Funktionen ist zwar grundsätzlich eine gute Sache. Geschwindigkeit kann aber auch Gefahren mit sich bringen. Schwachstellen finden ihren Weg in laufende Anwendungen aus vielen unterschiedlichen Quellen, darunter beispielsweise (und diese Liste ist sehr unvollständig):

  • Unzureichend geprüfte Basis-Container
  • Sprachmodule
  • Cut & Paste aus nicht validierten Quellen (was auch ein rechtliches Risiko darstellen kann)
  • Erstellte und/oder über Container verteilte Komponenten von Drittanbietern

Die Containerisierung macht vieles davon undurchsichtig. Komplexität in großem Maßstab macht alles noch schlimmer.

Noch weiter verschärft wird die Problematik durch die Automatisierung: Von Build-Prozessen, die spontan entscheiden, welche Container und Repositories genutzt werden sollen, bis hin zur Ops-Automatisierung, die Container von Drittanbieter-Komponenten dynamisch einbindet und dabei möglicherweise Konfigurationen verändert. Die Hochgeschwindigkeits-Bereitstellung moderner Anwendungen wird für Menschen schnell unkontrollierbar. Es passiert einfach viel zu viel auf einmal.

Weitere Risiken treten auf jeder Ebene der erweiterten Plattform auf. Kubernetes läuft aus guten Gründen oft auf einem Deep Stack: IaaS-Clouds (öffentlich oder privat) ermöglichen beispielsweise die schnelle und auch relativ einfache Bereitstellung und Skalierung von Kubernetes-Clustern auf virtuellen Maschinen. Aber die theoretische Angriffsfläche umfasst jetzt zum Beispiel die Netzwerk- und Betriebsdienste einer Cloud sowie die niedrigsten Host-Betriebssysteme auf Bare Metal, Hypervisoren, Gastbetriebssysteme auf jeder VM, alle Kubernetes-Komponenten sowie viele Kubernetes-Erweiterungen für Ingress, Networking, Service Mesh und vieles mehr. Oder, etwas kürzer ausgedrückt: Das ist eine ganze Menge.

Die Entschärfung von Sicherheitsrisiken dauert oft viel zu lange

All dies bedeutet, dass Schwachstellen (wenn nicht manchmal sogar direkt Malware) ihren Weg in die Produktionsebene finden und in vielen Fällen dem Internet ausgesetzt sind. In dieser Hinsicht sollten Sie sich vor allem auf den Aspekt “Zeitspanne bis zur Behebung” konzentrieren. Denn je länger eine Sicherheitslücke bestehen bleibt, desto größer ist die Wahrscheinlichkeit, dass sie auch tatsächlich ausgenutzt wird.

Leider sieht es hier mit Blick auf die meisten Unternehmen und Organsisationen allerdings nicht allzu gut aus. Laut einem von HelpNet Security veröffentlichten Artikel , der sich auf Analysen von SecurityScorecard und The Cyentia Institute stützt, die die CVEs von 1,6 Millionen Unternehmen aus verschiedenen Branchen untersucht haben, weisen 53 % der Unternehmen mindestens eine Schwachstelle auf, die dem Internet ausgesetzt ist. Bei 22 % sind es sogar mehr als 1.000. Schlimmer noch: Die durchschnittliche Zeit für die Behebung einer CVE liegt zwischen 270 und 426 Tagen. Die durchschnittliche Zeit, die ein Unternehmen benötigt, um nur die Hälfte der ausstehenden CVEs zu beheben, liegt bei rund einem Jahr. Und je mehr CVEs sich ansammeln, desto länger dauert es in der Regel, sie zu beheben.

Und genau das ist es leider, was Schwachstellen tun: sie werden mehr. Mit jeder neuen Version, mit jedem Komponenten-Upgrade.

Der Weg zu mehr Sicherheit

Wie kann man diese Problematik nun lösen? Die vielleicht nicht ganz so angenehme Antwort lautet: indem man akribisch viele, viele und durchaus mühsame Schritte unternimmt. Im Folgenden eine – unvollständige – Liste der Schritte, die in Betracht gezogen werden sollten, um ein erweitertes Kubernetes-System abzusichern. (Das beinhaltet: die Software-Lieferkette sowie die Ziel-Cluster für Entwicklung, Test, (Staging) und Produktion, einschließlich aller Bereitstellungs- und Life-Cycle-Management-Tools / LCM). Zwar sind Entwicklungs-/Test-/Staging-Cluster manchmal nicht vollständig über das Internet zugänglich. Sie lassen sich aber umso sinnvoller nutzen, je genauer sie mit Ihren Produktionsumgebungen übereinstimmen).

Grundsätzlich kann hier nach einem Top-Down-Ansatz (zuerst die Anwendungen, dann die Plattform) oder nach Bottom-Up-Methode (zunächst die Plattform, dann die Anwendungen) vorgegangen werden. In der Praxis teilen sich viele Entwicklungsteams die Arbeit mit dem Betrieb der Cloud-Plattformen oder beauftragen einen Anbieter von Managed Services oder einer öffentlichen Cloud mit dem Management der Plattform-Komponenten. Wie man im Folgenden sehen wird, kann diese Vorgehensweise tatsächlich sinnvoll sein: Die Plattform soll eine vertrauenswürdige Basis darstellen. Und wer Anwendungen schneller bereitstellen will, muss sich auf die Vertrauenswürdigkeit der Plattform auch verlassen können. Dieser Aspekt hängt jedoch stark davon ab, wer die Partner und Dienstleister rund um die Plattform sind und wie ernst sie das Thema Sicherheit nehmen.

Früherkennung ist der Schlüssel. Wenn Probleme bereits im Quellcode erkannt werden können, bevor sie sich in Containern “verstecken”, ist die Behebung deutlich einfacher. Die Analyse der Softwarezusammensetzung – die Offenlegung aller Quellen, aus denen eine Codebasis abgeleitet werden kann, und die Identifizierung bekannter Schwachstellen – ist ein erster Schritt. Tools wie beispielsweise Black Duck oder Sonatype können dabei helfen.

Die Kuratierung von Container-Basis-Images ist entscheidend für die Identifizierung von CVEs und die Verkleinerung potenzieller Angriffsflächen (und sorgt dafür, dass die Dinge schneller und besser funktionieren). Slim.ai hat einige erwähnenswerte Untersuchungen zu aufeinanderfolgenden Versionen beliebter öffentlicher Container-Images durchgeführt, Tools von Drittanbietern eingesetzt, um Schwachstellen aufzudecken, Software-Stücklisten erstellt und darüber hinaus seine eigenen "Container-Slimming"-Tools eingesetzt, um die Angriffsfläche zu verringern und ungenutzte Abhängigkeiten zu entfernen. Ein Großteil dieser Informationen ist kostenfrei verfügbar.

Erstellte Container scannen

Sobald ein Container erstellt wurde, ist es wichtig, einen erneuten Scan durchzuführen. So können Probleme erkannt werden, die sich möglicherweise dynamisch eingeschlichen haben. Tools wie Sysdig , Snyk , oder Synopsys können hier eine entscheidende Rolle spielen – idealerweise integriert in die Container-Registrierung, um automatisch zu laufen, wenn Container gespeichert und wenn sie angefordert werden.

Signieren von Containern und obligatorische Signaturprüfungen bei Container-Runtimes

Eine entscheidende Maßnahme, um zu verhindern, dass durch Automatisierung Sicherheitsprobleme entstehen, ist die Einführung strikter Richtlinien, die Menschen in die Prozesse einbeziehen und Audit-Trails erstellen. Zu den wichtigsten Aspekten zählt dabei das Signieren von Images. Das bedeutet, eine autorisierte Person muss Images kryptografisch signieren und nach einer Überprüfung für die Produktion freigeben. Dies wird in der Regel auf der Ebene der Container-Registry implementiert. Eine ebenfalls wichtige und damit zusammenhängende Funktion, die in der Container-Laufzeitumgebung implementiert wird, ist die "Verhinderung der Ausführung" (engl. execution prevention): Images, die nicht ordnungsgemäß signiert wurden, werden grundsätzlich nicht ausgeführt.

Lint & Scan von YAML-Konfigurationsdateien, Helm-Diagrammen, Deployment-Automatisierung und anderen Komponenten, die nicht direkt zum Anwendungscode gehören.

Container sind natürlich nicht die einzigen Orte, an denen sich Probleme verstecken können. Hier verlassen wir allerdings den Bereich der CVEs, die typischerweise von Institutionen wie Synopsys oder MITRE verfolgt werden, und beschäftigen uns mit den etwas subtileren Risiken. Dabei kann es sich beispielsweise um Fehlkonfigurationen von Anwendungen oder Clustern handeln, die Angreifern entsprechende Einstiegspunkte bieten. Auch dies sollte automatisiert werden, wobei die Automatisierung mit Infrastructure as Code, Helm und anderen Repositories integriert werden sollte.

So viel wie möglich davon sollte in einen automatisierten Workflow eingebunden werden, der als Secure Software Supply Chain bezeichnet wird.

Eines sollte immer bedacht werden: Auf das Unternehmen bezogen besteht der Zweck von CI/CD und der damit verbundenen Automatisierung hauptsächlich in der Beschleunigung der Vorgänge. Daher ist es nicht sinnvoll und zielführend, viele manuelle Schritte mit komplexen Sicherheitstools einzuführen (auch wenn dies darauf abzielt, die Sicherheit der Resultate zu gewährleisten).

Durch kontinuerliche Pflege der Lieferkette wird sichergestellt, dass sie reibungslos funktioniert. Ein Thema ist hier auch die regelmäßige Optimierung, wenn beispielsweise neue Tools und Technologien verfügbar werden. Es ist erforderlich, an allen Punkten auf die sich laufend verändernde Bedrohungslandschaft zu achten. Um zielgerichtete Optimierungen durchführen zu können, sollten die Ergebnisse anhand von Standardmetriken gemessen werden.

Absicherung der Plattform

Von entscheidender Bedeutung ist auch die Absicherung von Kubernetes selbst, also des Clusters und seiner Host-Infrastruktur. Dies gilt zudem auch für die Verwaltung von Kubernetes und der integrierten Dienste, die die Bereitstellung und das Lifecycle-Management von Anwendungen bestimmen.

Um Kubernetes selbst sicher zu machen, müssen die Quellen für einzelne Komponenten auf CVEs gescannt und gefundene Schwachstellen behoben werden. Anschließend ist es wichtig, Kubernetes stets auf dem neuesten Stand zu halten. Dies wiederum setzt voraus, eine Update-Automatisierung einzuführen und (ebenso wichtig) auf zukunftssichere Anwendungsarchitekturen zu setzen, die alle Belange sauber voneinander trennen und Funktionen, die vermutlich veraltet sind, gar nicht oder nur zu einem absoluten Minimum nutzen. Gegenwärtig setzen viele Unternehmen und Organisationen immer noch Kubernetes 1.21 ein, welches die End-of-Life-Phase bereits überschritten hat. Der Hauptgrund dafür ist, dass ein Umzug von Anwendungen, die von in neuen Versionen veralteten Funktionen abhängig sind, nicht einfach ohne Refactoring möglich ist.

Die Umgebung für die Anwendungsunterstützung umfasst darüber hinaus Aspekte und Bereiche wie Zugriffskontrolle und RBAC, Richtlinienverwaltung, Auditierbarkeit, Zertifikatsverwaltung, Ressourcenverbrauch sowie Überwachung und Monitoring (plus spezielle Unterbereiche in Bezug auf die Sicherheitstransparenz, für die es sinnvoll ist, dedizierte Dashboards zu erstellen).

All diese Dinge erfordern eine Bewertung und ein detailliertes Management, um sowohl Sicherheits- als auch andere Betriebsrisiken (wie etwa Datenverluste und Ausfälle) zu verringern und den Ressourcenverbrauch zu steuern (sowie die Kosten richtig zuordnen zu können). Auch anwendungsspezifische Service-Mesh-Konfigurationen und "Zero-Trust"-Frameworks müssen validiert werden. Ebenso gilt dies für Richtlinien und Technologieentscheidungen, die die Verschlüsselung von Daten bei der Übertragung und Aufbewahrung sicherstellen. Data Loss Prevention, Backup und Disaster Recovery sind ebenfalls wichtige Aspekte der Gesamtsicherheit, der Einschätzung der Reichweite möglicher Auswirkungen und der Schadensbegrenzung. In der Regel wird eine Liste der noch zu erledigenden Punkte sehr individuell auf die Besonderheiten der spezifischen Systemarchitektur zugeschnitten sein.

Viele dieser Dienste sind auch generell für die Betriebssicherheit von Clustern von grundlegender Bedeutung. Sie fallen daher nicht unbedingt in den Bereich "DevOps" (in strengem Sinne als Betrieb von Anwendungen definiert) und werden im Idealfall unternehmensweit von Plattform-Spezialisten und SRE-Teams implementiert und standardisiert (und im Endeffekt von Entwicklern lediglich genutzt). In der manchmal nicht ganz so idealtypischen realen Welt kann es aber natürlich auch durchaus vorkommen, dass der DevOps-Bereich für all dies verantwortlich ist.

Unter der Plattform

Spricht man in diesem Zusammenhang von “low hanging fruits”, dann ist die Verbesserung der Sicherheit unter Kubernetes-Clustern das nächste relativ leicht zu erreichende Ziel. Selbst wenn die Bereitstellung in öffentlichen Clouds erfolgt (einmal angenommen, es kommt keine vorkonfigurierte Kubernetes-Lösung zum Einsatz, die vollständig vom Cloud-Anbieter verwaltet wird), gibt es hier Möglichkeiten zur Risikoverringerung.

Besonders wichtig ist das Betriebssystem, auf dem die Kubernetes-Knoten gehostet werden – die meisten gängigen Linux-Distributionen bieten eine relativ große und vielfältige Angriffsfläche. Die generelle Strategie sollte deshalb darin bestehen, den Linux-Quellcode mit einem Open-Source-Tool wie OpenVAS (es gibt auch viele weitere) auf CVEs zu scannen. Anschließend kann das bevorzugte Betriebssystem soweit wie möglich minimiert werden, indem es neu aufgebaut wird und dabei nicht benötigte Abhängigkeiten entfernt werden. Eine weitere Möglichkeit ist, direkt mit einem bereits minimierten Linux zu starten, das speziell für Cloud und Kubernetes ausgelegt ist, beispielsweise also mit einer Distribution wie Rocky Linux .

Ein weiteres Beispiel für eine Überprüfung, die regelmäßig durchgeführt werden sollte: Der Scan sämtlicher Deployment-Templates (zum Beispiel CloudFormation), die für das Erstellen von Clustern verwendet werden. Für gängige Deployment-Tools stehen sowohl Open-Source- als auch proprietäre Tools (beispielsweise Aqua Security ) zur Verfügung. Diese ermöglichen den Scan und können gleichzeitig Empfehlungen zur Behebung von Problemen aussprechen.

Das große Ganze

Das übergeordnete Ziel ist natürlich Schnelligkeit. Gleichzeitig gilt es aber auch zu verhindern, sich gewissermaßen ein Eigentor zu schießen. Automatisierung ist daher von entscheidender Bedeutung.

Man kann hier entweder selbst tätig werden oder aber mit DevOps-/DevSecOps-Partnern zusammenarbeiten, die Security-affin sind, sich gut mit der Einschätzung und Behebung von Schwachstellen auskennen und quasi einen sofort implementierbaren Best-Practice-Ansatz entwickelt haben: Ein vertrauenswürdiges Strategiepapier für die zuverlässige und flexible Automatisierung kritischer Schritte, so dass der Fokus künftig komplett auf der Entwicklung des Codes liegen kann.