Dies ist der dritte Blog in einer Reihe von Blogs, die verschiedene Aspekte dessen behandeln, was für den Aufbau und Betrieb unseres SaaS- Dienstes erforderlich war:
In meinem ersten Blog habe ich einige Hintergrundinformationen zu den Anforderungen gegeben, die uns zum Aufbau einer neuen Plattform für verteilte Clouds veranlasst haben. Mithilfe dieser Plattform erstellen unsere Kunden ein komplexes und vielfältiges Applications – wie etwa intelligente Fertigung, Videoforensik für die öffentliche Sicherheit, algorithmischen Handel und 5G-Telekommunikationsnetze.
Da viele dieser Applications unternehmenskritisch sind, erwarten unsere Kunden von uns nicht nur, dass wir mehrschichtige Sicherheit bieten, sondern auch in der Lage sind, kontinuierliche Verbesserungen vorzunehmen, um die Sicherheit ihrer verteilten Cluster zu gewährleisten. In diesem speziellen Blog werden die Herausforderungen der Sicherung von Infrastrukturen, Applications und Daten über mehrere Cluster hinweg behandelt.
Wie oben bereits erwähnt, ist das Problem der Sicherung des Benutzerzugriffs auf Applications (beispielsweise des Zugriffs auf unsere Bankkonten oder unsere E-Mails) allgemein bekannt. Für den App-zu-App- oder App-zu-Daten-Zugriff ist das Gleiche jedoch nicht so einfach, da am Verifizierungsprozess kein Mensch beteiligt ist.
Damit eine Application auf sichere Weise auf eine andere Ressource zugreifen kann – beispielsweise auf in einem Objektspeicher gespeicherte Daten oder einen API-Aufruf an eine andere Application usw. – muss Folgendes geschehen:
Im Rahmen des Authentifizierungsprozesses kann die anfragende Application ihre Identität in Form eines PKI-Zertifikats oder eines Geheimnisses (z. B. eines Passworts) oder eines Schlüssels vorlegen. Bei der Verwendung von Geheimnissen oder Schlüsseln zur Identitätsermittlung müssen zwei Aspekte berücksichtigt werden:
Das zuverlässige und wiederholbare Durchführen dieser Sicherheitsvorgänge (für die App-zu-App-Interaktion) ist kein triviales Problem. Dafür gibt es viele Gründe:
Daher stellt die Sicherung der Infrastruktur, Applications und Daten in einer dynamischen Umgebung eine große Herausforderung dar. Zwar haben sich die Cloud-Anbieter dieser Herausforderung gestellt und zahlreiche Tools zur Lösung dieser Probleme bereitgestellt, doch die Integration und Wartung dieser Tools gestaltet sich aus folgenden Gründen nicht einfach:
Während viele Unternehmen auf einen einzigen Cloud-Anbieter zurückgreifen und es für sie ausreichend sein kann, Ressourcen in die Verwaltung und Verbesserung der Sicherheitsprimitiven dieses Anbieters zu investieren, arbeiten wir in einer heterogenen Umgebung (Hybrid-Cloud und Edge) und mussten zur Behebung dieser Probleme eine neue Lösung entwickeln.
Unser Team wurde damit beauftragt, die Sicherheit der Applications, Infrastruktur und Daten zu gewährleisten, die sich möglicherweise auf einer verteilten Infrastruktur befinden, wie in Abbildung 1 dargestellt.
Daher beschloss unser Plattformteam, neue Softwaredienste zu entwickeln, die die folgenden vier Aspekte integrieren, um Plattformsicherheit über den Edge, alle Clouds und unsere Netzwerk-PoPs hinweg zu gewährleisten:
Identität ist ein grundlegendes Thema, da viele Sicherheitsherausforderungen leichter bewältigt werden können, wenn das Identitätsproblem gelöst ist. Um das Identitätsproblem zu lösen, müssen wir jedoch definieren, was wir damit meinen und wie eine Identität auf zuverlässige Weise ausgegeben werden kann. Krypto-Freaks haben gerne ihre eigene Meinung zu allem, und die Definition von Identität ist da keine Ausnahme:
Der einzigartige und vollständige Satz nicht fälschbarer und kryptografisch verifizierbarer Merkmale, die über ein nicht delegiertes und sicheres Protokoll von einer vertrauenswürdigen Autorität kryptografisch zertifiziert werden und die ausmachen, was eine Person oder Sache ist oder wofür sie gehalten wird.
Was im Wesentlichen benötigt wird, ist eine fälschungssichere und kryptografisch verifizierbare Identität, die sicher übermittelt wird. Die Ausstellung einer solchen Identität ist aus zwei Gründen eine Herausforderung: 1) Bootstrapping der Identität und 2) Root-of-Trust
Es gibt einige Ansätze, die im Zusammenhang mit Identität häufig diskutiert werden – SPIFFE und Hashicorp Vault. Wir möchten klarstellen, dass SPIFFE ein Benennungsschema ist, das in unserem System als Ausweisdokument (X.509-Zertifikat) verwendet werden könnte. Das Format ist jedoch für einige Identitätsattribute, die Binärdaten enthalten, nicht geeignet. Obwohl Vault zum Ausstellen eines Ausweisdokuments verwendet werden kann, löst es nicht die Herausforderungen des Bootstrapping of Identity und des Root of Trust-Problems:
Wenn beispielsweise eine VM in AWS gestartet wird, wird sie mit einer Bootstrap-Identität versehen und der Metadatendienst von AWS fungiert als Vertrauensanker. Das Identitätsdokument (das von AWS mit einem eigenen kryptografischen Schlüssel signiert ist) sieht ungefähr so aus:
Während die Instanz-ID die eindeutige Identität der gestarteten Application angeben kann, muss sie mit einem bekannten Namen (myserver.acmecorp.com) verknüpft werden, den andere Applications zur Kommunikation mit dieser bestimmten Instanz verwenden. Daher ist auch dieses AWS-Bootstrap-Identitätsdokument nicht ausreichend, kann aber zum Ausstellen einer anderen Identität verwendet werden, die von den Applications zur Kommunikation mit einer anderen Application verwendet werden kann.
Wie bereits erwähnt, war es für uns von entscheidender Bedeutung, eine Identität bereitzustellen, die es Applications ermöglicht, über Cloud-Anbieter und/oder Edge-Standorte hinweg zu kommunizieren und Informationen auszutauschen (Abbildung 2). Dies bedeutete, dass wir ein System sowohl für Identity Bootstrapping als auch für Root-of-Trust entwickeln mussten, das in all diesen Umgebungen funktioniert.
Da wir Kubernetes zum Verwalten und Orchestrieren von Applications (sowohl Microservices als auch VMs) verwenden, bedeutete dies, dass das Bootstrapping einer eindeutigen Identität für jeden gestarteten Pod in den Pod-Erstellungsprozess von Kubernetes eingebunden werden musste. Abbildung 3 zeigt, wie wir uns mithilfe des Webhook-Mechanismus von K8 in den Pod-Erstellungsprozess einklinken. Dieser Webhook namens „Voucher“ fügt einen Sicherheits-Sidecar namens „Wingman “ in alle im Cluster erstellten Pods ein und stellt außerdem die erforderlichen kryptografisch signierten Informationen bereit, die als Vertrauensanker verwendet werden können. Dieser Webhook stellt ein kurzlebiges signiertes Token bereit, das von Wingman verwendet wird, um ein X.509-Zertifikat von der Identitätsbehörde im SaaS-Backend von Volterra anzufordern.
Die Identitätsbehörde setzt die Regeln zur Prägung der Identität auf eine Weise durch, die den „Explosionsradius“ minimiert, falls einer der K8-Cluster kompromittiert wird. Viele andere Lösungen, die auf einer gemeinsamen Stammzertifizierungsstelle oder einem Verbund von K8s-Clustern basieren, können den Explosionsradius nicht begrenzen, was ein wichtiger Faktor bei unserer Designentscheidung war.
Für einen bestimmten Pod in K8s können sich die Attribute nach der Erstellung des Pods ändern. Beispielsweise kann ein Pod nach seiner Erstellung an einen neuen Dienst angehängt werden. Dies bedeutete, dass Identitätszertifikate mit dem neuen Dienst aktualisiert werden mussten. Wingman überwacht den Voucher, der den K8s-API-Server verfolgt, kontinuierlich auf solche Updates.
Dieser Mechanismus verleiht jeder Application , die auf unserer Plattform ausgeführt wird, eine eindeutige und universelle globale Identität, unabhängig davon, ob es sich um unsere eigene Arbeitslast oder die Arbeitslast eines Kunden handelt. Diese eindeutige Identität und der Sidecar (Wingman) werden dann verwendet, um die gesamte Kommunikation, den Zugriff und alle Schlüssel/Geheimnisse in einem verteilten System zu sichern.
Eine eindeutige Identität pro Pod ist ein guter Anfang, da sie die Implementierung einer gegenseitigen Authentifizierung zwischen kommunizierenden Diensten erleichtert. Unsere zugrunde liegende Infrastruktur besteht aus vielen verschiedenen Diensten, die auf unterschiedlichen Protokollen wie gRPC, REST, IPSec, BGP usw. laufen. Das Ziel des Teams bestand seit der Gründung darin, eine gegenseitige Authentifizierung und Kommunikationssicherheit (verschlüsselter Kanal) für alle kommunizierenden Parteien zu erreichen, unabhängig vom Protokoll. Dies bedeutete auch, dass wir unsere Identität nicht an eine Lösung (z. B. Istio) binden konnten, die sich auf einen bestimmten Satz von Protokollen beschränkt (z. B. HTTP/TCP vs. IP-basiert).
Da unsere Plattform es Kunden auch ermöglicht, Workloads ihrer Wahl auszuführen, erwarten wir, dass diese Workloads eine Vielzahl von Protokollen ausführen können. Die Plattform sollte deren Möglichkeiten nicht dadurch einschränken, dass sie eine Identität bereitstellt, die auf einen bestimmten Satz von Protokollen beschränkt ist. Stattdessen wird die Authentifizierung von der Identität entkoppelt (via Wingman), was die Einbindung in verschiedene Service-Mesh-Technologien ermöglicht. Unser Service-Mesh-Sidecar/Dataplane (in einem früheren Blog behandelt) verwendet diese Identität, um mTLS für Kunden-Workloads bereitzustellen.
Da viele unserer eigenen Infrastrukturdienste mit dem Volterra Golang Service Framework geschrieben wurden (wird in einem zukünftigen Blog besprochen), haben wir beschlossen, die Logik der Identitätsnutzung (von Wingman) direkt in das Framework einzubauen. Dies hat unseren Entwicklern dabei geholfen, ihre Service-zu-Service-Kommunikation sofort zu sichern, ohne auf einen Service-Mesh-Sidecar für mTLS angewiesen zu sein.
Der nächste logische Schritt nach der Erstellung eines gegenseitig authentifizierten sicheren Kanals ist die Autorisierung – ein Prozess, bei dem der Empfänger der Anfrage (Server) feststellt, ob die Anfrage des identifizierten Anrufers (Client) zugelassen wird oder nicht. Es kann viele Gründe geben, die Anfrage nicht zuzulassen – Kontingentbeschränkungen, Berechtigungen usw. Da sich diese Gründe und ihre Schwellenwerte dynamisch ändern, kam ein fest codierter Regelsatz (Richtlinie) für die Autorisierung für unsere Plattform nicht in Frage.
Wir entschieden uns, die Engine von Open Policy Agent als Ausgangspunkt zu verwenden und erstellten einen Wrapper für die Autorisierung im Wingman-Sidecar. Dieser Wrapper-Code ruft die relevanten Richtlinien dynamisch ab und hält sie für eine schnelle Auswertung aktuell. Ähnlich wie bei der Authentifizierung hat uns die Entkopplung der Autorisierungs-Engine von der Identität (und Authentifizierung) ermöglicht, Autorisierungsrichtlinien in mehreren Phasen der Anforderungsverarbeitung durchzusetzen, auch tief in der Geschäftslogik und nicht nur unmittelbar nach der Authentifizierung.
Da Wingman in alle Workloads, einschließlich der Workloads des Kunden, eingefügt wird, bietet unsere Plattform eine Autorisierungs-Engine als integrierte Funktion. Obwohl Open Policy Agent (OPA) auf einer leistungsstarken Sprache namens Rego basiert, wollten wir ihre Komplexität vor unseren Entwicklern und Kunden verbergen. Alle Richtlinien auf unserer Plattform können auch mithilfe einer viel einfacher verständlichen und intuitiven Richtlinienstruktur definiert werden, die von den Benutzern (DevOps) kein Erlernen von Rego erfordert und somit Fehler vermeidet. Ähnlich wie bei der Authentifizierungskonfiguration wurde unser Golang Service Framework in die Autorisierungs-Engine von Wingman eingebunden, indem Wingman automatisch zur Autorisierung aufgerufen und die Komplexität der Autorisierung vor den Entwicklern verborgen wurde.
Durch die Verwendung einer eindeutigen Identität (ausgestellt mit Wingman) zur Authentifizierung und einer programmierbaren Richtlinien-Engine (innerhalb von Wingman) zur Autorisierung können wir die Kommunikation mit mTLS sichern und jeden Zugriff mit einer robusten und programmierbaren Richtlinie kontrollieren.
Jeden Tag machen Ingenieure unbeabsichtigte Fehler, indem sie Schlüssel und Passwörter in ihrem Code speichern, und diese gelangen irgendwie in den öffentlichen Code oder in Artefakt-Repositories. Die Verwaltung von Geheimnissen ist schwierig und ohne ein einfach zu verwendendes Toolkit und einen klar definierten Prozess wird von den Entwicklern erwartet, den kürzesten Weg nach vorne zu wählen. Aus diesem Grund bestand die Aufgabe unseres Teams für Plattformsicherheit (die sich von der Netzwerk- und App-Sicherheit unterscheidet) von Anfang an darin, dafür zu sorgen, dass Entwickler sich keine Fragen stellen müssen wie: „Wo speichere ich Geheimnisse – Quellcode oder Artefakte oder …?“
Wir haben zwei gängige Ansätze bewertet, die uns für die Geheimnisverwaltung zur Verfügung standen, als wir mit dem Aufbau unserer Plattform begannen, und beide hatten bestimmte Mängel:
Da es sich in unserem Fall um einen SaaS-Dienst handelt, mussten wir eine robustere Methode entwickeln, um die Geheimnisse unserer Kunden zu schützen, da diese bei einem Kompromiss nicht preisgegeben werden sollten.
Aus diesem Grund haben wir uns entschieden, eine neue Technik zu implementieren, die wir Volterra Blindfold (Warenzeichen) nennen und die in Verbindung mit unserem Sicherheits-Beiwagen Wingman funktioniert, wie in Abbildung 4 dargestellt. Dieser Ansatz ermöglicht es dem Besitzer des Geheimnisses, das Geheimnis so zu sperren (zu verschlüsseln), dass es niemals im Klartext an unerwünschte Parteien (einschließlich des Entschlüsselungsservers) weitergegeben wird. Das Geheimnis wird nicht einmal auf einem zentralen Entschlüsselungsserver gespeichert und dieses Design vereinfacht in mancher Hinsicht das Serverdesign erheblich.
Wir stellen Benutzern ein Blindfold-Tool zur Verfügung, das in einer vollständig Offline-Umgebung verwendet werden kann, um das Geheimnis (S) zu verschlüsseln, das dann verteilt werden kann – beispielsweise kann das Geheimnis selbst mit der Arbeitslast gespeichert und in die Registrierung hochgeladen werden. Sobald dies erreicht ist, müssen die folgenden Schritte ausgeführt werden:
Dadurch wird sichergestellt, dass die zentralisierte Steuerebene niemals Zugriff auf das Geheimnis im Klartext (S) erhält und das Geheimnis außerdem nur für die Dauer des Zugriffs im Laufzeitspeicher des Pods verfügbar ist. Darüber hinaus können Zugriffsrichtlinien angewendet werden, um zu definieren, wer Zugriff auf ein Geheimnis erhält. Die Richtlinie kann basierend auf Identitätsattributen wie Application , Standort, Konformitätsstufe usw. definiert werden. Auf diese Weise können beliebige komplexe Teilmengen von Arbeitslasten herausgearbeitet und eine präzise Zugriffskontrolle erreicht werden. Die Richtlinie ist kryptografisch in den Verschlüsselungs-, Blinding-, Entschlüsselungs- und Unblinding-Prozess eingebunden – es ist rechnerisch nicht möglich, die Absicht der Richtlinie zu umgehen.
Mithilfe unserer einzigartigen Blindfold-Technik zum Verschließen aller Geheimnisse und Wingman zum Entschlüsseln aller Geheimnisse auf der Grundlage von Richtlinien und einer fälschungssicheren Identität sind wir in der Lage, die Probleme bestehender Lösungen zu überwinden und die Geheimnisverwaltung in einer verteilten Umgebung bereitzustellen, ohne uns jemals Sorgen über die Gefährdung der zentralen Goldmine machen zu müssen.
Obwohl Geheimnisse und Schlüsselverwaltung wie zwei verschiedene Namen für dasselbe Problem klingen, gibt es zwischen den beiden Begriffen subtile (in der Praxis jedoch wichtige) Unterschiede, je nachdem, wen Sie fragen und wie Sie die Lösungen implementieren möchten.
Als „geheim“ gelten alle Informationen, die geheim sein müssen und für unbefugte Parteien nicht zugänglich sind. In gewisser Weise sind kryptografische Schlüssel ein Sonderfall von Geheimnissen. Unter Schlüsselverwaltung versteht man dagegen im Allgemeinen ein System, das sensibles kryptografisches Schlüsselmaterial sicher speichert und die Verwendung des Materials kontrolliert. In manchen Fällen kann das Schlüsselverwaltungssystem Rohbytes des Schlüssels an autorisierte Parteien weitergeben und daher mit einem Geheimnisverwaltungssystem verwechselt werden. In den meisten Fällen gibt das Schlüsselverwaltungssystem jedoch keine Rohbytes des Schlüsselmaterials heraus, sondern führt Operationen für autorisierte Anforderer aus und sendet nur die Ausgabe der Operation. Viele Schlüsselverwaltungssysteme werden auch durch Hardwarespeicher (z. B. HSM) für das Schlüsselmaterial unterstützt, sodass der Schlüssel der Software nie im Klartext preisgegeben wird.
In verteilten Umgebungen ist das Verwalten, Synchronisieren und Rotieren kryptografischer Schlüssel selbst für einen einzelnen Cloud-Anbieter eine große Herausforderung und aktuelle Lösungen sind fehleranfällig, ineffizient und sogar unsicher. Wenn Sie beispielsweise heute drei AWS-Regionen nutzen und in allen drei Regionen denselben Kryptoschlüssel verwenden möchten, müssen Sie die Schlüssel manuell synchronisieren und rotieren. Das Problem wird noch schlimmer, wenn sich die Umgebung über mehrere Cloud-Anbieter (öffentlich und/oder privat) erstreckt. Selbst wenn dies alles gesagt und getan ist, müssen die Application immer noch komplexen Code schreiben, um diese KMS-Funktionen nutzen zu können.
Unsere Plattform verbirgt die gesamte Komplexität der Schlüsselverwaltung vor der Application , indem sie Wingman Sidecar die ganze Schwerstarbeit übernimmt und einfache Schnittstellen zur Application bereitstellt, um die Schlüsselverwaltungsanforderungen einschließlich Verschlüsselung, Entschlüsselung, HMAC, HMAC-Verifizierung, digitale Signatur, Signaturverifizierung, Schlüsselabruf (sofern zulässig) usw. durchzuführen. Dadurch wird die Schlüsselverwaltung für unsere eigenen Infrastrukturdienste und die Arbeitslast unserer Kunden zu einem Kinderspiel.
Das folgende Diagramm (Abbildung 5) zeigt, wie das KMS von Volterra umgebungsübergreifend funktioniert und Workloads dabei hilft, ihre Schlüsselverwaltungs- und Kryptooperationen auf den Wingman-Sidecar auszulagern. Je nach Konfiguration kann Wingman Schlüssel zwischenspeichern und den Cache aktualisieren, ohne dass die Application davon etwas mitbekommt. Der ermöglichende Faktor ist hierbei die universelle und fälschungssichere Identität, die wir zuvor eingeführt haben. Da jeder Pod, unabhängig von seinem Standort, eine global eindeutige Identität erhält, kann das Volterra KMS-System Zugriffsrichtlinien sehr genau auf Kryptoschlüssel und bestimmte Vorgänge wie Verschlüsselung, Entschlüsselung, HMAC, HMAC-Verifizierung, digitale Signatur und Signaturverifizierung anwenden.
Da alle Schlüssel über das SaaS-Backend von Volterra verwaltet werden, müssen sich die in heterogenen Umgebungen ausgeführten Workloads nicht mit Schlüsselsynchronisierung, Rotation, Widerruf usw. befassen – sie müssen für alle ihre Sicherheitsanforderungen für ruhende Daten lediglich einfache Wingman-APIs kennen.
Durch die Verwendung mehrschichtiger Plattformsicherheit ist es uns gelungen, für drei kritische Probleme eine umfassende Lösung auf völlig neue Art und Weise bereitzustellen! Unser System ist in der Lage, eine universelle Identität sicher zu starten, die nicht unter dem Problem des „ Sturzmann-das-ganze-Tief “ leidet. Es kann Geheimnisse verwalten, die gespeichert und verteilt werden können, ohne sich jemals um das Goldminenproblem sorgen zu müssen, und bietet Schlüsselverwaltung, um die Sicherheit ruhender Daten in einer verteilten Umgebung zu erleichtern. Dies hat zu folgenden Vorteilen für unsere internen Teams sowie unsere Kunden geführt:
In dieser Blogserie werden verschiedene Aspekte dessen behandelt, was für den Aufbau und Betrieb unseres weltweit verteilten SaaS-Dienstes mit vielen Application in der öffentlichen Cloud, unseren privaten Netzwerk-PoPs und Edge-Sites erforderlich war. Als nächstes geht es um Application und Netzwerksicherheit …
Wir suchen einige freiwillige Entwickler und Lösungsarchitekten, die uns dabei helfen, diese Funktion als Open-Source-Projekt einer breiteren Community zugänglich zu machen. Wenden Sie sich bei Interesse bitte direkt an asingla@volterra.io, um bei etwas Spannendem mitzumachen!