BLOG

Sicherung einer verteilten Plattform – Identität, Geheimnisse und Schlüsselverwaltung

Ankur Singla Miniaturansicht
Ankur Singla
Veröffentlicht am 11. Dezember 2019

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: 

  1. Kontrollebene für verteiltes Kubernetes PaaS
  2. Globales Service Mesh für verteilte Anwendungen
  3. Plattformsicherheit für verteilte Infrastrukturen, Apps und Daten 
  4. Anwendungs- und Netzwerksicherheit verteilter Cluster
  5. Beobachtbarkeit über eine global verteilte Plattform
  6. Betrieb und SRE einer global verteilten Plattform 
  7. Golang-Service-Framework für verteilte Microservices

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.

TL;DR (Zusammenfassung)

  1. Während es relativ gut bekannt ist, wie man Benutzern und Mitarbeitern einen sicheren Zugriff auf Applications ermöglicht (das tun wir jeden Tag, wenn wir auf unsere Bankkonten oder Firmen-E-Mails zugreifen), ist es nicht so einfach, dasselbe für den App-zu-App- oder App-zu-Daten-Zugriff zu tun, da am Verifizierungsprozess kein Mensch beteiligt ist.
  2. Um Apps und Daten in einer heterogenen Umgebung (Edge, mehrere Clouds und Netzwerk-PoPs) zu sichern, mussten wir ein mehrschichtiges Problem lösen – Identität, Authentifizierung und Autorisierung, Geheimnisse und Schlüsselverwaltung.
  3. Obwohl für diese vier Probleme viele Punktlösungen verfügbar sind (z. B. mehrere Dienste von einzelnen Cloud-Anbietern, Hashicorp Vault, SPIFFE/Spire usw.), gibt es keine integrierte Lösung, die über mehrere Cloud-Anbieter hinweg funktioniert oder diese Dienste nahtlos und damit benutzerfreundlich kombiniert.
  4. Angesichts des Mangels an Fachwissen unserer Entwickler- und DevOps-Teams hinsichtlich der Zusammenführung dieser Teile wurde es für unser Plattformteam unabdingbar, diese Funktionen als integrierte Lösung bereitzustellen, die einfach zu verwenden ist. Die sich weiterentwickelnde Sicherheitslandschaft und neue Technologien machen es diesen Teams noch schwerer, da sie weder über das notwendige Fachwissen noch über die Bandbreite verfügen, um mit allen Änderungen Schritt zu halten.
  5. Im Rahmen der Bereitstellung einer mehrschichtigen Plattformsicherheit haben wir neue Softwarekomponenten erstellt, die drei kritische Probleme auf völlig neue Weise lösen: den sicheren Aufbau einer universellen Identität, die nicht unter dem Problem der „Turtles all the way down“ leidet, Geheimnisse, die gespeichert und ausgezahlt werden können, ohne sich jemals Sorgen über die Gefährdung eines zentralen Tresors machen zu müssen (Goldmine-Problem) und eine verteilte Schlüsselverwaltung, um die Sicherheit ruhender Daten zu verbessern.

Hintergrund zum Sicherheitsproblem

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: 

  1. Identität – der Anforderer muss auf sichere Weise eine überprüfbare Identität erwerben, die beim Zugriff auf die erforderlichen Ressourcen zu Authentifizierungs- und Autorisierungszwecken verwendet werden kann. Der Anforderer muss außerdem sicher mit den erforderlichen Vertrauensankern ausgestattet sein, die zur Überprüfung der Identitäten von Peers verwendet werden können. 
     
  2. Authentifizierung – Beim Zugriff auf eine bestimmte Ressource müssen der Anforderer und der Ressourcenbesitzer die Identität des jeweils anderen sicher überprüfen. Der Vorgang der Überprüfung der behaupteten Identität eines Peers anhand der präsentierten Identität wird als Authentifizierung bezeichnet. 
     
  3. Autorisierung – sobald der Anforderer authentifiziert ist, wird der Vorgang der Überprüfung, ob er auf die Ressource zugreifen darf (oder nicht), als Autorisierung bezeichnet.

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: 

  • Die Geheimnisse und Schlüssel sollten nicht direkt im Code gespeichert werden, da dies ein einfacher Angriffsvektor ist und durchgesickerte Schlüssel ein großes Problem darstellen können. 
  • Wenn die Geheimnisse in einem externen Tresor gespeichert sind, welche Identität (normalerweise ein anderes Geheimnis) sollte dann verwendet werden, um das Geheimnis zu erhalten, und wie sichern wir diese Identität, um das Geheimnis zu erhalten?

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: 

  1. Applications können einfach geklont und erstellt werden (z. B. Microservices). Wie weist man jedem Klon eine eindeutige Identität zu, die für forensische, Prüf- oder Beobachtungszwecke erforderlich sein kann? 
  2. Die Application ist je nach Ausführungsumgebung unterschiedlich. Beispielsweise ist in der Entwicklung und in der Produktion die Application dieselbe, benötigt aber in jeder Umgebung eine andere Identität. 
  3. Wie kann Vertrauen aufgebaut werden, dass die Infrastruktur, in der die Application erstellt wird, die Identität oder Geheimnisse und Schlüssel nicht unbemerkt stiehlt? 
  4. Wie kann der zentrale Tresor vor Angriffen geschützt und alle in diesem Tresor gespeicherten Geheimnisse und Schlüssel gesichert werden?

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: 

  • Komplexität – Jeder Cloud-Anbieter erfordert vom Kunden die Konfiguration und Verwaltung mehrerer Dienste. Beispielsweise in AWS – Metadatendienst, IAM-Rollen, Dienstkonto, RBAC, KMS und Geheimnismanager. Jeder dieser Dienste ist bei jedem Cloud-Anbieter anders – sowohl hinsichtlich der Semantik, der APIs als auch der Überwachung. 
     
  • Interoperabilität – Auch wenn die Dienste der Cloud-Anbieter konfiguriert und betriebsbereit sind, ist bei keinem davon Interoperabilität möglich. Beispielsweise kann eine in GCP ausgeführte VM nicht auf eine Ressource in AWS zugreifen, da die mit dem GCP-Dienstkonto zugewiesene Identität von einer AWS-Ressource nicht verstanden wird. 
     
  • Heterogene Umgebungen – Wenn die Umgebung auf öffentliche und private Clouds oder mehrere öffentliche Clouds verteilt ist oder – schlimmer noch – sich am Rand befindet, besteht die Herausforderung darin, wie und wo Geheimnisse wie Passwörter, Schlüssel usw. gespeichert werden – zentral oder verteilt. 
     
  • Umgebungsspezifisch – Die Lösung für die Rotation und/oder den Widerruf von Anmeldeinformationen ist bei jedem Cloud-Anbieter sehr unterschiedlich, während für Edge-Cluster keine dieser Lösungen vorhanden ist.

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.

Lösung zur Sicherung einer verteilten Plattform

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.

Schlüsselverwaltung-01
Abbildung 1: Sichern einer verteilten Plattform – Identität, Geheimnisse und Schlüsselverwaltung

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: 

  1. Identitätsmanagement – ​​wir beschreiben, wie wir kryptografisch sichere und fälschungssichere PKI-basierte Identitäten nicht nur für Applications bereitstellen, sondern auch für die Infrastruktur, die über eine heterogene Umgebung verteilt ist (mehrere Clouds, unsere globalen PoPs und geografisch weit verteilte Randstandorte) und in mehreren Umgebungen betrieben wird (z. B. Entwicklercomputer, Komponententest, Produktion usw.). 
     
  2. Authentifizierung und Autorisierung – unsere Infrastruktur basiert auf Mikrodiensten, die eine PKI-basierte Identität nutzen und die gesamte Kommunikation unabhängig vom verwendeten Kommunikationsprotokoll gegenseitig authentifizieren. Darüber hinaus haben wir die Autorisierung von der Authentifizierung entkoppelt, sodass für verschiedene Autorisierungsentscheidungen eine gemeinsame Autorisierungs-Engine verwendet und die Richtlinienstruktur vereinheitlicht werden kann. 
     
  3. System zur Verwaltung von Geheimnissen – es gibt viele Arten von Geheimnissen (wie TLS-Zertifikate, Passwörter, Token usw.), die unsere Software sowie die Arbeitslasten der Kunden benötigen. Die einfachste Methode wäre die Einrichtung eines zentralen Tresors gewesen, in dem alle Geheimnisse gespeichert sind. Dieser Ansatz hat jedoch den Nachteil, dass bei einem Kompromiss alle Geheimnisse preisgegeben werden. Wir beschreiben einen anderen Ansatz, den wir implementiert haben, um durch Verzicht auf etwas Einfachheit ein höheres Maß an Sicherheit zu erreichen. 
     
  4. Schlüsselverwaltungssystem (KMS) – Datensicherheit ist für unser verteiltes System von entscheidender Bedeutung und das Team musste ein KMS bereitstellen, das nahtlos mit verschiedenen Cloud-Anbietern funktioniert. Das KMS muss Schlüssel verwalten, versionieren und rotieren, die für die symmetrische Verschlüsselung und Entschlüsselung ruhender Daten, HMAC von CSRF-Token und die digitale Signierung von Binärdateien verwendet werden. Wir besprechen, wie wir sowohl Funktionen für sicherheitssensitive Vorgänge mit diesem KMS als auch für latenzsensitive Vorgänge mit dem Geheimnisverwaltungssystem bereitstellen.

Fälschungssichere Identität für Infrastruktur und Apps

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:

  1. Bootstrapping der Identität – im wirklichen Leben wird die Identität einer Person bei ihrer Geburt durch die Geburtsurkunde festgelegt. Dadurch wird die Identität der Person logisch ermittelt und mithilfe dieses Zertifikats kann die Person weitere Identitätszertifikate wie Reisepass, Führerschein usw. ableiten/anfordern. Ähnlich verhält es sich in der Computerwelt: Bei jedem Start einer Application (oder eines Mikrodienstes) muss eine Identität gebootet werden. Die Feststellung der Identität ist einer der ersten Schritte, die jeder laufende Code ausführen muss, um mit anderen Diensten interagieren zu können. Da derselbe Application außerdem mehrmals und in unterschiedlichen Umgebungen (Laptop des Entwicklers vs. Komponententest vs. Produktion) gestartet werden kann, ist es auch erforderlich, dass bei jedem dieser Starts eine separate Bootstrap-Identität erstellt wird.
  2. Vertrauenswurzel – die Ausgabe einer Bootstrap-Identität scheint zwar ein unkomplizierter Vorgang zu sein, das Problem besteht jedoch darin, wer diese Identität bereitstellen darf. In der realen Welt beginnt die Bereitstellung einer Identität beispielsweise damit, dass das Krankenhaus die Tatsache bestätigt, dass ein Kind zu einem bestimmten Datum und Zeitpunkt von einer bestimmten Person geboren wurde. Außerdem wird davon ausgegangen, dass das Krankenhaus die Geburtsurkunde ordnungsgemäß überprüft und diese nicht gefälscht werden kann. Daher kann die Geburtsurkunde als Quelle der Wahrheit (oder Vertrauensbasis) verwendet werden. Wenn eine Application durch einen Menschen oder einen automatisierten Code gestartet wird, muss es eine Vertrauensbasis geben, die die Identität der gestarteten Application nachweisbar bestätigen kann. Mit dieser Bestätigung kann dann ein späteres Ausweisdokument für die Application generiert werden.

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:

Rohcode 1

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.

Schlüsselverwaltung-02
Abbildung 2: Kommunikation zwischen Cloud-Anbietern, Netzwerk-PoPs und Edge

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.

Schlüsselverwaltung-03
Abbildung 3: Root-of-Trust in jedem Kubernetes-Cluster

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.

Authentifizierung und Autorisierung

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.

Geheimnisverwaltung ohne zentralen Tresor

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: 

  1. Kubernetes-Geheimnisse – Obwohl wir Kubernetes verwenden und es über eine eigene Geheimnislösung verfügt, ist diese aus verschiedenen Gründen nicht besonders nützlich – Geheimnisse werden im Ruhezustand nicht verschlüsselt, die Richtlinienkonstrukte sind nicht umfassend und Multi-Cluster-Szenarien werden damit nicht gelöst.
     
  2. Zentralisierter Tresor (z. B. Hashicorp- oder Cyberark-Tresor) – Ein anderer Ansatz hätte darin bestehen können, einen Tresor zu verwenden, in dem die Geheimnisse zentral gespeichert und an autorisierte Antragsteller ausgegeben werden. Die Geheimnisse werden durch einen einzigen Verschlüsselungsschlüssel geschützt, der für die verschlüsselte Speicherung von Vault verwendet wird. Das Problem bei diesem Ansatz besteht jedoch darin, dass das Geheimnisverwaltungssystem Zugriff auf klare Geheimnisse hat (selbst wenn diese verschlüsselt gespeichert sind) und bei einer Kompromittierung des Systems alle Geheimnisse preisgegeben werden könnten.

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.

Schlüsselverwaltung-04
Abbildung 4: Blindfold und Wingman für das Geheimnismanagement

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.

Schlüsselverwaltung für verteilte Systeme

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.

Schlüsselverwaltung-05
Abbildung 5: Wingman und KMS-Server in unserem SaaS-Backend

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.

Vorteile unserer Plattform-Sicherheitslösung

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: 

  1. Sicherheit und Compliance – fälschungssichere und universelle Identität, Blindfold und Sicherheits-Sidecar (Wingman), das vollständig in die Plattform integriert und automatisch von ihr verwaltet wird, um die gesamte Kommunikation zu sichern, jeden Zugriff zu autorisieren und Schlüssel/Geheimnisse in einem verteilten System zu verwalten. Mithilfe dieser Fortschritte sind wir in der Lage, eine robustere Sicherheitslösung bereitzustellen, die es uns und unseren Kunden erleichtert, Compliance-Vorschriften einzuhalten. 
     
  2. Produktivitätssteigerungen – durch die Verwendung einer Sicherheitslösung, die in unser DevOps-Prozess- und Service-Framework integriert ist, können sich Entwickler und DevOps-Teams ganz auf ihre Aufgaben konzentrieren, ohne sich um wichtige Aspekte der Application und Datensicherheit kümmern zu müssen. 
     
  3. Kontinuierliche Weiterentwicklung – die sich entwickelnde Sicherheitslandschaft und neue Technologien führen zu einer kontinuierlichen Weiterentwicklung von Blindfold, Wingman und unserem Golang Service Framework. Dadurch werden neue Funktionen automatisch von der Plattform bereitgestellt, ohne dass Änderungen an der Application erforderlich sind.

Fortgesetzt werden…

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!