Zu Abschnitt

Einführung in Kubernetes-Sicherheit

URL kopieren

Trotz zunehmender Akzeptanz bleibt die Sicherheit ein wichtiges Anliegen bei Containern und Kubernetes. Die gute Nachricht ist, dass Sie zahlreiche Maßnahmen ergreifen können, um die Sicherheit Ihrer Container-Implementierung zu verbessern. In dieser Einführung in die Sicherung von Kubernetes werden viele der Schritte beschrieben, die Sie für den Einstieg in die Container-Sicherheit ausführen können.

Container Images sind häufig eine Hauptquelle für Schwachstellen in cloudnativen Umgebungen. Ein Kernelement einer effektiven Sicherheitsstrategie besteht darin, die Einhaltung sicherer Verfahren zur Image-Erstellung im gesamten Unternehmen sicherzustellen. Das Scannen von Images trägt wesentlich zum Sicherheitsstatus des Unternehmens bei. Doch die Sicherung von Images bietet eine Möglichkeit, die Sicherheit containerisierter Anwendungen bereits zu einem früheren Zeitpunkt im Anwendungs-Lifecycle proaktiv zu gewährleisten.

Best Practices zum sicheren Erstellen von Container Images:

  1. Minimale Basis-Images verwenden

    Zur Reduzierung der Angriffsfläche sollte das Image nur die Libraries und Tools enthalten, die für den Container erforderlich sind.

  2. Basis-Images von vertrauenswürdigen Quellen verwenden

    Wenn Sie ein Image nicht von Grund auf neu erstellen, wählen Sie Basis-Images, die von einer vertrauenswürdigen Quelle stammen. Sie sollten das Dockerfile und den Quellcode für alle Image-Komponenten sehen können, und er sollte in einer seriösen Registry gehostet werden. Die Basis-Images sollten auch regelmäßig aktualisiert werden.

  3. Nutzer angeben

    Wenn das Dockerfile keinen Nutzer angibt, wird der Container standardmäßig mit dem Root-Nutzer ausgeführt. Dadurch wird die potenzielle Angriffsfläche erweitert, und bei einer beschädigten Anwendung besteht die Gefahr einer Berechtigungseskalation.

  4. Docker-Images verifizieren

    Die Gewährleistung der Authentizität eines Images ist eine Herausforderung, aber eine wichtige Komponente beim Erstellen sicherer Images. Alle Basis-Images sollten signiert und validiert werden. Nur durch das Abrufen von Images aus vertrauenswürdigen Registries kann sichergestellt werden, dass alle Images authentisch sind.

  5. Auf Schwachstellen scannen

    Es ist wichtig, in Container Images vorhandene Schwachstellen zu finden und zu beheben, einschließlich solcher aus Open Source Libraries.

  6. Secrets auslassen

    Secrets, die sensible Daten wie Zugangsdaten und Schlüssel enthalten, sollten nicht in Container Images eingebettet werden.

  7. Ressourcenlimits festlegen

    Durch eine Beschränkung der Menge an CPU- oder Speicherressourcen, auf die ein Container zugreifen kann, können Sie den Schaden begrenzen, der bei unsachgemäßer Verwendung entstehen kann.

  8. Berechtigungen einschränken

    Legen Sie die Berechtigungen des Containers so restriktiv wie möglich fest, und konfigurieren Sie den Container so, dass Berechtigungen nicht eskaliert werden können.

  9. Multi-Stage Builds verwenden

    Die zum Generieren und Kompilieren von Anwendungen verwendeten Build-Tools können ausgenutzt werden, wenn sie auf Produktionssystemen ausgeführt werden. Statt in der Build- und Ausführungsphase die gleichen Images zu verwenden, nutzen Sie Multi-Stage Dockerfiles, um unnötig komplizierte Tools aus den Runtime Images zu entfernen. Auch Debugger sollten in Produktions-Images nicht verwendet werden.

  10. Sicherheitsorientierte Codierungspraktiken verwenden

    Diese können durch Verwendung eines Linters durchgesetzt werden, um unsicheren Code während des Entwicklungsprozesses abzufangen.

Obwohl diese Schritte spezifisch für den Image-Erstellungsprozess sind, sollten die Prinzipien zum Erstellen sicherer Images auch die Sicherheitspraktiken in anderen Teilen der Anwendung bestimmen. Zu diesen Praktiken gehört es, die Angriffsfläche so klein wie möglich zu halten, Berechtigungen einzuschränken und Konfigurationen zu straffen, anstatt die Standardeinstellungen in Kubernetes und anderen Aspekten des cloudnativen Stacks zu verwenden.

CIS-Benchmarks für Kubernetes

Das Center for Internet Security (CIS) entwickelt Best Practices für die Cyberabwehr. Das CIS nutzt Crowdsourcing, um ihre Sicherheitsempfehlungen zu definieren. Die CIS-Benchmarks zählen zu seinen am weitesten verbreiteten Tools.

Unternehmen können die CIS-Benchmark für Kubernetes verwenden, um ihre Kubernetes-Umgebungen zu härten. Es stehen eine Reihe von quelloffenen und kommerziellen Tools zur Verfügung, die automatisch Prüfungen anhand der Einstellungen und Kontrollen in der CIS-Benchmark durchführen, um unsichere Konfigurationen zu identifizieren.

Die CIS-Benchmark bietet eine Reihe hilfreicher Konfigurationsprüfungen. Organisationen sollten diese jedoch nur als Ausgangspunkt betrachten und über die CIS-Prüfungen hinaus sicherstellen, dass Best Practices auf Kubernetes angewendet werden. Dazu zählen Implementierung von Netzwerkrichtlinien, RBAC-Einstellungen (Role-based Access Control), Admin-Berechtigungen und andere Schutzmaßnahmen für den Kubernetes-API-Server.

Kubernetes-RBAC (Role-based Access Control) ist die Standardmethode zum Verwalten der Autorisierung für die Kubernetes-API-Endpunkte. Die RBAC-Konfiguration Ihres Clusters steuert, welche Subjekte welche Verben auf welchen Ressourcentypen in welchen Namespaces ausführen können. Beispielsweise kann eine Konfiguration dem Nutzer „alice“ Zugriff gewähren, um Ressourcen vom Typ „pod“ im Namespace „external-api“ anzuzeigen. Die RBAC-API enthält vier deklarative Objekte: Role, ClusterRole, RoleBinding und ClusterRoleBinding.

Roles sind eine Namespace-Ressource, die aus Regeln zur Festlegung von Berechtigungen für einzelne Namespaces besteht. ClusterRoles hingegen sind eine Nicht-Namespace-Ressource. Sie erteilen clusterweite Berechtigungen oder Berechtigungen, die sich über mehrere Namespaces erstrecken. Jede Regel ist eine Kombination aus Verben, Ressourcentypen und Namespace-Selektoren.

Eine Rollenbindung ist die Brücke, die einen Nutzer, eine Gruppe von Nutzern oder ein Service-Account (auch als „Subjekte“ bezeichnet) mit einer Rolle verbindet und diesen Nutzern die in dieser Rolle definierten Berechtigungen gewährt. Eine Cluster-Rollenbindung bindet eine ClusterRole an alle Namespaces in Ihrem Cluster. Auf diese Weise weist eine RoleBinding Berechtigungen innerhalb eines Namespace zu, während eine ClusterRoleBinding diese Berechtigungen clusterweit gewährt.

Basierend auf unseren Erfahrungen mit Kunden haben wir die folgenden 5 häufigsten Fehler ermittelt, auf die Sie in den RBAC-Konfigurationseinstellungen achten sollten.

 

Konfigurationsfehler 1: Cluster-Administratorrolle unnötigerweise gewährt

Die integrierte Rolle des Cluster-Administrators gewährt unbegrenzten Zugriff auf den Cluster. Während des Übergangs vom Legacy-ABAC-Controller zu RBAC haben einige Administratoren und Nutzer möglicherweise die permissive ABAC-Konfiguration repliziert, indem sie die Warnungen in der entsprechenden Dokumentation vernachlässigt und weitestgehend die Cluster-Administratorrolle gewährt haben. Wenn Nutzern oder Gruppen routinemäßig die Cluster-Administratorrolle gewährt wird, können Account-Kompromittierungen oder -Fehler gefährlich weitreichende Auswirkungen haben. Auch Service-Accounts benötigen diese Art von Zugriff in der Regel nicht. In beiden Fällen sollte eine besser zugeschnittene Rolle oder Cluster-Rolle erstellt und nur den spezifischen Nutzern zugewiesen werden, die sie benötigen.

Konfigurationsfehler 2: Unsachgemäße Verwendung der Rollenaggregation

In Kubernetes 1.9 und höher kann Rollenaggregation verwendet werden, um die Gewährung von Berechtigungen zu vereinfachen, indem neue Berechtigungen mit bestehenden Rollen kombiniert werden. Wenn diese Aggregationen jedoch nicht sorgfältig überprüft werden, können sie die beabsichtigte Verwendung einer Rolle ändern. Zum Beispiel könnte die Rolle „system:view“ fälschlicherweise Regeln mit anderen Verben als „view“ aggregieren. Dadurch würde die Absicht verletzt, dass Subjekte, denen die Rolle „system:view“ erteilt wurde, den Cluster niemals ändern können.

Konfigurationsfehler 3: Doppelte Rollenzuweisung

Rollendefinitionen können sich überschneiden, wodurch Subjekten auf mehr als eine Weise der gleiche Zugriff gewährt wird. Administratoren beabsichtigen zwar manchmal, dass diese Überschneidung auftritt, aber durch diese Konfiguration kann es schwieriger sein zu erkennen, welchen Subjekten welche Zugriffe gewährt werden. Diese Situation kann den Widerruf des Zugriffs erschweren, wenn ein Administrator nicht erkennt, dass mehrere Rollenbindungen dieselben Berechtigungen gewähren.

Konfigurationsfehler 4: Nicht verwendete Rolle

Rollen, die erstellt, aber keinem Subjekt zugewiesen werden, können die Komplexität des RBAC-Managements erhöhen. Ebenso können Rollen, die nur nicht vorhandenen Subjekten zugewiesen werden (z. B. Service-Accounts in gelöschten Namespaces oder Nutzern, die die Organisation verlassen haben), das Erkennen der relevanten Konfigurationen erschweren. Das Entfernen dieser nicht verwendeten oder inaktiven Rollen ist normalerweise sicher und lenkt die Aufmerksamkeit auf die aktiven Rollen.

Konfigurationsfehler 5: Gewähren fehlender Rollen

Rollenbindungen können auf Rollen verweisen, die nicht vorhanden sind. Wenn derselbe Rollenname in Zukunft für einen anderen Zweck wiederverwendet wird, können diese inaktiven Rollenbindungen plötzlich und unerwartet anderen Subjekten Berechtigungen erteilen als denjenigen, die der neue Rollenersteller beabsichtigt.

 

Durch die richtige Konfiguration Ihrer Cluster-RBAC-Rollen und -Bindungen können Sie die Auswirkungen von Anwendungskompromittierungen, Übernahmen von Nutzer-Accounts, Anwendungsfehlern oder einfachen menschlichen Fehlern minimieren.

Container und Kubernetes im Vergleich zu Sicherheit bei virtuellen Maschinen (VM)

Virtuelle Maschinen (VMs) und Container haben grundlegend unterschiedliche Architekturen, obwohl sie gerade genug Ähnlichkeiten aufweisen, um einige Verwirrung zu stiften. Container und VMs unterscheiden sich hinsichtlich der Sicherheit in mancher Hinsicht. Sowohl VMs als auch Container bieten in unterschiedlichem Maße Isolation, und beide ermöglichen Portierbarkeit. Virtuelle Maschinen sind vollständig autark, verfügen über ein eigenes Betriebssystem und teilen sich keine Ressourcen mit anderen virtuellen Maschinen. Container teilen Hosts mit anderen Containern, was der Vorstellung einer sicheren Grenze widerspricht.

Container und Kubernetes unterliegen einem anderen Architekturparadigma und erfordern daher einen anderen Sicherheitsansatz. Die bewährten Techniken für hostbasierte Sicherheit sind nicht auf Container übertragbar. Andere Sicherheitstechniken aus der Host- oder VM-Domäne, z. B. das Erstellen von Netzwerk-Firewalls um einen definierten Perimeter, gelten ebenfalls nicht für Container. Darüber hinaus ist ein wichtiger Bestandteil der Best Practices für die Sicherheit virtueller Maschinen das Anwenden von Sicherheits-Patches. Patches können jedoch nicht auf einen laufenden Container angewendet werden – stattdessen muss das Container Image aktualisiert und der Container neu erstellt werden.

Für die Sicherheit von Containern sind folgende Aspekte erforderlich:

  • Kontrolle der Verbindungen zwischen Containern
  • Sicherstellen, dass Container frei von bekannten Schwachstellen sind
  • Verhindern, dass Container Root-Zugriff haben
  • Beschränken von Berechtigungen und Zugriff auf das, was für die Funktion der Anwendung erforderlich ist

Kubernetes erhöht die Komplexität und bringt zusätzliche potenzielle Sicherheitsrisiken mit sich. Die Verwaltung von Kubernetes-Konfigurationen und Netzwerkrichtlinien ist entscheidend für einen starken Sicherheitsstatus bei containerisierten Anwendungen.

Darüber hinaus ist es aufgrund der Workflow-Änderungen, die mit der Umstellung auf containerisierte Anwendungen einhergehen, wichtig, die Sicherheit über den gesamten Lifecycle zu integrieren. Die Sicherheit muss von Anfang an in die Anwendung integriert werden, beginnend mit der Konfiguration von Images und Containern. Am Ende des Entwicklungsprozesses, direkt vor dem Deployment, kann einer containerisierten Anwendung keine Sicherheit mehr hinzugefügt werden.

Die Sicherheit in containerisierten Anwendungen erfordert die Kontrolle der Herkunft aller Komponenten, einschließlich Open Source-Elementen, der Verwaltung von Konfigurationen, dem Scannen von Images und der Aktivierung granularer, rollenbasierter Zugriffskontrollen. Container und Kubernetes erfordern einen anderen Sicherheitsansatz, bieten jedoch aufgrund ihres deklarativen und unveränderlichen Charakters die Möglichkeit – bei richtiger Konfiguration – Anwendungen mit einem außergewöhnlich hohen Maß an Sicherheit zu entwickeln.

In Kubernetes werden Container in Pods ausgeführt, einem von mehreren Kubernetes-Objekten, und die Runtime-Konfiguration der einzelnen Pods kann mithilfe einer Kombination aus Sicherheitskontext in der Pod-Spezifikation, Pod-Sicherheitsrichtlinien (Pod Security Policies, PSPs) oder einem Admission Controller wie dem Open Policy Agent (OPA) Gatekeeper festgelegt und durchgesetzt werden.

Der Sicherheitskontext wird im Deployment-Manifest definiert und ermöglicht Ihnen die Definition der genauen Anforderung für jede Workload. Er kann für einen Pod oder Container konfiguriert werden. Pod-Sicherheitsrichtlinien sind eine Kubernetes-Ressource auf Cluster-Ebene, die den Sicherheitskontext steuern, mit dem Pods ausgeführt werden können. Wenn PSPs für einen Cluster aktiviert sind, wird jeder Versuch, einen Pod zu erstellen, der nicht der zugeordneten Pod-Sicherheitsrichtlinie entspricht, vom PSP Admission Controller zurückgewiesen.

Berechtigungen für die Container-Runtime beschränken:

  • Führen Sie Anwendungsprozesse nicht als Root aus. Setzen Sie runAsUser auf MustRunAsNonRoot.
  • Erlauben Sie keine Eskalation von Berechtigungen. Setzen Sie allowPrivilegeEscalation auf false.
  • Verwenden Sie ein schreibgeschütztes Root-Dateisystem. Setzen Sie readOnlyRootFilesystem auf true.
  • Verwenden Sie den standardmäßigen (maskierten) Dateisystem-Mount /proc.
  • Verwenden Sie nicht den Host-Netzwerk- oder -Prozessbereich. Setzen Sie hostPID, hostNetwork und hostIPC auf false.
  • Löschen Sie ungenutzte Linux-Funktionen, und fügen Sie keine optionalen Funktionen hinzu, die in der Anwendung nicht unbedingt benötigt werden.
  • Verwenden Sie SELinux-Optionen für mehr Granularität bei Prozesskontrollen.
  • Erstellen Sie für jede Anwendung einen eigenen Kubernetes-Service-Account.
  • Mounten Sie die Zugangsdaten des Service-Accounts nur dann in einem Container, wenn dieser auf die Kubernetes-API zugreifen muss.

 

Kubernetes-Namespaces verwenden

Kubernetes-Namespaces legen den Geltungsbereich für Cluster-Objekte fest und ermöglichen so eine differenzierte Verwaltung von Cluster-Objekten. Container/Pods, Services und Deployments innerhalb eines Namespace können mithilfe von Kontrollen wie Kubernetes-Netzwerkrichtlinien isoliert und der Zugriff mithilfe von Kubernetes-RBAC (Role-based Access Control) eingeschränkt werden.

Planen Sie, wie Sie Namespaces zuweisen möchten, bevor Sie mit dem Deployment von Workloads in Ihren Clustern beginnen. Ein Namespace pro Anwendung bietet die beste Möglichkeit zur Kontrolle, verursacht jedoch zusätzlichen Verwaltungsaufwand beim Zuweisen von RBAC-Rollenberechtigungen und Standardnetzwerkrichtlinien. Die Entscheidung, mehr als eine Anwendung in einem Namespace zu gruppieren, sollte hauptsächlich davon abhängen, ob diese Anwendungen gemeinsame RBAC-Anforderungen haben und ob es sicher wäre, diese Berechtigungen den Service-Accounts und Nutzern zu erteilen, die in diesem Namespace Kubernetes-API-Zugriff benötigen.

Im Allgemeinen versteht man unter Konfigurationsmanagement die technische Praxis, Richtlinien für Konfigurationen festzulegen und sicherzustellen, dass diese Richtlinien im gesamten Unternehmen während des gesamten Anwendungs-Lifecycles konsistent angewendet werden. Konfigurationen sind ein kritischer Bestandteil beim Management von Sicherheitsrisiken in cloudnativen Anwendungen, insbesondere weil viele Standardkonfigurationen für Container und Kubernetes nicht sicher sind. Fehlkonfigurationen sind die häufigste Ursache für Sicherheitsrisiken bei containerisierten Anwendungen, die auf Kubernetes ausgeführt werden.

Das Konfigurationsmanagement muss automatisiert werden. Dabei müssen die Rahmenbedingungen zentral verwaltet werden, damit einzelne Entwickler oder Operatoren nicht für die manuelle Konfiguration von Workloads verantwortlich sind. Diese Rahmenbedingungen sollten auf den Sicherheitsrichtlinien der Organisation basieren.

Laut IBM werden 95 % der Cloud-Sicherheitsausfälle durch menschliches Versagen verursacht. Da Anwendungen immer komplizierter werden und auf verteilten Systemen in Containern und auf Kubernetes ausgeführt werden, wächst das Risiko von Fehlkonfigurationen. Ohne ein zentralisiertes Konfigurationsmanagementtool ist es für Unternehmen nahezu unmöglich sicherzustellen, dass Konfigurationsrichtlinien konsistent angewendet werden. Für Unternehmen mit einer Multi-Cloud- oder Hybrid Cloud-Infrastruktur ist eine konsistente Konfiguration noch schwieriger, da jede Umgebung eine andere Konfiguration erfordert. Es gibt auch eine anhaltende Qualifikationslücke unter Entwicklern und Operatoren, die sich nicht immer der Best Practices für eine sichere Konfiguration bewusst sind.

In vielen Fällen bietet der einfachste Weg für Entwickler, Konfigurationen für die Ausführung ihrer Anwendungen festzulegen, auch am wenigsten Sicherheit, wie das Gewähren von Root-Zugriff, das Gewähren von Administratorrechten oder das Festlegen sehr hoher Ressourcengrenzen. Mit den richtigen Tools kann das Konfigurationsmanagement in den DevOps-Workflow integriert werden, damit die Entwicklungsgeschwindigkeit nicht gebremst wird. Dies ist eine Best Practice, da der Widerspruch zwischen einem schnellen Release und der Sicherheit in Workload-Konfigurationen beseitigt wird.

Das Konfigurationsmanagement sollte die Möglichkeit beinhalten, sowohl Einblick in Konfigurationen zu erhalten als auch Rahmenbedingungen für die zulässigen Konfigurationen festzulegen, damit unsichere Builds oder riskante Deployments rechtzeitig automatisch zum Scheitern gebracht werden. Unternehmen benötigen eine zentrale Übersicht, um alle relevanten Konfigurationen in Containern und Kubernetes anzuzeigen und vor potenziell riskanten Konfigurationen gewarnt zu werden.

Die Eckpfeiler des Konfigurationsmanagements für Container und Kubernetes sind:

  • Role-based Access Controls (RBAC). Organisationen müssen zu permissive Konfigurationen und/oder unnötige Rollen identifizieren.
  • Secrets. Ein gutes Tool für das Konfigurationsmanagement kann den Zugriff auf Secrets proaktiv einschränken.
  • Richtlinienbasierte Bewertungen. Das Festlegen von Sicherheitsrichtlinien für Unternehmen ist ein wesentlicher Bestandteil des Sicherheitsstatus, und es sollte eine Möglichkeit geben, Deployments anhand dieser vordefinierten Richtlinien zu überprüfen.
  • Berechtigungen: Berechtigungen sollten nach dem Prinzip der geringsten Privilegien zugewiesen werden.
  • Ressourcenlimits: Sowohl für Container als auch für Kubernetes-Cluster sollten Beschränkungen für die verfügbare CPU und den verfügbaren Arbeitsspeicher gelten.
  • Netzwerkrichtlinien: Netzwerkrichtlinien sollten die Kommunikation zwischen Teilen der Anwendung so weit wie möglich einschränken, um potenzielle Schäden zu begrenzen, wenn ein Container kompromittiert wird.

Der einfachste erste Schritt beim Konfigurationsmanagement besteht darin, branchenübliche Best Practices wie die CIS-Benchmarks zu befolgen. Mit fortschreitender Einführung von Containern ist das Erstellen von Governance-Richtlinien für die gesamte Organisation eine Best Practice für das Konfigurationsmanagement. Das Konfigurationsmanagement sollte Konfigurationen für Container und für Kubernetes abdecken, da Konfigurationen an beiden Stellen angemessen verwaltet werden müssen, um für einen starken Sicherheitsstatus zu sorgen.

Standardmäßig ermöglicht Kubernetes allen Pods innerhalb eines Clusters uneingeschränkte Kommunikationsmöglichkeiten. Dadurch werden Anwendungsvorgänge vereinfacht, allerdings entsteht auch ein gewisses Sicherheitsrisiko. Obwohl die Standardeinstellungen zu permissiv sind, verfügt Kubernetes auch über integrierte Durchsetzungsfunktionen, die so konfiguriert werden können, dass die Kommunikation zwischen Assets eingeschränkt wird. Ein Teil der Einschränkung der Kommunikation zwischen Teilen des Deployments ist die Netzwerksegmentierung. Die Netzwerksegmentierung ist auch für bestimmte Compliance-Frameworks (z. B. PCI-DSS) erforderlich.

Bei der Netzwerksegmentierung werden Netzwerke in kleinere Subnetzwerke unterteilt. In Bezug auf die Sicherheit besteht der Hauptvorteil darin, dass die Netzwerksegmentierung böswillige Akteure daran hindert, auf alle Apps in einem Kubernetes-Cluster zuzugreifen, falls sie Zugriff auf eine Anwendung erhalten, die auf dem Cluster mit anderen Anwendungen ausgeführt wird. Es ist auch eine Möglichkeit, sensible Workloads und/oder Workloads, die in den Geltungsbereich eines bestimmten Compliance-Frameworks fallen, von anderen Teilen der Anwendung zu isolieren.

Netzwerkrichtlinien sollten so restriktiv wie möglich sein, damit einzelne Container nur mit den Containern kommunizieren können, die für die vorgesehene Funktion der Anwendung erforderlich sind.

In Kubernetes erfolgt die Netzwerksegmentierung mittels Durchsetzung von Netzwerkrichtlinien, sowohl durch die nativen Netzwerkdurchsetzungsfunktionen von Kubernetes als auch durch die Verwendung zusätzlicher Infrastrukturschichten wie einem Service Mesh.

Standardmäßig gibt es keine Einschränkungen für die Kommunikation zwischen Pods, Containern und Nodes, weder innerhalb desselben Namespace noch zwischen Namespaces. Die Einführung von Netzwerkrichtlinien zur Einschränkung der Kommunikation, gewöhnlich mit einer Richtlinie, die jegliche Kommunikation verweigert, ist ein guter Ausgangspunkt für eine Best Practice. Da Pods miteinander kommunizieren müssen, ist es am besten, alle anderen Pods, mit denen ein bestimmter Pod kommunizieren muss, systematisch aufzulisten. Ingress aus und Egress in das öffentliche Internet sollte ebenfalls auf Basis einer Zulassungsliste nur für die Pods zugelassen werden, die dies benötigen.

Es besteht auch ein gewisses Betriebsrisiko im Zusammenhang mit sich ändernden Netzwerkrichtlinien und einer zunehmenden Netzwerksegmentierung. Die Verwendung eines Tools zur Visualisierung der Auswirkungen von Änderungen an systemweiten Netzwerkrichtlinien auf die Anwendung kann dazu beitragen, das Risiko unerwarteter Folgen durch die Anpassung von Netzwerkrichtlinien zu minimieren.

Keine Organisation hat jemals eine perfekt sichere Anwendung oder IT-Infrastruktur. Sicherheit erfordert die Priorisierung und das Verständnis der Risiken und Kompromisse, die mit verschiedenen Aktionen verbunden sind. Risikoprofiling ist der Prozess, bei dem die bekannten Sicherheitsrisiken der Organisation und ihre Richtlinien und Praktiken im Zusammenhang mit dem Management dieser Risiken skizziert werden. Jede Organisation muss einen gewissen Grad an Risiken akzeptieren, sollte sich jedoch darüber im Klaren sein, wie viel Risiko akzeptabel ist. Risikoprofiling sollte nicht nur für die Organisation als Ganzes, sondern für einzelne Anwendungen erfolgen. Sensible Workloads oder Workloads, die Compliance-Anforderungen unterliegen, haben ein anderes Risikoprofil als nicht sensible Workloads.

Risikoprofiling hilft auch bei der Bewertung der Bedeutung von Schwachstellen, die in der Umgebung vorhanden sind. Es wäre unmöglich, auf jede Schwachstelle zu reagieren. Daher erfordert ein starker Sicherheitsstatus die Bewertung des Risikos jeder Schwachstelle, um deren Behebung korrekt zu priorisieren.

In einer verteilten, containerisierten Anwendung kann es schwierig sein, das Risikoprofil einer Anwendung zu verstehen und zu priorisieren. In jeder potenziellen Anwendung können Hunderte von Schwachstellen vorhanden sein, aber nicht alle Schwachstellen bergen das gleiche Risiko. Für das Sicherheitsrisiko einer Schwachstelle sind beispielsweise folgende Faktoren ausschlaggebend:

  • Der Schweregrad der Schwachstelle
  • Ob die Anwendung öffentlich ist oder nicht
  • Ob die Anwendung produktionsrelevant ist
  • Ob die Anwendung in den Geltungsbereich von Compliance-Vorschriften fällt
  • Ob die Anwendung Zugriff auf sensible Daten hat
  • Die Berechtigungen des Containers
  • Die Netzwerkeinbindung des Containers

Obwohl Unternehmen im Voraus festlegen sollten, welcher Risikograd akzeptabel ist, indem sie regelmäßig interne Richtlinien aufstellen, wie schnell Schwachstellen aller Schweregrade behoben werden müssen, ist das Risikoprofiling mehr als eine gleichbleibende Routine. Der Prozess der Bewertung von Sicherheitsrisiken, insbesondere im Kontext containerisierter Anwendungen, muss während der Runtime kontinuierlich erfolgen.

Das manuelle Festlegen der Handlungsreihenfolge bei potenziellen Sicherheitsvorfällen, Schwachstellen und Richtlinien kann zu Fehlern und Burnout führen. Besonders in großem Umfang ist ein Risikoprofiling oft einfach nicht möglich, ohne sich auf automatisierte Tools zu verlassen, um Sicherheitsrisiken aufzudecken und zu priorisieren. Erfolgreiches Risikoprofiling in Kubernetes sollte die deklarativen, kontextbezogenen Daten von Kubernetes nutzen, um den Priorisierungsprozess zu automatisieren. Auf diese Weise können sich Sicherheitsteams darauf konzentrieren, die Deployments mit dem höchsten Risiko zuerst zu korrigieren, anstatt Zeit mit dem Risikoprofiling zu verschwenden.

Idealerweise kann Risikoprofiling sowohl als reaktives als auch als proaktives Tool verwendet werden. Wenn Risiken in einem Deployment gefunden und behoben werden, können diese Informationen verwendet werden, um andere Deployments mit ähnlichen Risikofaktoren zu finden und potenzielle Sicherheitsrisiken im Voraus proaktiv anzugehen.

Die Laufzeitsicherheit ist eine kritische Abwehrmaßnahme gegen böswillige Akteure. Im Idealfall werden alle ungepatchten Schwachstellen, unsicheren Konfigurationen oder unsicheren Zugangsdaten in der Build- oder Deployment-Phase abgefangen. In Wirklichkeit ist die Erkennung und Reaktion zur Laufzeit jedoch unerlässlich, da Schwachstellen manchmal in diesen früheren Phasen durchgehen und neue Schwachstellen erst im laufenden Betrieb entdeckt werden. Sie ist auch aus Compliance-Gründen und als Abwehrmaßnahme gegen interne Bedrohungen wichtig.

Deklarative, unveränderliche Workloads erfordern ein völlig neues Modell zum Erkennen von und Reagieren auf potenzielle Sicherheitsvorfälle zur Laufzeit. Die Tatsache, dass Container gewöhnlich eine minimale Anzahl von Prozessen ausführen, kombiniert mit dem deklarativen Charakter von Kubernetes, macht einige Aspekte der Laufzeitsicherheit tatsächlich einfacher als bei Anwendungen, die auf virtuellen Maschinen (VM) basieren. Auf der anderen Seite sollten laufende Container nicht so „gepatcht“ werden, wie Sicherheits-Patches auf eine VM-basierte App angewendet würden. Stattdessen sollten sie als unveränderlich behandelt und entsprechend gelöscht, aktualisiert und neu gestartet werden.

Die Erkennung ist die Basis der Laufzeitsicherheit. Dazu gehört, dass eine Baseline für das Verhalten der Anwendung festgelegt und jede Aktivität untersucht wird, die zu weit von der Baseline abweicht. Einige der Aktivitäten, die verfolgt werden können, sind Netzwerkanforderungen und Prozessausführungen. Wenn diese Aktivitäten von den Erwartungen abweichen, kann dies ein Zeichen für potenziell verdächtige oder böswillige Aktivitäten sein. Zum Beispiel, wenn eine Verbindung zum Internet hergestellt wird, obwohl dies nicht zulässig ist. In jedem Fall würde diese Art von anomalem Verhalten auf etwas hinweisen, was angegangen werden muss.

Die Anomalieerkennung kann in Containern genauer sein als bei VM-basierten Workloads, da Container nur eine Anwendung enthalten. Dadurch kann einfacher abgegrenzt werden, was zum Baseline-Verhalten eines Containers gehört und was nicht. Die Anomalieerkennung sollte jedoch immer auch mit einem Prozess zur Reaktion auf Vorfälle verbunden sein.

Je nach Art des anomalen Verhaltens besteht die beste Vorgehensweise möglicherweise darin, automatisch zu reagieren, indem die Plattform die betroffenen Pods oder Container löscht. In anderen Fällen kann es sinnvoller sein, eine Warnung zu senden und das Verhalten manuell auszuwerten. Die Reaktion auf potenzielle Vorfälle sollte jedoch so automatisiert wie möglich sein, um die Reaktionszeiten zu minimieren und die allgemeine Sicherheit containerisierter Anwendungen zu verbessern.

Das Kubelet ist der wichtigste „Node Agent“, der auf den Nodes ausgeführt wird. Eine Fehlkonfiguration kann eine Vielzahl von Sicherheitsrisiken nach sich ziehen. Zur Konfiguration des Kubelets können Sie Argumente für die ausführbare Datei des ausgeführten Kubelets oder eine Kubelet-Konfigurationsdatei verwenden.

Führen Sie den folgenden Befehl aus, um nach der Kubelet-Konfigurationsdatei zu suchen:

ps -ef | grep kubelet | grep config

Suchen Sie nach dem Argument --config, das den Speicherort der Kubelet-Konfigurationsdatei angibt.

Führen Sie dann auf jedem Node den folgenden Befehl aus:

ps -ef | grep kubelet

Stellen Sie in der Ausgabe Folgendes sicher:

Das Argument --anonymous-auth ist auf false gesetzt. In dem zuvor erwähnten Kubelet-Artikel war eine der ausgenutzten Fehlkonfigurationen, dass anonyme (und nicht authentifizierte) Anfragen vom Kubelet-Server bedient werden durften.

Das Argument --authorization-mode wird als AlwaysAllow angezeigt, sofern vorhanden. Wenn es nicht vorhanden ist, stellen Sie sicher, dass eine durch --config angegebene Kubelet-Konfigurationsdatei vorhanden ist und in dieser Datei „authorisation: mode“ auf etwas anderes als AlwaysAllow gesetzt ist.

Das Argument --client-ca-file ist vorhanden und auf den Speicherort der Client-Zertifizierungsstellendatei festgelegt. Wenn es nicht vorhanden ist, stellen Sie sicher, dass eine durch --config angegebene Kubelet-Konfigurationsdatei vorhanden ist und in dieser diese Datei authentication: x509: clientCAFile auf den Speicherort der Client-Zertifizierungsstellendatei gesetzt ist.

Das Argument --read-only-port ist vorhanden und auf 0 gesetzt. Wenn es nicht vorhanden ist, stellen Sie sicher, dass eine durch --config angegebene Kubelet-Konfigurationsdatei vorhanden ist und readOnlyPort auf 0 gesetzt ist, sofern vorhanden.

Das Argument --protect-kernel-defaults ist auf true gesetzt. Wenn es nicht vorhanden ist, stellen Sie sicher, dass eine durch --config angegebene Kubelet-Konfigurationsdatei vorhanden ist und in dieser Datei protectKernelDefaults auf true gesetzt ist.

Das Argument --hostname-override ist nicht vorhanden, um sicherzustellen, dass das TLS-Setup zwischen dem Kubelet und dem API-Server nicht unterbrochen wird.

Das Argument --event-qps ist vorhanden und auf 0 gesetzt. Wenn es nicht vorhanden ist, stellen Sie sicher, dass eine durch --config angegebene Kubelet-Konfigurationsdatei vorhanden ist und eventRecordQPS auf 0 gesetzt ist.

Die Argumente --tls-cert-file und --tls-private-key-file sind ordnungsgemäß festgelegt, oder die durch --config angegebene Kubelet-Konfiguration enthält die entsprechenden Einstellungen für tlsCertFile und tlsPrivateKeyFile. Diese Konfiguration stellt sicher, dass alle Verbindungen über TLS auf den Kubelets erfolgen.

RotateKubeletServerCertificate und --rotate-certificates sind auf true gesetzt, wenn Ihre Kubelets ihre Zertifikate vom API-Server beziehen. Stellen Sie außerdem sicher, dass Ihr Kubelet nur starke Verschlüsselungscodes verwendet.

Der Kubernetes-API-Server verarbeitet die REST-API-Aufrufe von Nutzern oder Anwendungen, die innerhalb des Clusters ausgeführt werden, um die Cluster-Verwaltung zu ermöglichen. Der API-Server wird als Gateway zur Kubernetes Control Plane betrachtet. Sie können über kubectl, Client-Bibliotheken oder direkt über API-Anfragen darauf zugreifen. Eine Möglichkeit, die Autorisierung für den Kubernetes-API-Server zu verwalten, ist die Verwendung von Kubernetes-RBAC (Role-based Access Control). Sie können Anfragen an den API-Server auch mithilfe von Admission Controllern validieren.

Der erste Schritt zum Schutz eines API-Servers ist die Zugangskontrolle. Das Center for Internet Security (CIS) bietet Best Practices für die Konfiguration zum Härten und Sichern des API-Servers.

Führen Sie den folgenden Befehl auf Ihrem Master-Node aus:

ps -ef | grep kube-apiserver

Stellen Sie in der Ausgabe Folgendes sicher:

Das Argument --anonymous-auth ist auf false gesetzt. Mit dieser Einstellung wird sichergestellt, dass Anfragen, die von anderen Authentifizierungsmethoden nicht zurückgewiesen wurden, nicht als anonym behandelt und daher gemäß der Richtlinie zugelassen werden.

Das Argument --basic-auth-file ist nicht vorhanden. Bei der Basisauthentifizierung werden für die Authentifizierung Klartext-Zugangsdaten anstelle der bevorzugten Tokens oder Zertifikate verwendet.

Das Argument --insecure-allow-any-token ist nicht vorhanden. Durch diese Einstellung wird sichergestellt, dass nur authentifizierte sichere Tokens zulässig sind.

Das Argument –kubelet-https ist nicht vorhanden oder ist auf true gesetzt. Durch diese Konfiguration wird sichergestellt, dass Verbindungen zwischen dem API-Server und den Kubelets während der Übertragung über TLS (Transport Layer Security) geschützt sind.

Das Argument --insecure-bind-address ist nicht vorhanden. Durch diese Konfiguration wird verhindert, dass sich der API-Server an eine unsichere Adresse bindet. Ein nicht authentifizierter und unverschlüsselter Zugriff auf Ihren Master-Node wird verhindert. Dadurch wird das Risiko minimiert, dass Angreifer möglicherweise sensible Daten während der Übertragung lesen.

Das Argument --insecure-port ist auf 0 gesetzt. Durch diese Einstellung wird verhindert, dass der API-Server einen unsicheren Port verwendet. Ein nicht authentifizierter und unverschlüsselten Zugriff auf den Master-Node wird verhindert. Dadurch wird das Risiko minimiert, dass ein Angreifer die Kontrolle über den Cluster übernimmt.

Das Argument --secure-port ist entweder nicht vorhanden oder wird als eine Ganzzahl zwischen 1 und 65535 angezeigt. Das Ziel hier besteht darin sicherzustellen, dass Ihr gesamter Datenverkehr über HTTPS mit Authentifizierung und Autorisierung bereitgestellt wird.

Das Argument --profiling wird als false angezeigt. Der Profiler ist nur erforderlich, wenn Sie Engpässe haben oder Fehler beheben müssen. Er würde lediglich unnötige System- und Programmdetails erzeugen.

Das Argument --repair-malformed-updates wird als false angezeigt. Durch diese Einstellung wird sichergestellt, dass absichtlich falsch formatierte Anfragen von Clients vom API-Server zurückgewiesen werden.

Das Argument --enable-admission-plugins ist auf einen Wert gesetzt, der AlwaysAdmit nicht enthält. Wenn Sie diese Einstellung auf „AlwaysAdmit“ setzen, werden Anfragen auch dann zugelassen, wenn sie vom Plugin für die Zugangskontrolle nicht ausdrücklich zugelassen werden. Dies würde die Effektivität des Plugins verringern.

Das Argument --enable-admission-plugins ist auf einen Wert gesetzt, der AlwaysPullImages enthält. Durch diese Konfiguration wird sichergestellt, dass Nutzer keine Images vom Node abrufen und an einen Pod übertragen dürfen, wenn sie lediglich den Namen des Images kennen. Wenn diese Kontrolle aktiviert ist, werden Images vor dem Starten eines Containers, für den gültige Zugangsdaten erforderlich sind, immer abgerufen.

Das Argument --enable-admission-plugins ist auf einen Wert gesetzt, der SecurityContextDeny enthält. Durch diese Kontrolle wird sichergestellt, dass der Sicherheitskontext auf Pod-Ebene nur auf eine Weise angepasst werden kann, die in der Pod-Sicherheitsrichtlinie beschrieben ist.

Das Argument --disable-admission-plugins ist auf einen Wert gesetzt, der NamespaceLifecycle nicht enthält. Diese Kontrolle sollte nicht deaktiviert werden, da sie sicherstellt, dass keine Objekte in nicht vorhandenen Namespaces oder in Namespaces erstellt werden, die beendet werden sollen.

Das Argument --audit-log-path ist auf einen geeigneten Pfad gesetzt, in dem Ihre Auditprotokolle gespeichert werden sollen. Es ist immer eine gute Sicherheitspraxis, das Auditing für alle Kubernetes-Komponenten zu aktivieren, sofern verfügbar, einschließlich des Kubernetes-API-Servers.

Das Argument --audit-log-maxage ist auf 30 oder eine beliebige Anzahl von Tagen festgelegt, für die Sie Ihre Auditprotokolldateien speichern müssen, um die internen und externen Richtlinien zur Datenaufbewahrung einzuhalten.

Das Argument --audit-log-maxbackup ist auf 10 oder eine beliebige Zahl gesetzt, die Ihnen hilft, Ihre Compliance-Anforderungen für die Aufbewahrung der Anzahl alter Protokolldateien zu erfüllen.

Das Argument --audit-log-maxsize ist auf 100 oder eine beliebige Zahl gesetzt, die Ihnen hilft, Ihre Compliance-Anforderungen zu erfüllen. Beachten Sie, dass die Zahl 100 für 100 MB steht.

Das Argument --authorization-mode ist vorhanden und nicht auf AlwaysAllow festgelegt. Durch diese Einstellung wird sichergestellt, dass nur autorisierte Anfragen vom API-Server zugelassen werden, insbesondere in Produktions-Clustern.

Das Argument --token-auth-file ist nicht vorhanden. Dieses Argument verwendet, falls vorhanden, eine statische tokenbasierte Authentifizierung, die mehrere Sicherheitslücken aufweist. Verwenden Sie stattdessen alternative Authentifizierungsmethoden, beispielsweise Zertifikate.

Das Argument --kubelet-certificate-authority ist vorhanden. Diese Einstellung hilft, einen Man-in-the-Middle-Angriff zu verhindern, wenn eine Verbindung zwischen dem API-Server und dem Kubelet besteht.

Die Argumente --kubelet-client-certificate und --kubelet-client-key sind vorhanden. Durch diese Konfiguration wird sichergestellt, dass sich der API-Server bei den HTTPS-Endpunkten des Kubelets authentifiziert. (Standardmäßig führt der API-Server diesen Schritt nicht aus.)

Das Argument --service-account-lookup ist vorhanden und auf true gesetzt. Durch diese Einstellung wird verhindert, dass der API-Server nur die Gültigkeit des Authentifizierungstokens überprüft, ohne sicherzustellen, dass das in der Anforderung enthaltene Service-Account-Token in etcd vorhanden ist.

Das Argument --enable-admission-plugins ist auf einen Wert gesetzt, der SecurityContextPolicy enthält.

Das Argument --service-account-key-file ist vorhanden und auf ein separates öffentliches/privates Schlüsselpaar zum Signieren von Service-Account-Tokens festgelegt. Wenn Sie kein öffentliches/privates Schlüsselpaar angeben, wird der private Schlüssel aus dem TLS-Zertifikat verwendet, was Ihre Möglichkeit zum Rotieren der Schlüssel für Service-Account-Tokens verhindern würde.

Die Argumente --etcd-certfile und --etcd-keyfile sind vorhanden, damit sich der API-Server mit dem Clientzertifikat und dem Schlüssel beim etcd-Server identifiziert. Beachten Sie, dass etcd Objekte speichert, die wahrscheinlich sensibler Natur sind, sodass alle Client-Verbindungen die TLS-Verschlüsselung verwenden müssen.

Das Argument --disable-admission-plugins ist festgelegt und enthält kein ServiceAccount. Diese Konfiguration stellt sicher, dass beim Erstellen eines neuen Pods kein Standard-Service-Account innerhalb desselben Namespace verwendet wird.

Die Argumente --tls-cert-file und --tls-private-key-file sind vorhanden, damit der API-Server nur HTTPS-Datenverkehr über TLS überträgt.

Das Argument --client-ca-file ist vorhanden, um sicherzustellen, dass die TLS- und Clientzertifikat-Authentifizierung für Kube-Clusterbereitstellungen konfiguriert ist.

Das Argument --etcd-cafile ist vorhanden und ist so festgelegt, dass sich der API-Server über die SSL-Zertifizierungsstellendatei beim etcd-Server verifizieren muss.

Das Argument --tls-cipher-suites ist so festgelegt, dass starke Verschlüsselungscodes verwendet werden.

Das Argument --authorization-mode ist vorhanden und auf einen Wert gesetzt, der Node enthält. Diese Konfiguration schränkt ein, welche Objekte Kubelets lesen können, die ihren Nodes zugeordnet sind.

Das Argument --enable-admission-plugins ist festgelegt und enthält den Wert NodeRestriction. Dieses Plugin stellt sicher, dass ein Kubelet nur sein eigenes Node-API-Objekt und die mit seinem Node verknüpften Pod-API-Objekte ändern darf.

Das Argument --encryption-provider-config ist auf eine EncryptionConfig-Datei festgelegt, und diese Datei sollte über alle erforderlichen Ressourcen verfügen. Durch diese Einstellung wird sichergestellt, dass alle im etcd-Schlüsselwertspeicher gespeicherten REST-API-Objekte im Ruhezustand verschlüsselt werden.

Stellen Sie sicher, dass der aescbc-Verschlüsselungsanbieter für alle gewünschten Ressourcen verwendet wird, da dieser als einer der stärksten gilt.

Das Argument --enable-admission-plugins enthält den Wert EventRateLimit, um die Anzahl der vom API-Server akzeptierten Events zur Leistungsoptimierung des Clusters zu begrenzen.

Das Argument --feature-gates ist nicht auf einen Wert gesetzt, der AdvancedAuditing=false enthält. Dadurch stellen Sie sicher, dass das erweiterte Auditing für Auditing- und Untersuchungszwecke nicht deaktiviert ist.

Das Argument --request-timeout ist entweder nicht festgelegt oder auf einen geeigneten Wert gesetzt (weder zu kurz noch zu lang). Der Standardwert ist 60 Sekunden.

Das Argument --authorization-mode ist vorhanden und auf einen Wert gesetzt, der Kubernetes-RBAC enthält.

Diese Einstellung stellt sicher, dass RBAC aktiviert ist. Neben dem einfachen Aktivieren sollten Sie mehrere andere Empfehlungen zur optimalen Verwendung von RBAC befolgen, darunter:

  • Vermeiden Sie es, Nutzern die Rolle des Cluster-Administrators zuzuweisen, da sie sehr weitreichende Befugnisse über die Umgebung erteilt und wenn überhaupt nur sehr sparsam verwendet werden sollte.
  • Überprüfen Sie Ihre Rollenaggregationsregeln, um sicherzustellen, dass Sie sie richtig verwenden.
  • Erteilen Sie Subjekten keine doppelten Berechtigungen, da dies den Widerruf des Zugriffs erschweren kann.
  • Entfernen Sie regelmäßig nicht verwendete Rollen.

Die Sicherheitsproblematik bei Standardeinstellungen

Eines der größten Risiken bei Containern und Kubernetes besteht darin, dass die Standardkonfigurationen beider Technologien nicht sicher sind. Um das Risiko eines Sicherheitsvorfalls zu reduzieren, müssen diese Standardkonfigurationen im gesamten Unternehmen proaktiv geändert werden. Die Vernachlässigung dieses Schrittes durch Übersehen, fehlendes Wissen oder Workflows, die kein Konfigurationsmanagement beinhalten, führt zu unnötig anfälligen Workloads.

 

Standardeinstellungen in Containern

Viele Container-Standardeinstellungen sowie gängige Verfahren beim Erstellen von Containern können die Container anfällig machen. Hier sind einige Dinge, auf die Sie beim Konfigurieren von Containern achten sollten.

  • Geben Sie einen Nutzer an. Wenn Sie keinen Nutzer angeben, wird standardmäßig der Root-Nutzer verwendet, wodurch der Container möglicherweise Root-Zugriff auf den Host erhält.
  • Verifizieren Sie Images. Standardeinstellungen erzwingen keine Image-Verifizierung, was dazu führt, dass beschädigte Images unwissentlich abgerufen werden.
  • Legen Sie Ressourcenlimits fest. Ressourcenlimits können konfiguriert werden, es gibt jedoch keine Standardlimits. Durch ein Begrenzen der CPU und des Arbeitsspeichers, die ein Container verbrauchen kann, können Sie verhindern, dass der Container große Mengen an Ressourcen verbraucht, wenn er beschädigt wird.
  • Installieren Sie Tools und Libraries selektiv. Je weniger Tools und Libraries sich in den Containern befinden, desto weniger Tools kann ein Angreifer ausnutzen, wenn er Zugriff auf den Container erhält. Stellen Sie sicher, dass Sie in jedem Container nicht einfach bestimmte Standardtools installieren, sondern nur die Tools, die tatsächlich benötigt werden.
  • Kontrollieren Sie den Zugriff auf die Registry mithilfe von Zulassungslisten. Stellen Sie sicher, dass sämtliche von Ihnen verwendeten Images aus vertrauenswürdigen Quellen stammen, und kontrollieren Sie den Zugriff auf die Registry, idealerweise durch Zulassungslisten mit vertrauenswürdigen Nutzern.

Standardeinstellungen in Kubernetes

Kubernetes bietet auch viele Tools zur Verbesserung des Sicherheitsstatus für Unternehmen, die jedoch aktiv konfiguriert werden müssen, um Sicherheitsvorteile zu bieten. Hier sind einige grundlegende Dinge, die Sie in Kubernetes überprüfen sollten.

  • Konfigurieren Sie RBAC (Role-based Access Controls). RBAC ist in Kubernetes 1.6 und höher standardmäßig aktiviert, muss jedoch noch richtig konfiguriert werden, um die entsprechenden Vorteile zu bieten. Idealerweise sollte der Zugriff über Namespaces und nicht über Cluster bereitgestellt werden.
  • Verwenden Sie Namespaces. Standardmäßig wird alles im gleichen Namespace ausgeführt. Verwenden Sie aktiv die von Namespaces bereitgestellte Trennung, um Workloads voneinander zu isolieren.
  • Verwenden Sie Kubernetes-Netzwerkrichtlinien. Da keine Netzwerkrichtlinien vorkonfiguriert sind, müssen Unternehmen ein Netzwerk-Plugin installieren, um den Ingress- und Egress-Datenverkehr von der Anwendung zu kontrollieren und die Richtlinien entsprechend zu konfigurieren.
  • Aktivieren Sie die Auditprotokollierung. Die Auditprotokollierung ist normalerweise nicht standardmäßig aktiviert. Sie sollte jedoch aktiviert werden, um einen Einblick in anomale API-Aufrufe und Autorisierungsfehler zu erhalten.

Das Risiko, nichts zu tun

Normalerweise sind Entwicklungsteams ohne tiefgehende Sicherheitsexpertise die ersten, die Container und Kubernetes verwenden. Das Ignorieren der Sicherheit setzt Unternehmen jedoch Risiken aus, unabhängig von der Art der verwendeten Infrastruktur.

Wie bereits erwähnt, sind Konfigurationen in Containern und Kubernetes standardmäßig nicht sicher. Die nativen Sicherheitsfunktionen von Kubernetes müssen aktiv konfiguriert werden, um Sicherheitsvorteile zu bieten. Der schnellste und einfachste Weg bei der Inbetriebnahme einer Anwendung besteht oft darin, ihr zu viele Berechtigungen zu erteilen und/oder die Ressourcenlimits viel höher festzulegen, als für die Anwendung erforderlich ist – oder einfach die Standardeinstellungen unverändert zu lassen. Unternehmen können versucht sein, die Sicherheit zunächst zweitrangig zu behandeln, insbesondere wenn sie sich erst mit Containern und Kubernetes vertraut machen. Sie sind dadurch jedoch einem großen Risiko ausgesetzt. Böswillige Akteure können containerisierte Anwendungen auf Kubernetes genauso einfach ausnutzen wie Legacy-Anwendungen.

Wenn Sie keine Sicherheitsmaßnahmen ergreifen, besteht das Hauptrisiko darin, dass die Anwendung durch böswillige Akteure beschädigt werden kann. Wie katastrophal dies wäre, hängt von der Branche des Unternehmens, der Art der verwendeten Anwendung sowie dem Umfang und der Art des Verstoßes ab. Die Wahrscheinlichkeit, dass eine Vernachlässigung der Sicherheit zu einem Vorfall führt, hängt auch von anderen Faktoren ab, beispielsweise ob die Anwendung mit dem Internet verbunden ist.

Wenn Sie keine Sicherheitsmaßnahmen für Ihre containerisierten Anwendungen ergreifen, gehen Sie das Risiko ein, dass Ihre Anwendungen unnötig gefährdet sind. Das Ignorieren der Sicherheit kann folgende Auswirkungen haben:

Ungepatchte Sicherheitslücken: Es werden ständig neue Sicherheitslücken entdeckt, von denen einige schwerwiegend sind. Sowohl die Open Source Community als auch böswillige Akteure wissen von diesen Schwachstellen, sobald sie veröffentlicht werden – es ist riskant, sie nicht schnell zu beheben.

Lockere Berechtigungen: Obwohl RBAC (Role-based Access Control) in Kubernetes standardmäßig aktiviert ist, liegt es am Entwickler, die Zugriffskontrollen einzurichten. Ohne Sicherheitsbewusstsein erstellen Entwickler oft Workloads, die zu viel Zugriff haben.

Nicht isolierte Workloads: Standardmäßig kann alles in einem einzigen Standard-Namespace ausgeführt werden. Die Verwendung von Namespaces zur anfänglichen Isolierung von Workloads ist eine einfache Best Practice für die Sicherheit. Diese Ebene der Isolierung findet nur statt, wenn das entsprechende Sicherheitsbewusstsein besteht.

Keine Kontrolle über Netzwerkrichtlinien: Mit Kubernetes-Netzwerkrichtlinien können Organisationen den Datenverkehr kontrollieren. Hierfür ist allerdings ein Netzwerk-Plugin erforderlich, und die Richtlinien müssen konfiguriert werden.

Die zögerliche Anwendung von Sicherheitskontrollen führt letztendlich zu inkonsistenten Sicherheitspraktiken. Diese sorgen für Probleme bei der Sicherheitsüberprüfung, verringern die Entwicklungsgeschwindigkeit und erhöhen das Risiko von Sicherheitsvorfällen. Unternehmen sollten stattdessen Sicherheitskontrollen frühzeitig und häufig im Softwareentwicklungs-Lifecycle durchführen.

Als De-facto-Container-Orchestrierungssystem ermöglicht Kubernetes das Container-Management, bringt aber auch potenzielle Sicherheitslücken in Infrastrukturumgebungen mit sich. Die Unterschiede zwischen der Sicherheit bei Containern/Kubernetes und virtuellen Maschinen sowie anhaltende mangelnde Kompetenz in Bezug auf die Kubernetes-Sicherheit können zu unnötigen Sicherheitsrisiken führen.

Best Practices für die Kubernetes-Sicherheit umfassen (wie alle Best Practices für die Sicherheit) sowohl Maßnahmen zur Verbesserung der Sicherheit in der Anwendung und der Infrastruktur als auch organisatorische und kulturelle Praktiken, um eine zentrale Kontrolle über die Sicherheit zu erhalten.

Das Erstellen und Durchsetzen von Sicherheitsrichtlinien für Unternehmen ist eine Best Practice, unabhängig davon, auf welchen Technologie-Stack das Unternehmen aufbaut. Sicherheit ist ein Risikomanagement-Prozess. Man kann sich dabei nicht ausschließlich auf Tools verlassen, um zu entscheiden, wie viel Risiko für jede Anwendung akzeptabel ist. Diese Art von Entscheidung muss von Menschen getroffen werden, die abwägen können, wie viel Risiko für die Organisation im Allgemeinen, für einzelne Geschäftsbereiche und für jede Anwendung akzeptabel ist.

Zentrale Kontrolle der Sicherheit: In Bezug auf den ersten Punkt benötigen Unternehmen eine Möglichkeit zur Sicherstellung, dass die von ihnen festgelegten Sicherheits- und Governance-Richtlinien befolgt werden. Zentrale Teams müssen in der gesamten verteilten Anwendung Einblick in Konfigurationen und Schwachstellen haben. Sie müssen die Möglichkeit haben, potenzielle Probleme einfach zu visualisieren und zu priorisieren. Darüber hinaus müssen sie in der Lage sein, Rahmenbedingungen zu erstellen, damit Einzelpersonen sofortiges Feedback erhalten, wenn eine riskante Konfiguration, ein unsicheres Image oder ein anderes potenzielles Sicherheitsrisiko Teil eines Builds ist.

Frühzeitige Einbindung der Sicherheit: Eine möglichst frühe Einbindung der Sicherheit in den Entwicklungsprozess hilft nicht nur, spätere Probleme bei der Sicherheitsprüfung zu vermeiden und Anwendungen schneller bereitzustellen, sondern verringert auch die Wahrscheinlichkeit von Fehlern, die dazu führen, dass Schwachstellen oder Fehlkonfigurationen ausgenutzt werden.

Einsatz von Automatisierung: Insbesondere wenn sich der Kubernetes-Footprint auf mehrere Cluster und Hunderte von Namespaces ausdehnt, ist die manuelle Verwaltung der Konfigurationen oder die Überwachung des Laufzeitverhaltens nicht mehr möglich.

Es gibt auch einige sehr wichtige technische Best Practices, um Kubernetes so sicher wie möglich zu machen.

  • Kubernetes auf dem neuesten Stand halten: Da Sicherheits-Patches nicht immer auch für ältere Versionen veröffentlicht werden, empfiehlt es sich, eine neuere, unterstützte Version auszuführen.
  • RBAC (Role-based Access Control) verwenden: Der Zugriff sollte immer nach dem Prinzip der geringsten Privilegien konfiguriert werden.
  • Kommunikation zwischen Pods einschränken: Die Einschränkungen sollten so restriktiv wie möglich sein, damit die Pods wie vorgesehen funktionieren.
  • Netzwerksegmentierung nutzen. Jeder Pod sollte nur mit den internen oder externen Ressourcen kommunizieren können, die er benötigt, und von allen anderen Ressourcen isoliert bleiben.

Das Schwachstellenmanagement ist eine kritische Komponente für die Sicherheit von Anwendungen. Es umfasst die Prozesse der Identifizierung, Bewertung und Behebung von Sicherheitsschwachstellen in allen Phasen des Softwareentwicklungs-Lifecycles. Das Schwachstellenmanagement in containerisierten, cloudnativen Anwendungen muss automatisiert und in die DevOps-Prozesse zum Erstellen und Versenden von Anwendungen integriert werden. Die Umgebung ist zu komplex, um Schwachstellen manuell zu verwalten. In der Praxis sind Unternehmen versucht, Sicherheitsvorkehrungen zu überspringen, wenn sie die Entwicklungsgeschwindigkeit verlangsamen.

Das Schwachstellenmanagement ist keine Sperre, die die Anwendung passieren muss, sondern ein kontinuierlicher Prozess. Dieser Prozess beginnt mit dem Scannen von Images und der Introspektion in der Build-Phase und setzt sich über den gesamten Lifecycle der Anwendung in Test- und Produktivumgebungen fort.

Das Scannen von Images und die Implementierung von Richtlinien in Bezug auf Image-Schwachstellen während der Build-Phase sind die ersten Schritte zu einem effektiven containernativen Schwachstellenmanagement. Die Möglichkeit, Scans beim Erstellen von Images oder bei der Ausführung von Containern bei Bedarf auszuführen, ist wichtig, um Schwachstellen zu erkennen, die zur Laufzeit aufgedeckt wurden. Das Schwachstellenmanagement muss sowohl in Containern als auch in Kubernetes in der Lage sein, Gefährdungen zu erkennen, da beide die Quelle von Schwachstellen sein können.

Es gibt keine vollständig sichere Anwendung. Doch mit einem guten Schwachstellenmanagement können Teams nicht nur Schwachstellen erkennen, sondern auch zusätzliche Informationen erhalten, um die organisationsspezifische Kritikalität einer bestimmten Schwachstelle zu priorisieren. Beispielsweise hat selbst ein CVE mit hoher Priorität je nach Sensibilität der Workload ein anderes Risikoprofil. Bei einem guten Schwachstellenmanagement geht es darum, Korrekturen auszugleichen, zu bewerten und zu priorisieren, um den bestmöglichen Sicherheitsstatus zu erreichen.

Das Schwachstellenmanagement sollte in erster Linie in cloudnativen Anwendungen automatisiert werden. Für die Definition von Richtlinien ist menschliche Intelligenz erforderlich. Doch für das Finden von Richtlinienverstößen und das Ergreifen geeigneter Maßnahmen basierend auf der Schwachstelle, dem Risikograd und dem Teil des Lifecycles – von automatisch fehlschlagenden Builds bis hin zum Blockieren von Deployments oder deren Skalierung in der Produktion auf Null – sollten Tools verantwortlich sein.

Image- und Schwachstellen-Scanning sollten während der Build-Phase beginnen, müssen jedoch während des gesamten Anwendungs-Lifecycles, einschließlich der Laufzeit, fortgesetzt werden. Es können jederzeit neue Sicherheitsschwachstellen entdeckt werden, und die Fähigkeit, Schwachstellen in laufenden Deployments zu erkennen, ist für den Sicherheitsstatus des Unternehmens von entscheidender Bedeutung. Schwachstellen in laufenden Deployments können zu einem unmittelbaren Sicherheitsrisiko führen, und Unternehmen müssen eine Möglichkeit haben, diese so schnell wie möglich zu erkennen und zu beheben.

In der Build-Phase sollten nicht konforme Images, einschließlich solcher mit schwerwiegenden und behebbaren Schwachstellen, nicht erfolgreich erstellt werden. DevOps-Teams sollten das entsprechende Feedback direkt im CI-System erhalten. Zum Zeitpunkt des Deployments können Sicherheitstools eine Zugangskontrolle anwenden, um automatisch zu verhindern, dass Container mit im Image erkannten bekannten Schwachstellen bereitgestellt werden. Es ist wichtig zu wissen, wie die Behebung in Abhängigkeit vom Schweregrad der Schwachstelle, der Sensibilität der Workload und der allgemeinen Toleranz des Unternehmens gegenüber Sicherheitsrisiken priorisiert werden kann. Unternehmen sollten sich die Zeit nehmen, benutzerdefinierte Richtlinien zu erstellen und Tools zu implementieren, mit denen diese Richtlinien – während des Builds und des Deployments – durch Automatisierung durchgesetzt werden können. Auch nachdem Deployments ausgeführt wurden, sollten Unternehmen weiterhin nach Schwachstellen suchen.

 

Unterschiedliche Funktionen bei Image-Scannern

Nicht alle Image-Scanner bieten das gleiche Maß an umfassenden Prüfungen: Einige scannen nur das zugrunde liegende Betriebssystem, andere scannen auch Libraries, andere führen Prüfungen auf Sprachebene durch und wieder andere scannen Dateiinhalte. Es ist wichtig, einen Image-Scanner zu wählen, dessen Funktionen mindestens den Anforderungen des Unternehmens entsprechen. Außerdem sollte er mit den von Ihren Anwendungen verwendeten Programmiersprachen kompatibel sein.

Einige Image-Scanner führen bei jedem Image-Abruf einen Echtzeit-Scan durch. Doch dieser Ansatz kann die Latenz erhöhen, so dass Unternehmen entscheiden müssen, ob die Echtzeitinformationen den Leistungsabfall rechtfertigen.

 

Scanning zur Laufzeit

Ebenso wie beim Scannen von Images während der Build-Phase verdienen nicht alle erkannten Schwachstellen die gleiche Aufmerksamkeit. Unternehmen benötigen eine Möglichkeit, die Maßnahmen zur Problembehebung basierend auf der Sensibilität der Workload und der Daten, der Internetpräsenz sowie dem Schweregrad der erkannten Schwachstellen zu priorisieren. Jede Organisation hat unterschiedliche Maßnahmen und Servicelevel-Ziele, um auf entdeckte Schwachstellen angemessen zu reagieren. So gibt es beispielsweise Kompromisse, wenn es darum geht, alle Container mit entdeckten Schwachstellen zu blockieren, unabhängig von Schweregrad oder Sensibilität. Ein erfolgreiches Schwachstellen-Scanning in laufenden Deployments erfordert die richtigen Tools, um Transparenz zu gewährleisten und aussagekräftige Informationen zu liefern. Dabei bedarf es durchdachter Sicherheitsrichtlinien im Unternehmen, die ein gutes Gleichgewicht zwischen Schwachstellenmanagement und betrieblichen Auswirkungen finden.

Die Komplexität von Unternehmensnetzwerken und der darin enthaltenen verteilten Anwendungen hat zugenommen. Die Bedrohungsszenarien und Methoden zu einer vertieften Infiltration sind entsprechend nachgezogen. Sichere Perimeter können nur als erste Verteidigungslinie zum Schutz interner Netzwerke dienen, nicht als umfassende Strategie zum Schutz von Infrastruktur und Daten. Robuste Sicherheit erfordert eine Kombination von Kontrollen und Strategien.

Zero-Trust-Networking kann als wichtiger Teil des Sicherheitspuzzles dienen, indem es sich auf die Erhöhung der Sicherheit des internen Anwendungsverkehrs konzentriert. Dieses Modell kippt den lang gehegten Grundsatz, dass der gesamte Datenverkehr innerhalb eines Firewall-Netzwerks authentisch ist, mit der gegenteiligen Annahme: Netzwerkverbindungen dürfen nicht als sicher angesehen werden, bis das Gegenteil bewiesen ist.

Traditionell arbeiteten Netzwerkadministratoren unter der Annahme, dass jede Einheit (ob Anwendung, Server oder Netzwerksoftware oder -hardware) in ihren internen Netzwerken dorthin gehörte und vertrauenswürdig war. Einige Anwendungen erforderten keine Authentifizierung von Clientverbindungen oder verließen sich auf statische, gemeinsam genutzte Zugangsdaten, beispielsweise ein Passwort für eine Datenbank. Alle Anwendungen mussten alle benötigten Authentifizierungs- oder Autorisierungsschemata handhaben, sofern sie überhaupt welche verwendeten. Interne Netzwerkverbindungen verwendeten oft keine Verschlüsselung, nicht einmal für sicherheitsrelevante Services.

Noch immer folgen viele Unternehmensnetzwerke diesem Muster. Allerdings kann ein einzelner böswilliger Akteur, sei es durch einen direkten Hack, einen versehentlich von einer autorisierten Person gesetzten Trojaner oder einfach durch ein Loch in einer Netzwerk-Firewall, verheerende Folgen haben, indem er die lasche Umgebung eines vertrauensvollen Netzwerks ausnutzt. Die dadurch entstehenden Sicherheitslücken mögen zwar begrenzt sein, sie sind jedoch vorhersehbar. Vom Schnüffeln von Klartext-Netzwerkpaketen über das Auffinden von Anwendungspasswörtern für Datenbanken oder andere kritische Systeme bis hin zur Kontrolle über Netzwerkgeräte öffnet dieses Szenario die Tür für inakzeptable Risiken, einschließlich Datenexfiltration oder -verlust.

Zero-Trust ist die Grundlage für eine wachsende Zahl von Security-First-Produktionsinfrastrukturen. Anstatt davon auszugehen, dass jeder Einheit in einem Netzwerk ohne Überprüfung vertraut werden kann, wird davon ausgegangen, dass nichts vertrauenswürdig ist, nicht einmal die Netzwerkinfrastruktur selbst. Das Zero-Trust-Framework bietet keine vorgeschriebene Implementierung oder einen bestimmten Satz von zu verwendenden Technologien. Es beschreibt vielmehr eine Reihe von Prinzipien und Zielen und überlässt die spezifischen technischen Details der Implementierung der jeweiligen Organisation.

Zero-Trust-Architekturen

Zero-Trust-Architekturen folgen im Allgemeinen diesen Prinzipien:

  • Sicherheitskontrollen sollten für alle Einheiten, ob Software oder Hardware, unabhängig von ihrem Netzwerkstandort gleichermaßen gelten.
  • Netzwerkverbindungen sollten sowohl auf Server- als auch auf Clientseite authentifiziert werden. Client-Authentifizierung durch den Server wird mittlerweile generell erwartet. Clients sollten jedoch zusätzlich überprüfen, ob sie mit einem gültigen Server verbunden sind. Verbindungen sollten erneut authentifiziert werden, und Anforderungen sollten nach Bedarf erneut autorisiert werden, wenn sie sich über mehr als eine einzelne Transaktion erstrecken.
  • Berechtigungen sollten nach dem Prinzip der geringsten Privilegien erteilt werden und nur die minimalen Berechtigungen zulassen, die für die Workload eines Clients erforderlich sind.
  • Alle Netzwerkverbindungen und Transaktionen sollten einer kontinuierlichen Überwachung zur Analyse unterzogen werden.

Implementierung des Zero-Trust-Modells in Kubernetes

Wie sieht ein Zero-Trust-Modell in einem Kubernetes-Cluster aus? Obwohl es keine vorgeschriebene Methodik zur Implementierung von Zero-Trust-Prinzipien innerhalb eines Kubernetes-Clusters gibt, haben sich Service Meshes als beliebte Lösung für viele der Ziele der Architektur herausgestellt.

Service Meshes bilden eine virtualisierte Netzwerkschicht, um verteilte Anwendungs-Services zu verbinden und zu steuern. Während sich die meisten Service-Mesh-Lösungen anfangs nicht auf die Netzwerksicherheit konzentrierten, sondern auf die Erleichterung und das Management von intelligenter Service Discovery und Anfrage-Routing, bieten die beliebtesten Open Source-Projekte heute Funktionen, die zu einer Zero-Trust-Architektur passen. Viele Service Meshes versuchen, ein Overlay zu erstellen, das keine Modifikation einzelner Anwendungen erfordert. Aufwändige Änderungen, die zur Einführung strenger Authentifizierungs- und Autorisierungskontrollen erforderlich sind, werden weitgehend vermieden.

Service Meshes, die Kubernetes unterstützen, verwenden in der Regel dezentrales Punkt-zu-Punkt-Routing, bei dem jedem einzelnen Cluster-Pod eine eigene Proxy-Instanz zugewiesen wird. Diese Proxys können Client-TLS-Zertifikate verwalten, mit denen der Proxy seine Identität nachweisen kann, wenn er Verbindungen zu anderen Services herstellt oder Verbindungen von anderen Clients empfängt. Diese Verwendung von TLS-Zertifikaten zum Nachweis der Identität auf Client- und Serverseite wird als mTLS (Mutual Transport Layer Security) bezeichnet. mTLS dient neben der Verbindungsauthentifizierung auch zur Verschlüsselung der Netzwerkverbindung. Neben Authentifizierung und Over-the-Wire-Verschlüsselung unterstützen verschiedene Service Meshes verschiedene Autorisierungsquellen, von statischen Listen bis hin zu Integrationen mit Single Sign-On oder anderen Services von Drittanbietern.

Service Meshes bieten keine vollständige Zero-Trust-Lösung für Kubernetes-Cluster, aber sie bieten eine Reihe ihrer wichtigsten Vorteile. Auch wenn Sie in Ihren Kubernetes-Clustern keine perfekte Zero-Trust-Architektur erreichen können, tragen alle inkrementellen Änderungen in diese Richtung zum Schutz Ihres Clusters und seiner Workloads bei.

Die Absicherung cloudnativer Anwendungen und der zugrundeliegenden Infrastruktur erfordert signifikante Änderungen des Sicherheitsansatzes einer Organisation. Organisationen müssen Kontrollen früher im Lifecycle der Anwendungsentwicklung anwenden, integrierte Kontrollen nutzen, um Richtlinien durchzusetzen, die operative und Skalierbarkeitsprobleme verhindern, und mit den zunehmend schnelleren Release-Zeitplänen Schritt halten.

Red Hat® Advanced Cluster Security for Kubernetes ist eine Kubernetes-native Sicherheitsplattform, mit der Unternehmen cloudnative Anwendungen noch sicherer entwickeln, bereitstellen und ausführen und so Innovationen zuverlässig voranbringen können. Die Lösung trägt dazu bei, die Sicherheit des Entwicklungsprozesses von Anwendungen zu verbessern, die Anwendungsplattform und -konfigurationen zu schützen und Runtime-Probleme zu erkennen und zu beheben.

Weiterlesen

ARTIKEL

Vergleich zwischen Containern und VMs

Linux-Container und virtuelle Maschinen (VMs) sind paketierte Computing-Umgebungen, die verschiedene IT-Komponenten vereinen und vom Rest des Systems isolieren.

ARTIKEL

Was ist Container-Orchestrierung?

Mithilfe der Container-Orchestrierung werden Deployment, Management, Skalierung und Vernetzung von Containern automatisiert.

ARTIKEL

Was ist ein Linux-Container?

Ein Linux-Container besteht aus Prozessen, die vom System isoliert sind und auf einem eigenen Image ausgeführt werden, das alle benötigten Dateien zur Unterstützung der Prozesse bereitstellt.

Mehr über Container erfahren

Produkte

Eine Plattform, die es Ihnen ermöglicht, Unternehmensanwendungen schnell und effizient über die von Ihnen gewünschte Infrastruktur bereitzustellen.

Ressourcen

Training

Kostenloser Trainingskurs

Running Containers with Red Hat Technical Overview

Kostenloser Trainingskurs

Containers, Kubernetes and Red Hat OpenShift Technical Overview

Kostenloser Trainingskurs

Developing Cloud-Native Applications with Microservices Architectures