Wie man Geheimnisse bewahrt? Im Repository, im Bereitstellungssystem oder im Konfigurationsmanagementsystem? Auf einem PC, auf Servern oder vielleicht in einer Box unter dem Bett? Und wie gehe ich mit Geheimnissen um, um Lecks zu vermeiden?
Sergey Noskov ( Albibek ) - der Leiter der Informationssicherheitsgruppe der Plattform aus Avito , kennt die Antwort auf diese Fragen und wird sie uns
mitteilen . In Avito nutzt HashiCorp Vault HashiCorp Vault seit zwei Jahren aktiv. Während dieser Zeit haben sie Unebenheiten und Erfahrung auf das „Master“ -Niveau gebracht.
In dem Artikel werden wir umfassend über Vault sprechen: Was es ist, wo und wie es im Unternehmen verwendet wird, wie Avito Geheimnisse mit HashiCorp Vault verwaltet, wie Puppet und Kubernetes verwendet werden, Anwendungsfälle mit Puppet und anderen SCM, welche Probleme auftreten, was die Sicherheit beeinträchtigt und Entwickler, und natürlich teilen Ideen, wie man es beheben kann.
Was ist ein Geheimnis?
Alle vertraulichen Informationen:
- Login und Passwort zum Beispiel in der Datenbank;
- API-Schlüssel
- Server-Zertifikatschlüssel (* .google.com)
- Kundenzertifikatschlüssel (Partner, Yandex-Geld, QIWI);
- Schlüssel zum Signieren mobiler Anwendungen.
Alle Informationen, die wir geheim halten wollen, nennen wir geheim. Dies führt zu einem Speicherproblem: Das Speichern im Repository ist in verschlüsselter Form fehlerhaft. Sie müssen die Verschlüsselungsschlüssel irgendwo aufbewahren.
HashiCorp Vault ist eine der guten Lösungen für das Problem.
- Schlüssel sicher speichern und verwalten.
- Geschärft auf der Welt der Microservices, seit dem Microservice selbst.
- HashiCorp Vault hat viel getan, um den Zugriff auf Geheimnisse wie ACLs und das Prinzip der Mindestberechtigungen zu authentifizieren und zu autorisieren.
- REST-Schnittstelle mit JSON.
- Sicherheit ist nicht perfekt, aber auf einem ziemlich hohen Niveau.
Meiner Meinung nach ist dies ein ziemlich praktisches Werkzeug.
Was ist neu in HashiCorp Vault?
Das Tool entwickelt sich und in den letzten Jahren sind viele interessante Funktionen enthalten: CORS-Header für die grafische Benutzeroberfläche ohne Zwischenhändler; eingebaute GUI; native Integration mit Kubernetes; Plugins für logische und Auth-Backends und Frameworks.
Die meisten Änderungen, die mir persönlich gefallen haben, sind die
Möglichkeit, keine Erweiterungen und Ergänzungen zu schreiben , die außerhalb des Tools stehen.
Zum Beispiel gibt es Vault, das Sie erweitern möchten - schreiben Sie zusätzliche Logik oder Ihre eigene Benutzeroberfläche für die Automatisierung, die etwas automatisiert. Vor den Änderungen musste ich einen zusätzlichen Dienst auslösen, dem Vault gegenübersteht, und alle Anforderungen weiterleiten: Zuerst gehen die Anforderungen an den Dienst, dann an Vault. Dies ist schlecht, da im Zwischendienst möglicherweise ein geringeres Sicherheitsniveau besteht und alle Geheimnisse dies durchlaufen.
Sicherheitsrisiken sind viel höher, wenn das Geheimnis mehrere Punkte gleichzeitig durchläuft!Henne-Ei-Problem
Wenn Sie das Problem der Speicherung vertraulicher Informationen ansprechen und sich für die Verschlüsselung entscheiden, wird Ihr Geheimnis, sobald Sie etwas verschlüsseln, vom Ort der Verschlüsselung an den Ort verschoben, an dem der Schlüssel gespeichert ist. Dies geschieht ständig: Sobald Sie irgendwo ein Geheimnis gespeichert oder ein vorhandenes geändert haben, haben Sie ein anderes und ein verzauberter Kreis beginnt -
wo Sie das Geheimnis für den Zugriff auf das Geheimnis aufbewahren können .
Das Geheimnis für den Zugriff auf das Geheimnis ist der Teil der Sicherheit, der als
Authentifizierung bezeichnet wird . Sicherheit hat einen anderen Teil - die
Autorisierung. Im Autorisierungsprozess wird geprüft, ob der Benutzer genau dort zugreifen kann, wo er anfordert. Im Fall von Vault gibt es einen vertrauenswürdigen Dritten, der entscheidet, ob das Geheimnis preisgegeben wird oder nicht. Die Autorisierung löst das Problem nur teilweise.
HashiCorp Vault in Avito
Bei Avito wird HashiCorp in der einzigen großen Installation im gesamten Netzwerk installiert. HashiCorp Vault hat viele verschiedene Backends. Wir verwenden das auf
Consul basierende Backend auch von HashiCorp, da Vault seine eigene Fehlertoleranz nur über Consul unterstützen kann.
Das Entsiegeln ist eine Möglichkeit, den Hauptschlüssel nicht an einem Ort
aufzubewahren . Wenn Vault gestartet wird, wird alles auf einem Schlüssel verschlüsselt, und erneut tritt das Problem mit Hühnchen und Eiern auf: Wo soll ein Geheimnis aufbewahrt werden, das alle anderen Geheimnisse verschlüsselt? Um dieses Problem zu vermeiden, stellt Vault einen zusammengesetzten Schlüssel zur Verfügung, für den mehrere Teile des Schlüssels erforderlich sind, den wir an mehrere Mitarbeiter verteilen. In Avito haben wir Unseal in den Optionen für 3 von 7 Personen konfiguriert. Wenn wir Vault starten, müssen mindestens 3 Personen hereinkommen und ihren Teil des Schlüssels eingeben, um mit der Arbeit zu beginnen. Der Schlüssel ist in 7 Teile unterteilt und Sie können jeden von ihnen mitbringen.
Wir haben einen kleinen Test-Tresor zusammengestellt, eine Sandbox für Entwickler, in der sie spielen können. Es hat die Form eines Docker-Containers und schafft einfache Geheimnisse, damit die Leute das Werkzeug mit den Händen berühren und es sich bequem machen können. Es gibt keinen Konsul und kein Clustering in der Sandbox. Es handelt sich lediglich um ein Dateisystem, in dem Vault verschlüsselte Geheimnisse enthält, und ein kleines Skript zum Initialisieren.
Folgendes speichern wir jetzt in Vault:
- Fast alle Geheimnisse für Kubernetes Microservices: Datenbankkennwörter, API-Schlüssel, alle oben genannten.
- Geheimnisse für das Auflegen auf die "Eisen" -Server und LXC.
- Wir haben auch Geheimnisse für CI / CD-Builds in TeamCity in Vault gespeichert. Die Abdeckung ist nicht 100%, aber durchaus akzeptabel.
- Die Schlüssel aller Zertifikate: interne PKI, externe Zertifizierungsstellen, z. B. GeoTrust und dergleichen.
- Gemeinsame Geheimnisse für Teams.
Im Inneren speichert Vault alles nur in JSON. Dies ist nicht immer praktisch und erfordert zusätzliche Aktionen des Entwicklers. Daher veröffentlichen wir Geheimnisse im Grunde in Form einer Datei.
Wir versuchen, Geheimnisse in Form von Dateien zu liefern.
Wir sagen dem Entwickler nicht: "Gehe zu Vault, nimm ein Geheimnis!", Aber lege die Datei auf die Festplatte und sage: "Entwickler, eine Datei wird auf deiner Festplatte angezeigt, nimm das Geheimnis von ihr und wir werden bereits herausfinden, wie du sie aus Vault holen und bringen kannst dir".

Wir haben eine einfache Vereinbarung für JSON-Felder getroffen, in der wir angeben, mit welchen Rechten die Datei hochgeladen werden soll. Dies sind Metadaten für das Dateisystem, und das Datenfeld ist eine codierte Zeichenfolge mit dem Geheimnis selbst, das zum Inhalt der Datei wird.
Marionette + Hiera + Gewölbe
Fast die gesamte Avito-Infrastruktur verwendet Puppet und rollt alle Server aus.
Puppet hat ein praktisches Werkzeug zum Organisieren von Hierarchien -
Hiera . Vault lässt sich über ein Add-On-Modul sehr gut in Hiera integrieren, da die Schlüsselwertanforderung an diese Bibliothek gesendet wird und Vault die Schlüsselwertdatenbank selbst ist, jedoch mit allen Sicherheitsfunktionen - mit transparenter Verschlüsselung und der Möglichkeit, den Schlüsselzugriff zu wählen.
Daher haben wir als erstes Vault in Puppet implementiert, aber mit einem Zusatz - wir haben eine Zwischenschicht namens
Router-Backend . Router-Backend - ein separates Hiera-Modul, nur Dateien auf der Festplatte, die angeben, wo Hiera den Schlüssel abrufen soll - in Vault oder an einem anderen Ort.
Er wird gebraucht, damit Hiera nicht ständig zum Tresor geht, weil sie immer durch die Hierarchie geht. Dies ist kein Vault-Problem oder eine Belastung, sondern eine Funktion von Hiera. Wenn Sie daher nur das Modul für Vault ohne das Router-Backend belassen, dauert es sehr lange, bis der Puppet-Master die Konfiguration für den Puppet-Agenten erfasst, da er jeden Schlüssel im Vault überprüft.

Für Puppet ist das Problem von Huhn und Eiern dadurch gelöst, dass die autorisierende Partei der Puppenspieler ist. Er gibt das Geheimnis, um auf das Geheimnis zuzugreifen. Der Puppenmeister hat Zugriff auf alle Geheimnisse gleichzeitig, aber jeder Host darf nur das empfangen, das für ihn bestimmt ist. Der Host auf dem Puppet Master ist bereits durch sein Zertifikat autorisiert, das lokal generiert wird und die Hostlimits nicht verlässt. Im Prinzip bleibt das Geheimnis, um auf das Geheimnis zuzugreifen, aber dies ist nicht so kritisch.
Unser Prozess, ein neues Geheimnis in Puppet zu enthüllen, besteht aus den folgenden Schritten.
- Wir nehmen irgendwo ein Geheimnis - jemand gibt es uns oder löscht es.
- Ein Geheimnis in Vault mit einer Hierarchie wie in Hiera: /puppet/role/www/site.ssl.key .
- Wir registrieren ein Präfix im Puppet-Manifest, das angibt, dass sich die Datei in Vault befindet und wo sie erhältlich ist.
- Wir schreiben den Pfad in Vault in YAML für den Hiera-Router und das Backend, damit Hiera ihn finden kann.
- Ziehen Sie die Anforderung über GIT in das Manifest-Repository.
- Führen Sie aus oder warten Sie, bis der Puppet-Agent ausgeführt wird.
Puppenspieler rennen alle 30 Minuten mit uns weg, also müssen Sie ein bisschen warten, bis das Geheimnis herauskommt. Dies verursacht keine Probleme -
wir teilen nicht jeden Tag Geheimnisse . Solange Kubernetes nicht in das Geschäft involviert ist, gibt es nicht viel Aufwand und wir sind bereit, mit minimaler Automatisierung mit unseren Händen Geheimnisse in Vault zu lüften.
Ein zusätzliches Plus ist die "Chip" -Hiera - das
Geheimnis kann sofort für eine Gruppe von Hosts oder abhängig von der Rolle des Hosts, die wir in der variablen Rolle festgelegt haben, festgelegt werden.
Die einzige
Gefahr : Wenn Sie Puppet haben und Hiera verwenden, ersetzen Sie Variablenvorlagen nicht durch Hindernisse, da viele Fakten und Variablen auf der Clientseite gesammelt werden. Wenn ein Angreifer eine Tatsache auf dem Klienten ersetzt, gibt ihm der Puppenmeister die Geheimnisse anderer Leute.
Überprüfen Sie unbedingt die Variablen : Verwenden Sie nur diejenigen, die der Puppet-Master auf der Client-Seite nicht bestimmen kann.
Was tun mit SCM ohne Assistenten?
Wenn Sie plötzlich keine Puppe mehr haben, dann höchstwahrscheinlich Ansible. Für Chefkoch und andere zentralisierte SCMs sind ihre Lösungen ein Plugin, das auf Vault zugreifen kann. Ich biete verschiedene Optionen an, die mit Ansible implementiert werden können.
Lokaler Agent
Generieren Sie lokal für den Server ein Token, das eigentlich das Kennwort für den Zugriff auf den Tresor ist. Das Token ist jederzeit gültig. Sie können es aktualisieren oder automatisieren. Mit diesem Token gehst du zum Tresor und nimmst deine Geheimnisse weg.
Die Idee ist, dass auf Ihrem Server, auf dem Sie Geheimnisse bereitstellen müssen, der Agent, der zu Vault kommt, sich dreht, alle Geheimnisse überprüft und sie in Form von Dateien ablegt. Wir verwenden den Agenten auf mehreren separaten Servern, auf denen keine Marionette vorhanden ist.
Nachteile:- Das Token kann einfach in ein kleines Segment eingegeben werden. Wenn jedoch mehrere Dutzend Server pro Tag bereitgestellt werden, müssen Sie für jeden Server ein Token generieren und eine Richtlinie vorschreiben. Dies ist unpraktisch.
- Token muss aktualisiert werden.
- Das Gruppieren von Servern nach Rolle, Zweck oder Fakten ist schwierig. Sie müssen mit Vault synchronisiert werden.
Transit-Verschlüsselung
Vault verfügt über eine Transitverschlüsselungsfunktion, deren Kern darin besteht, dass Vault als
Verschlüsselungsserver fungiert . Sie bringen ihm nur Klartext, und er verschlüsselt und gibt auf seinem privaten Schlüssel, den nur er hat, den geschlossenen Text aus. Dann wählen Sie, wer diesen geschlossenen Text entschlüsseln kann.
Ansible hat eine Entität, auch Vault genannt. Dies ist kein HashiCorp-Tresor, sondern ein
Ansible-Tresor . Es besteht kein Grund zur Verwirrung, und Geheimnisse können sowohl im ersten als auch im zweiten gespeichert werden. Ansible verfügt über ein vorgefertigtes Plugin für die Bereitstellung von Geheimnissen aus Hashicorp Vault. Wenn Sie persönlichen Zugriff auf Vault gewähren, können Sie Geheimnisse entschlüsseln. Wenn Sie Ansible rollen, geht es in Ihrem Namen zu Vault, entschlüsselt die Geheimnisse, die im Repository verschlüsselt sind, und rollt es in die Produktion.
Es gibt auch einen Nachteil:
Jeder Administrator erhält Zugriff auf Geheimnisse . Aber es gibt eine Prüfung: Vault weiß, wie man ein Aktivitätsprotokoll darüber führt, welcher Benutzer hereingekommen ist, welches Geheimnis er gelesen hat und welcher Zugriff erhalten hat. Sie wissen immer, wer, wann und was mit einem Geheimnis zu tun hat. Diese Option scheint mir gut zu sein.
Großer Fehler # 1
Der größte Nachteil, der uns am meisten schmerzt, ist, dass Sie in Vault die vollständige Kontrolle über keinen
Teil der Daten an Dritte delegieren können. In Vault erfolgt der Zugriff auf das Geheimnis auf ähnliche Weise wie in UNIX. Namen werden normalerweise durch Schrägstriche getrennt, und das Ergebnis ist ein "Verzeichnis". Wenn Sie einen solchen Pfad haben, möchten Sie manchmal Teil des Pfads sein und ihn zur Kontrolle an eine andere Person weitergeben.

Sie haben beispielsweise Zertifikate mit dem Namen
/ certs erhalten und möchten diese einzelnen Sicherheitsbeauftragten geben, die sich mit PKI befassen. Vault kann das nicht. Sie können nicht das Recht einräumen, Rechte innerhalb dieses Präfixes zu erteilen, damit die Sicherheitskräfte selbst die Rechte an Zertifikaten an andere Personen verteilen können.
Vault ist nicht in der Lage, selektiv Rechte zu gewähren, um Rechte zu gewähren . Sobald Sie das Recht eingeräumt haben, Rechte zu gewähren, haben Sie auch die Möglichkeit gegeben, uneingeschränkten Zugriff auf alle Geheimnisse zu erhalten. Mit anderen Worten, Sie können keinen Zugriff auf den Vault-Teil gewähren.
Dies ist eines der größten Probleme. Ich habe eine Idee, wie ich es lösen kann. Ich werde es dir später erzählen.
Kubernetes
Bei RIT ++ habe ich über ein separates System gesprochen, das wir für
Kubernetes implementiert haben: Es dient als Dritter, geht zur API, überprüft den Zugriff und fordert dann ein Geheimnis in Vault an.
Jetzt hat unser System an Relevanz verloren, da in Vault 0.9 native Unterstützung für Kubernetes angezeigt wurde. Jetzt weiß Vault selbst, wie man zu Kubernetes geht und sicherstellt, dass der Zugriff auf das Geheimnis erlaubt ist. Er tut dies mit einem
Service Account Token . Wenn Sie beispielsweise einen Pod eingeführt haben, gibt es einen speziellen, signierten und autorisierten
JWT dafür, der für Anforderungen an die Kubernetes-API entwickelt wurde. Mit einem Token können Sie sich auch bei Vault anmelden und Geheimnisse speziell für Ihren Namespace abrufen.
Alles wird auf der Ebene von Vault selbst erledigt. Es ist richtig, dass Sie für jeden Namespace eine Rolle starten müssen, dh Vault mitteilen, dass es einen solchen Namespace gibt, dass eine Autorisierung darin vorhanden ist, und registrieren, wohin Sie zu Kubernetes gehen sollen. Dies wird einmal durchgeführt, und dann geht Vault zur API selbst, bestätigt die Gültigkeit des JWT und stellt sein eigenes Zugriffstoken aus.
Kubernetes Regeln
In Bezug auf den Servicenamen und zusätzliche Metadaten vertrauen wir den Entwicklern. Es besteht eine geringe Wahrscheinlichkeit, dass Entwickler versehentlich oder absichtlich die Geheimnisse anderer Dienste erfahren, die sich in einem Namespace drehen. Daher haben wir eine Regel eingeführt:
einen Dienst -
einen Namespace.Neuer Microservice? Holen Sie sich einen neuen Namespace mit Ihren Geheimnissen. Sie können nicht über die Grenze zum Nachbarn gehen - sie haben ein eigenes Service Account Token.
Die Sicherheitsgrenze bei Kubernetes ist derzeit der Namespace. Wenn Sie in zwei verschiedenen Namespaces ein Geheimnis benötigen, kopieren Sie es.
Kubernetes hat
Kubernetes Geheimnisse . Sie werden unverschlüsselt in etcd in Kubernetes gespeichert und können im Dashboard oder beim Start von kubectl get pods "aufleuchten". Wenn die Authentifizierung in etcd in Ihrem Cluster deaktiviert ist oder Sie jemandem vollständigen Lesezugriff gewährt haben, sind alle Geheimnisse für ihn sichtbar. Aus diesem Grund haben wir zwei Regeln eingeführt: Es ist
verboten, Kubernetes-Geheimnisse zu verwenden, und es ist
verboten, Geheimnisse in Umgebungsvariablen in Manifesten anzugeben . Wenn Sie in deploy.yaml ein Geheimnis in die Umgebung schreiben, ist dies schlecht, da das Manifest selbst von jedem gesehen werden kann, der nicht faul ist.
Kubernetes Lieferung
Wie gesagt, wir müssen die Datei irgendwie in Kubernetes ablegen. Wir haben eine Art Geheimnis: die Essenz, das Passwort, das in JSON in Vault geschrieben ist. Wie kann man es jetzt in eine Datei im Container von Kubernetes verwandeln?

Die erste Lieferoption.
- Wir starten einen speziellen Init-Container.
- Es geht von unserem Bild aus.
- Das Image enthält ein kleines Dienstprogramm, das mit dem Service Account Token an Vault geht, das Geheimnis aufnimmt und es in das freigegebene Volume legt.
- Für das Dienstprogramm wird ein spezielles freigegebenes Volume nur im TMPFS-Speicher bereitgestellt, damit keine Geheimnisse über die Festplatte übertragen werden.
- Der Init-Container geht zu Vault und legt in diesem Volume in Form von Dateien alle Geheimnisse ab, die er auf dem angegebenen Pfad findet.
- Als nächstes wird das freigegebene Volume in dem Hauptcontainer bereitgestellt, in dem es benötigt wird.
- Wenn der Hauptcontainer gestartet wird, erhält er sofort das, was der Entwickler benötigt - Geheimnisse in Form einer Datei auf der Festplatte.
Der Entwickler muss sich nur an den Weg erinnern, auf dem sein Geheimnis liegt.
Wir verwenden so etwas wie dieses Präfix:
/k8s/<cluster>/<namespace>/<service>/some_secret
Der Präfixname enthält den Clusternamen, den Namespace und den Dienstnamen. Jeder Dienst hat sein eigenes Geheimnis, jeder Namespace hat sein eigenes Geheimnis.
Die zweite Option ist Ihr
eigener Einstiegspunkt . Wir ziehen jetzt in Avito um, weil Entwickler Probleme mit dem Init-Container haben. Im Diagramm befindet sich diese Option rechts.
Nicht jeder kann sich seinen eigenen Einstiegspunkt leisten. Wir können, also erzwingen wir in jedem Container unseren speziellen Einstiegspunkt.
Unser Einstiegspunkt macht dasselbe wie der Init-Container: Er geht mit einem Service Account Token zu Vault, nimmt Geheimnisse und löscht sie. Zusätzlich zu den Dateien legt er sie wieder in der Umgebung ab. Sie haben die Möglichkeit, die Anwendung wie vom
Twelve-Factor App- Konzept empfohlen auszuführen: Die Anwendung übernimmt alle Einstellungen, einschließlich Geheimnisse, von Umgebungsvariablen.
Umgebungsvariablen sind im Manifest und im Dashboard nicht sichtbar, da sie beim Start durch PID 1 (den Hauptcontainerprozess) festgelegt werden. Hierbei handelt es sich nicht um Umgebungsvariablen aus deploy.yaml, sondern um Umgebungsvariablen, die vom Einstiegspunkt im Prozess festgelegt werden. Sie sind im Dashboard nicht sichtbar, sie sind auch dann nicht sichtbar, wenn Sie kubectl exec in einem Container ausführen, da in diesem Fall parallel zu PID1 ein anderer Prozess gestartet wird.
Workflow
Aus organisatorischer Sicht ist der Prozess wie folgt. Der Entwickler erfährt vom Sicherheitschampion oder aus der Dokumentation, dass er keine Geheimnisse im Repository, sondern nur in Vault aufbewahren soll. Dann kommt er zu uns und fragt, wo er Geheimnisse preisgeben soll - er reicht einen Antrag bei der Sicherheit ein, um ein Präfix festzulegen. In Zukunft können Sie sofort beim Erstellen eines Dienstes ein Präfix ohne Anforderung erstellen.
Der Entwickler wartet, und das ist schlecht, weil Die Hauptsache für ihn ist die Markteinführungszeit. Dann liest er die Anweisungen, befasst sich mit langen Dateien - "füge diese Zeile dort ein, füge diese Zeile hier ein". Ein Entwickler hat noch nie einen Init-Container gestartet, muss ihn jedoch herausfinden und in deploy.yaml (Helmdiagramm) registrieren.
Commit -> deploy -> feel pain -> fix -> repeat
Es legt fest, wartet auf die Einführung von TeamCity, sieht Fehler in TeamCity, fühlt Schmerzen, versucht, etwas zu beheben, hat wieder Schmerzen. Darüber hinaus wird überlagert, dass jeder Rollout in TeamCity weiterhin in die Warteschlange gestellt werden kann. Manchmal kann ein Entwickler es nicht selbst herausfinden, kommt zu uns und wir klären es gemeinsam.
Grundsätzlich leidet der Entwickler an seinen eigenen Fehlern:
falsch angegebener Init-Container oder hat die Dokumentation nicht gelesen .
Sicherheit hat auch Probleme. Der Sicherheitsbeamte erhält eine Anwendung, in der immer nur wenige Informationen vorhanden sind, und wir finden immer noch die fehlenden Fragen heraus: Finden Sie die Namen der Cluster und den Namespace des Dienstes heraus, da der Entwickler sie in der Anwendung nicht angibt und nicht einmal immer weiß, was es ist. Wenn wir alles herausfinden, Richtlinien und Rollen in Vault erstellen, Gruppen Richtlinien vorschreiben und gemeinsam mit dem Entwickler herausfinden, wo und warum er einen Fehler gemacht hat, lesen wir gemeinsam die Protokolle.
Die Einheit „Architektur“ hilft bei der Lösung des Problems, indem sie sich vor dem Entwickler von deploy.yaml versteckt. Sie entwickeln ein Stück, das alles für den Entwickler generiert, einschließlich des Einstiegspunkts. Aufgrund der Tatsache, dass wir unseren Einstiegspunkt ersetzen, können wir ihn nicht nur zur Übermittlung von Geheimnissen verwenden, sondern auch für andere Dinge, die Sie möglicherweise beim Start tun müssen.
Offensichtliche Probleme mit Kubernetes Geheimnissen.
- Sehr komplizierter Workflow sowohl für den Entwickler als auch für den Sicherheitsbeamten.
- Sie können nichts an jemanden delegieren. Der Sicherheitsbeamte hat vollen Zugriff auf den Tresor, und ein teilweiser Zugriff ist nicht möglich (siehe Großer Fehler Nr. 1).
- Beim Verschieben von Entwicklern von Cluster zu Cluster, von Namespace zu Namespace, wenn gemeinsame Geheimnisse benötigt werden, treten Schwierigkeiten auf, da zunächst davon ausgegangen wird, dass verschiedene Geheimnisse in verschiedenen Clustern unterschiedlich sind.
Wir sagen: „Warum brauchen Sie Produktionsgeheimnisse im Entwicklungscluster? Holen Sie sich ein Testgeheimnis, machen Sie mit! “ Infolgedessen gibt es
Minen und Geheimnisse , die schwer zu verwalten sind. Wenn sich das Geheimnis geändert hat, dürfen Sie es nicht vergessen, es überall ändern, und es gibt keine Möglichkeit festzustellen, dass es dasselbe Geheimnis ist, außer durch den Namen des Dienstes.
Idee: Kubernetes KMS
In neuen Versionen von Kubernetes ist das KMS-Subsystem Key Management Service eine neue geheime Verschlüsselungsfunktion von Kubernetes. In v1.11 befand es sich im Alpha-Zustand, in v1.12 wurde es in die Beta übertragen.
Das Bild stammt von der KMS-Provider-Projektwebsite für Vault und weist einen Fehler auf. Wenn Sie finden - schreiben Sie in die Kommentare.Die Bedeutung von KMS besteht darin, einen einzigen Nachteil zu beseitigen - die unverschlüsselte Datenspeicherung in etcd.
KMS kann dies wie Ansible.
- Gehen Sie irgendwohin, verschlüsseln Sie das native Geheimnis von Kubernet und verschlüsseln Sie es.
- Bei Bedarf an den Pod liefern, entschlüsseln und in entschlüsselte Form bringen.
Die Entwickler haben einen speziellen Dienst geschrieben, der dies mithilfe der Transitverschlüsselung tut. Die Idee scheint zu funktionieren, aber es ist wichtig, sich daran zu erinnern, dass Geheimnisse nicht mehr nur unter der Kontrolle von Vault stehen und woanders in den Verantwortungsbereich der Kubernetes-Administratoren gehen.
Nachteile KMS.
- Speicherdezentralisierung - Übernahme von Vault zu Kubernetes (etcd) . Geheimnisse werden von Vault unkontrollierbar und eignen sich als zentrales Repository für Geheimnisse. Es stellt sich heraus, dass die Hälfte der Geheimnisse in Vault und die andere Hälfte.
- Nur-Kubernetes-Lösung . Wenn Sie nur über eine Kubernetes-Infrastruktur verfügen, holen Sie sich Vault und denken fast nicht, was dort gespeichert ist, weil Es enthält nur die Verschlüsselungsschlüssel, die Sie korrekt verwalten - regelmäßig drehen usw. ... Die Geheimnisse selbst befinden sich in Kubernetes, und dies ist praktisch.
- Es ist schwierig, Geheimnisse zwischen Clustern auszutauschen . Für jeden neuen Cluster müssen Sie erneut beginnen. Das Kopieren von Geheimnissen wie im Fall eines einzelnen Tresors funktioniert möglicherweise nicht.
Vorteile von KMS.
- Native Unterstützung in Kubernetes, einschließlich Verstecken beim Anzeigen der Umgebung.
- Autorisierung im Verantwortungsbereich von Kubernetes .
- Praktisch keine Vault-Unterstützung erforderlich .
- Schlüsselumdrehung aus der Box .
CI / CD: TeamCity
In TeamCity ist alles einfach, da JetBrains ein Plug-In geschrieben hat, das selbst Geheimnisse für den Zugriff auf das Geheimnis vorschreiben, diese mit TeamCity verschlüsseln und es dann irgendwo in der Vorlage als Parameter in Prozent ersetzen kann. In diesem Moment geht der TeamCity-Agent selbst zu Vault, nimmt das Geheimnis und bringt es als Parameter zum Build.
Während der Bereitstellung werden einige Geheimnisse benötigt, z. B. Datenbankmigration oder Warnungen in Slack. AppRole wird für jedes Projekt gestartet - die Einstellungen enthalten auch ein Geheimnis (Daten für AppRole), werden jedoch im Nur-Schreib-Modus eingegeben - TeamCity erlaubt das spätere Lesen nicht.
TeamCity selbst sorgt dafür, dass sich ein Geheimnis automatisch tarnt, wenn es in die Build-Protokolle eingeht. Infolgedessen wird das Geheimnis entweder überhaupt nicht durch die Festplatte "geleitet" oder mit TeamCity von der Festplatte gelöscht. Infolgedessen wird die gesamte Sicherheit des Geheimnisses durch TeamCity selbst und das Plugin gut gewährleistet, und zusätzliche Tänze mit einem Tamburin sind nicht erforderlich
CI / CD ist nicht TeamCity?
Dies sind die wichtigsten Punkte, die zu berücksichtigen sind, wenn Sie ein anderes System (nicht TeamCity) als CI verwenden.
- Isolation: Beschränken Sie den Umfang eines Geheimnisses auf ein Projekt, ein Team usw.
- Wer autorisiert den Zugriff auf das Geheimnis.
- Schließen Sie die Möglichkeit aus, das Geheimnis der autorisierenden Partei anzuzeigen.
- Eine separate Phase des Builds besteht darin, das Geheimnis in Dateien zu importieren.
- Räumen Sie nach sich selbst auf.
Infolgedessen werden Sie höchstwahrscheinlich etwas schreiben, das dem TeamCity-Plugin für Ihr CI / Ihre CD sehr ähnlich ist. Die autorisierende Partei hier wird höchstwahrscheinlich CI / CD sein, und sie wird entscheiden, ob dieser Build Zugriff auf dieses Geheimnis haben kann und ob sie das Geheimnis selbst basierend auf den Ergebnissen preisgibt oder nicht.
Es ist wichtig, nicht zu vergessen,
die Build-Ergebnisse am Ende der Assembly zu
bereinigen , wenn sie auf einer Festplatte angeordnet waren, oder sicherzustellen, dass sie sich nur im Speicher befinden.
Zertifizierungen
Zertifikate haben nichts Besonderes - wir verwenden Vault hauptsächlich für deren Speicherung.

Vault verfügt über ein spezielles PKI-Backend für die Ausstellung von Zertifikaten, in dem Sie eine Zertifizierungsstelle erstellen und neue Zertifikate signieren können. Wir haben eine einzige interne PKI ... Die Stammzertifizierungsstelle und die Zertifizierungsstelle der zweiten Ebene sind separat vorhanden, und wir verwalten die Zertifizierungsstelle der dritten Ebene bereits über Vault. Um ausgestellte Zertifikate jeder Ebene zu speichern, einschließlich von externen Zertifizierungsstellen signierter Zertifikate, verwenden wir ein separates Präfix und legen dort fast alle gültigen Zertifikate für Buchhaltungs- und Überwachungszwecke ab. Das Format zum Speichern von Zertifikaten ist proprietär und eignet sich zum Speichern eines separaten privaten Schlüssels und des Zertifikats selbst.
Zusammenfassung
Zu viel manuelle Arbeit für den Sicherheitsbeamten,
zu viel Eingabeschwelle für den Entwickler und keine integrierten Delegierungstools, obwohl ich wirklich ...
Wie man ist Dann beginnen die Träume.
Ideen: wie man es besser macht
Wie kann ich ein paar Kopien eines Geheimnisses loswerden?
Lieferung Master-Slave
Wir haben ein Hauptgeheimnis und einen speziellen Dämon, der herumläuft, das Geheimnis und seine Metadaten betrachtet, es wo nötig ablegt und sich als Sklavengeheimnis herausstellt. Auf dem Weg, auf dem der Daemon den Slave gepostet hat, kann nichts von Hand geändert werden, da der Daemon kommt und das Master-Geheimnis wieder auf den Slave legt.
Zuerst wollten wir einen Symlink-Mechanismus erstellen, um einfach anzuzeigen: "Suchen Sie dort nach diesem Geheimnis!", Wie unter Linux. Es stellte sich heraus, dass es Probleme mit Zugriffsrechten gibt: Es ist nicht bekannt, wie Zugriffsrechte überprüft werden sollen - wie unter Linux oder nicht, mit übergeordneten Pfaden, mit Übergängen zwischen Mountpunkten. Es gibt zu viele zweideutige Momente und Chancen, einen Fehler zu machen, deshalb haben wir die Symlinks abgelehnt.
Eigentumsberechtigung
Das zweite, was wir tun möchten, ist
, den Besitzer für jedes Geheimnis zu bestimmen . Standardmäßig gehört das Geheimnis der Person, die es erstellt hat. Bei Bedarf können Sie den Verantwortungsbereich auf die Einheit erweitern, indem Sie eine Eigentümergruppe festlegen.
Wenn wir delegieren lernen, geben wir dem Eigentümer das Recht auf ein Geheimnis, und er kann mit dem Geheimnis tun, was er will.
- In k8s verbreiten - eine Richtlinie wird generiert, eine Slave-Kopie wird erstellt.
- Auf dem Server verteilen - Eine Richtlinie wird generiert, eine Slave-Kopie wird erstellt.
- Verbreitung in CI / CD - ...
- Übertragung an einen anderen Eigentümer.
- Neuen Zugriff gewähren, neue ACLs generieren.
Jetzt sind wir für alle Geheimnisse und die Sicherheit verantwortlich, aber wir möchten die Verantwortung auf den Schöpfer übertragen.
Die Sicherheit wird nicht beeinträchtigt , da die Person, die mit der Bitte um Geheimhaltung zu uns gekommen ist, versteht, dass sie ein Geheimnis sicher aufbewahren muss, und sich ihrer Verantwortung bewusst ist.
Da er der Besitzer des Geheimnisses ist, konnte er für die Master-Slave-Lieferoption auswählen, wo und in welchem Format das Geheimnis an ihn geliefert werden soll. Es stellt sich heraus, dass der Eigentümer alles selbst verwaltet. Es ist nicht erforderlich, Anträge einzureichen. Sie können das erforderliche Präfix selbst verwenden und Geheimnisse selbst erstellen und löschen.
Delegierung über ACL-Vorlagen
Die Zugriffsrichtlinie für die Zugriffssteuerungsliste in Vault ist in zwei Teile unterteilt:
- Zugriffssteuerungsliste in der klassischen Ansicht, die den Zugriff auf das Präfix beschreibt, welche Art zu lesen und zu schreiben ist, welche nur zu lesen ist usw.
- Wenn Sie eine ACL erstellen, können Sie am Ende ein Sternchen schreiben, was "dieses Präfix und alles darunter" bedeutet. Das Präfix kann als separate Operation zugewiesen werden, die dem Benutzer oder der Gruppe zugewiesen wird, dh mehreren verschiedenen Entitäten zugeordnet ist.
Derzeit kann nur der Vault-Administrator die ACL ändern. Nachdem Sie Zugriff auf eine solche ACL erhalten haben, können Sie alles, was Sie möchten, vorschreiben, z. B. den
path “*” { capabilities = [sudo, ...] }
, und vollen Zugriff erhalten. Dies ist die Essenz von
Biggest Flaw # 1 -
es ist unmöglich zu verbieten, den Inhalt der ACL zu ändern .Wir möchten die ACLs mit einer vorgefertigten Vorlage festlegen, die den Pfad und die Platzhalter enthält, auf denen neue ACLs für diese Vorlage generiert werden dürfen.
Beispiel
Unten finden Sie die gelbe Schriftart, den Pfad der fertigen Standard-ACL von Vault und die zulässigen Aktionen auf diesem Pfad. Wir betrachten es als ACL für die Berechtigung, eine andere ACL unten zu ändern, die in Form einer Vorlage angegeben wird.

Wir möchten den Zugriff auf / k8s delegieren, wir lassen nur solche Vorlagen zu generieren. Geben Sie beispielsweise schreibgeschützten Zugriff auf einen bestimmten Cluster, Namespace oder Dienst, ändern Sie jedoch nicht das Feld "Funktionen".

Darüber hinaus möchten wir die Berechtigung erteilen, diese ACLs zu binden und andere Rechte zu erteilen.
Wir haben die Vorlage angewendet, um dem Entwickler Rechte zu gewähren. Beim Templating führte er den
$ vault write policy-mgr/create/k8s-microservice ...
. Als Ergebnis haben wir eine ACL erhalten, die cluster = prod, namespace = ..., service = ... usw. angibt. Die Rechte wurden automatisch festgelegt, eine Richtlinie wurde mit dem Namen
/k8s/some-srv
- dies ist nur der ACL-Name, der aus der Vorlage generiert werden kann.

Infolgedessen weist der Entwickler diese ACL nach unserem Ermessen jedem zu, der dies wünscht, und wird selbst Eigentümer. Er kann sie als Geheimnis verwalten: Löschen, Geben und Entfernen von Benutzern und Gruppen. Jetzt ist die Person selbst für ihr Präfix verantwortlich: Er verwaltet alle Geheimnisse, generiert ACLs gemäß der Vorlage und kann den gewünschten ACLs zuweisen. Natürlich können wir es auch einschränken.
Alle Magie funktioniert mit den neuen Vault-Entity-
Plugins . Sie sind ein separater Dienst, der dem eingangs erwähnten sehr ähnlich ist und fast genauso funktioniert. Der einzige wichtige Unterschied ist, dass sie keine Proxies sind. Plugins werden "auf der Seite" von Vault gestartet und starten ihren Haupt-Vault-Prozess. Aus diesem Grund werden alle Anforderungen nicht über den Dienst, sondern an Vault gesendet, der selbst bereits mit dem Plug-In interagiert und ihm eine verifizierte und gelöschte Anforderung sendet.
Informationen zu Plugins, wie sie angeordnet sind und wie sie geschrieben werden, finden Sie
auf der Vault-Website . Es ist am besten, sie auf Go zu schreiben, was ganz einfach ist, weil Es gibt einen Rahmen für Go. Vault kommuniziert mit dem Plugin über grpc, startet es als Dienst, aber keine Angst, Sie berühren es nicht - alles ist bereits im Framework. Sie schreiben einfach eine mehr oder weniger standardmäßige REST-Anwendung, in der Sie Endpunkte angeben, ihnen vorgefertigte Funktionen und Handler mit Logik zuweisen.
Haben Sie keine Angst, dass Sie etwas im Hauptgewölbe zerbrechen. Ein Plugin ist ein separater Dienst. Selbst wenn Ihr Plugin in Panik geriet und abstürzte, wird es die Arbeit von Vault nicht beeinträchtigen. Vault startet das Plugin einfach neu und arbeitet weiter.
Zusätzlich gibt es zusätzliche Einstellungen für das Plugin selbst: Es überprüft immer die Hash-Summen, damit niemand die Binärdatei ändert.
Die Sicherheit der Ausführung von Plugins ist gewährleistet .
Nützliche Links:
Wir werden über DevOps und Sicherheit, CI / CD, k8s, Puppet und all das in HighLoad ++ (das nächstgelegene in St. Petersburg im April) und DevOpsConf sprechen . Teilen Sie Ihre Erfahrungen mit oder schauen Sie sich andere an. Um nicht zu vergessen, abonnieren Sie den Blog und den Newsletter , in denen wir Sie an Fristen erinnern und nützliche Materialien sammeln.