Welche Vorteile bietet es, geheime Werte einer Website als Umgebungsvariablen zu definieren?

24

In den Devops-Richtlinien unter https://12factor.net/config wird vorgeschlagen , Website-Geheimnisse (Datenbankkennwörter, API-Schlüssel usw.) in Umgebungsvariablen abzulegen. Welche Vorteile hat das, anstatt Textdateien (JSON, XML, YAML, INI oder ähnliches) zu verwenden, die von der Versionskontrolle ignoriert werden?

Ich finde es viel einfacher, eine Konfigurationsdatei mit Geheimnissen zu kopieren, als Umgebungsvariablen in der Konfiguration .bash_profile und webserver zu handhaben. Vermisse ich etwas

Aidas Bendoraitis
quelle
1
Theoretisch ist es einfacher, eine Datei als einen Speicher zu lesen, sodass Sie die Angriffsfläche als größer und die Komplexität als kleiner betrachten können.
Florin Asăvoaie
Die Faustregel meiner Entwickler lautet, dass das Speichern von Einstellungen in Umgebungsvariablen nur in Docker-ähnlichen Umgebungen am besten ist. Außerhalb von Container-VMs genehmigt / bevorzugt er alle anderen Punkte von 12factor.net und die Verwendung von Konfigurationsdateien. Keiner von uns mochte die Unsicherheit von Umgebungsvariablen bei regulären Serverbereitstellungen.
Corey Ogburn

Antworten:

21

Der Autor listet ihre Argumentation auf, obwohl es ein bisschen unzusammenhängend ist. Das Hauptargument ist, dass es leicht ist, eine Konfigurationsdatei versehentlich einzuchecken, und dass Konfigurationsdateien unterschiedliche Formate haben und über das System verstreut sind (alle drei sind bestenfalls mittelmäßige Argumente für sicherheitsbezogene Konfigurationen wie Authentifizierungstoken und Anmeldeinformationen).

Nach meiner eigenen Erfahrung haben Sie im Wesentlichen die folgenden drei Optionen mit den damit verbundenen Vor- und Nachteilen:

Speichern Sie die Daten in Konfigurationsdateien.

Wenn Sie diesen Ansatz wählen, sollten Sie sie idealerweise vom Repository selbst isolieren und sicherstellen, dass sie sich außerhalb des Bereichs befinden, in dem die App ihren Inhalt speichert.

Vorteile:

  • Der Zugriff ist sehr einfach zu isolieren und zu steuern, insbesondere wenn Sie SELinux oder AppArmor verwenden, um die Gesamtsystemsicherheit zu verbessern.
  • Für nicht technische Benutzer im Allgemeinen leicht zu ändern (dies ist ein Vorteil für veröffentlichte Software, jedoch nicht unbedingt für unternehmensspezifische Software).
  • Einfache Verwaltung über große Servergruppen hinweg. Es gibt alle Arten von Tools für die Konfigurationsbereitstellung.
  • Es ist relativ einfach zu überprüfen, welche Konfiguration genau verwendet wird.
  • Für eine gut geschriebene App können Sie die Konfiguration normalerweise ändern, ohne den Dienst zu unterbrechen, indem Sie die Konfigurationsdatei aktualisieren und dann ein bestimmtes Signal an die App senden (normalerweise SIGHUP).

Nachteile:

  • Eine angemessene Planung ist erforderlich, um die Daten sicher zu halten.
  • Möglicherweise müssen Sie unterschiedliche Formate lernen (obwohl sich heutzutage nur noch wenige Sorgen machen müssen und sie im Allgemeinen eine ähnliche Syntax haben).
  • Genaue Speicherorte können in der App fest codiert sein, was die Bereitstellung möglicherweise problematisch macht.
  • Das Parsen der Konfigurationsdateien kann problematisch sein.

Speichern Sie die Daten in Umgebungsvariablen.

In der Regel wird dazu eine Liste von Umgebungsvariablen und -werten aus dem Startskript bezogen, in einigen Fällen werden sie jedoch möglicherweise nur in der Befehlszeile vor dem Programmnamen angegeben.

Vorteile:

  • Im Vergleich zum Parsen einer Konfigurationsdatei ist das Abrufen eines Werts aus einer Umgebungsvariablen in so gut wie jeder Programmiersprache trivial.
  • Sie müssen sich nicht so viele Sorgen machen, wenn Sie die Konfiguration versehentlich veröffentlichen.
  • Sie gewinnen ein gewisses Maß an Sicherheit durch Unbekanntheit, da diese Vorgehensweise ungewöhnlich ist und die meisten Leute, die Ihre App hacken, nicht sofort daran denken, Umgebungsvariablen zu betrachten.
  • Der Zugriff kann von der Anwendung selbst gesteuert werden (wenn untergeordnete Prozesse gestartet werden, kann die Umgebung leicht gesäubert werden, um vertrauliche Informationen zu entfernen).

Nachteile

  • Auf den meisten UNIX-Systemen ist es relativ einfach, auf die Umgebungsvariablen eines Prozesses zuzugreifen. Einige Systeme bieten Möglichkeiten, dies zu verringern ( z. B. die hidepidMount-Option /procunter LInux), sind jedoch standardmäßig nicht aktiviert und schützen nicht vor Angriffen des Benutzers, dem der Prozess gehört.
  • Es ist nicht trivial, die genauen Einstellungen zu sehen, die verwendet werden, wenn Sie das oben erwähnte Sicherheitsproblem richtig behandeln.
  • Sie müssen darauf vertrauen, dass die App die Umgebung bereinigt, wenn untergeordnete Prozesse erzeugt werden. Andernfalls gehen Informationen verloren.
  • Sie können die Konfiguration nicht ohne einen vollständigen Neustart der App ändern.

Verwenden Sie Befehlszeilenargumente, um die Daten zu übergeben.

Im Ernst, vermeiden Sie dies um jeden Preis, es ist nicht sicher und es ist ein Ärgernis, es beizubehalten.

Vorteile:

  • Noch einfacher als Umgebungsvariablen in den meisten Sprachen zu analysieren.
  • Untergeordnete Prozesse erben die Daten nicht automatisch.
  • Bietet eine einfache Möglichkeit, bestimmte Konfigurationen bei der Entwicklung der Anwendung schnell zu testen.

Nachteile:

  • Genau wie Umgebungsvariablen ist es auf den meisten Systemen einfach, die Befehlszeile eines anderen Prozesses zu lesen.
  • Sehr mühsam, die Konfiguration zu aktualisieren.
  • Setzt eine feste Grenze für die Länge der Konfiguration (manchmal nur 1024 Zeichen).
Austin Hemmelgarn
quelle
1
Ein nicht unwichtiger Punkt ist das unbeaufsichtigte (Neustarten) eines Servers, ohne manuell irgendwelche Passwörter eingeben zu müssen. Am Ende befinden sie sich dafür irgendwo auf der Festplatte
PlasmaHH
7
Auf den meisten UNIX-Systemen können Sie so ziemlich alle Prozessumgebungsvariablen lesen, ohne wesentliche Berechtigungen zu benötigen. - Können Sie das näher erläutern? Die Datei / proc / #### / environ kann nur vom Eigentümer gelesen werden. Sie müssen also root sein oder sudo haben.
Rrauenza
Ich denke, ein Teil dieses env config-Trends ist auch auf Dinge wie docker zurückzuführen, bei denen Sie einen Standardcontainer verwenden und ihn konfigurieren, indem Sie env-Variablen an den Container übergeben.
Rrauenza
@rrauenza Die Inhaberschaft eines Prozesses ist kein wesentliches Privileg, es sei denn, Sie haben eine sehr gute Arbeit bei der Trennung der Dinge nach Konto geleistet, und Sie benötigen tatsächlich nur die CAP_SYS_ADMIN-Funktion (die Root implizit hat), wenn Sie nicht der Eigentümer sind. Auch in Bezug auf die Umgebungsvariable haben Sie wahrscheinlich Recht, aber es ist auch mit Docker ein marginales Design.
Austin Hemmelgarn
3
Ich stimme dem Punkt @rrauenza zu. Die Antwort ist im Großen und Ganzen großartig, aber ich möchte klarstellen, wie genau Sie so ziemlich alle Prozessumgebungsvariablen lesen können, ohne signifikante Berechtigungen zu benötigen . In Bezug auf " und Sie benötigen nur die CAP_SYS_ADMIN-Funktion (die implizit als Root fungiert) ..." ist eine weitere Diskussion überflüssig, wenn ein böswilliger Agent über Root-Berechtigungen verfügt, und CAP_SYS_ADMIN kann auch als Root-Berechtigung fungieren (siehe man7.org/linux) /man-pages/man7/capabilities.7.html , CAP_SYS_ADMIN und Hinweise für Kernel-Entwickler )
Nubarke
13

Umgebungsvariablen werden von jedem untergeordneten Prozess des Webservers geerbt. Das ist jede Sitzung, die eine Verbindung zum Server herstellt, und jedes von ihnen erzeugte Programm. Die Geheimnisse werden all diesen Prozessen automatisch enthüllt.

Wenn Sie Geheimnisse in Textdateien aufbewahren, müssen diese für den Serverprozess und möglicherweise auch für jeden untergeordneten Prozess lesbar sein. Aber zumindest müssen die Programme gehen und sie finden; Sie werden nicht automatisch bereitgestellt. Möglicherweise können Sie auch einige untergeordnete Prozesse unter verschiedenen Konten ausführen und die Geheimnisse nur für diese Konten lesbar machen. Zum Beispiel macht suEXEC dies in Apache.

Andrew Schulman
quelle
1
"Das ist jede Sitzung, die eine Verbindung zum Server herstellt" ist eine irreführende Aussage. Sie können keine http-Sitzung für den Server öffnen und Zugriff auf dessen Umgebungsvariablen erhalten. Sie können sich auch nicht bei einer Shell auf diesem Server anmelden und diese abrufen, es sei denn, Sie verfügen über Root-Zugriff oder besitzen den Webserverprozess.
Segfault
Jeder vom Webserver ausgehende Prozess erbt seine Umgebung, sofern Sie keine anderen aktiven Schritte ausführen. Eine HTML-Seite kann diese Informationen nicht verwenden, ein Skript jedoch.
Andrew Schulman
Diese Antwort ist zwar richtig, könnte jedoch einige Korrekturen / Zugeständnisse enthalten, insbesondere im Hinblick auf die Term- Sessions . Auf den ersten Blick scheint es, als würde die Verwendung von Umgebungsvariablen in einem schlechten Licht erscheinen, fast um einem externen Kunden Möglichkeiten der Offenlegung von Informationen vorzuschlagen. Es kann auch eine mit suexec vergleichbare Konzession für die eingeschränkte Einstellung von env-vars gemacht werden. Beispielsweise begrenzt die Einstellung von env-vars (a la MYVAR=foo /path/to/some/executable) die Weitergabe auf einen Prozess und dessen untergeordnete Elemente - und bei Bedarf können Master-Daemons scrubben / zurücksetzen / ändern die Umgebung der Kindprozesse.
Shalomb
2

Auch wenn es einige sicherheitsrelevante Kompromisse bei Umgebungsvariablen oder -dateien gibt, glaube ich nicht, dass die Sicherheit die Hauptantriebskraft für diese Empfehlung war. Denken Sie daran, dass die Autoren von 12factor.net auch (oder waren auch?) Entwickler des Heroku PaaS sind. Die Verwendung von Umgebungsvariablen für jedermann hat ihre Entwicklung wahrscheinlich erheblich vereinfacht. Es gibt so viele verschiedene Konfigurationsdateiformate und -speicherorte, dass es für sie schwierig gewesen wäre, sie alle zu unterstützen. Umgebungsvariablen sind im Vergleich einfach.

Es braucht nicht viel Vorstellungskraft, um einige der geführten Gespräche zu erraten.

Entwickler A: "Ah, diese geheime Konfigurationsdatei-Benutzeroberfläche ist zu unübersichtlich! Müssen wir wirklich ein Dropdown-Menü haben, das zwischen json, xml und csv wechselt?"

Entwickler B: "Oh, das Leben wäre so großartig, wenn nur alle Umgebungsvariablen für die App-Konfiguration verwenden würden."

Entwickler A: "Tatsächlich gibt es einige plausible sicherheitsrelevante Gründe dafür. Umgebungsvariablen werden wahrscheinlich nicht versehentlich in die Quellcodeverwaltung eingecheckt."

Entwickler B: "Legen Sie die Umgebungsvariablen nicht mit einem Skript fest, das den Dämon startet, oder mit einer Konfigurationsdatei?"

Entwickler A: "Nicht in Heroku! Wir werden sie dazu bringen, sie in die Benutzeroberfläche einzutippen."

Entwickler B: "Oh, schau, mein Domainnamen-Alarm für 12factor.net ist gerade ausgegangen." 1


1 : Quelle: erfunden.

Segfault
quelle
1

TL; DR

Es gibt eine Reihe von Gründen, Umgebungsvariablen anstelle von Konfigurationsdateien zu verwenden. Zwei der häufigsten Gründe, die übersehen werden müssen, sind der Nutzwert der Out-of-Band-Konfiguration und die verbesserte Trennung zwischen Servern, Anwendungen oder Organisationsrollen. Anstatt eine erschöpfende Liste aller möglichen Gründe vorzulegen, spreche ich in meiner Antwort nur diese beiden Themen an und gehe leicht auf deren Auswirkungen auf die Sicherheit ein.

Out-of-Band-Konfiguration: Geheimnisse vom Quellcode trennen

Wenn Sie alle Ihre Geheimnisse in einer Konfigurationsdatei speichern, müssen Sie diese Geheimnisse auf jeden Server verteilen. Dies bedeutet entweder, dass Sie die Geheimnisse zusammen mit Ihrem Code in die Revisionskontrolle einchecken oder dass Sie ein völlig separates Repository oder einen separaten Verteilungsmechanismus für die Geheimnisse haben.

Das Verschlüsseln Ihrer Geheimnisse hilft dabei nicht wirklich. Alles, was Sie tun müssen, ist, das Problem zu entfernen, denn jetzt müssen Sie sich auch um die Schlüsselverwaltung und -verteilung kümmern!

Kurz gesagt, Umgebungsvariablen sind ein Ansatz zum Verschieben von Daten pro Server oder pro Anwendung aus dem Quellcode, wenn Sie die Entwicklung von den Vorgängen trennen möchten. Dies ist besonders wichtig, wenn Sie Quellcode veröffentlicht haben!

Verbesserung der Trennung: Server, Anwendungen und Rollen

Während Sie sicherlich eine Konfigurationsdatei für Ihre Geheimnisse haben könnten, haben Sie ein Spezifitätsproblem, wenn Sie die Geheimnisse im Quellcode speichern. Haben Sie für jeden Satz von Geheimnissen eine eigene Filiale oder ein eigenes Repository? Wie stellen Sie sicher, dass die richtigen Geheimnisse zu den richtigen Servern gelangen? Oder verringern Sie die Sicherheit, indem Sie "Geheimnisse" haben, die überall gleich sind (oder überall lesbar sind, wenn Sie alle in einer Datei haben) und daher ein größeres Risiko darstellen, wenn die Sicherheitskontrollen eines Systems ausfallen?

Wenn Sie auf jedem Server oder für jede Anwendung eindeutige Geheimnisse haben möchten, müssen Sie mit Umgebungsvariablen nicht mehr eine Vielzahl von Dateien verwalten. Wenn Sie einen neuen Server, eine neue Anwendung oder eine neue Rolle hinzufügen, müssen Sie keine neuen Dateien erstellen oder alte aktualisieren. Sie aktualisieren lediglich die Umgebung des betreffenden Systems.

Abschiedsgedanken zur Sicherheit

Obwohl eine gründliche Untersuchung der Kernel-, Speicher- und Dateisicherheit für diese Antwort nicht in Frage kommt, sollte darauf hingewiesen werden, dass ordnungsgemäß implementierte Umgebungsvariablen pro System nicht weniger sicher sind als "verschlüsselte" Geheimnisse. In beiden Fällen muss das Zielsystem das entschlüsselte Geheimnis noch irgendwann im Speicher halten, um es verwenden zu können.

Es ist auch erwähnenswert, dass es keine Datei auf der Festplatte gibt, die kopiert und offline angegriffen werden kann, wenn Werte in einem flüchtigen Speicher eines bestimmten Knotens gespeichert sind. Dies wird im Allgemeinen als Vorteil für In-Memory-Geheimnisse angesehen, ist aber sicherlich nicht schlüssig.

Bei der Frage der Umgebungsvariablen im Vergleich zu anderen Geheimhaltungs-Management-Techniken geht es mehr um Kompromisse zwischen Sicherheit und Benutzerfreundlichkeit als um absolute Werte. Ihr Kilometerstand kann variieren.

CodeGnome
quelle
2
Dies ist nicht überzeugend, da alle Nachteile, die Sie für Konfigurationsdateien erwähnen, auch für Umgebungsvariablen gelten. Umgebungsvariablen sind Konfigurationsdaten. Sie stellen sich nicht magisch ein. Sie müssen auf jedes System verteilt werden, und es muss ein Konfigurationsmechanismus verwendet werden, um sie festzulegen.
Jpaugh
@jpaugh Du bist ein Strohmann-Argument und greifst etwas an, was ich nie gesagt habe. Die Probleme, die ich anspreche, sind Out-of-Band-Konfiguration und Datentrennung. Wie klar erklärt, können Sie diese Dinge nach Belieben ausführen. Wenn Sie es vorziehen, können Sie Ihre Geheimnisse neben Ihrem Code öffentlich auf GitHub veröffentlichen, aber das scheint im Allgemeinen sicherlich unklug zu sein. Aber nur Sie können die Kompromisse notwendig bestimmen , die für Ihr System ordnungsgemäß innerhalb einer bestimmten Bedrohungsmodell zu arbeiten.
CodeGnome
2
Alle Ihre Punkte sind korrekt, mit der Ausnahme, dass sie für Umgebungsvariablen genauso gelten wie für andere Konfigurationsdaten. Wenn Sie Umgebungsvariablen in Dateien speichern, können Sie sie festschreiben. und wenn Sie sie außerhalb des Bandes senden, ist es einfacher, sie in eine Datei einzutippen, als sie einzutippen. Wenn Sie sie jedoch lieber eingeben möchten, geben Sie stattdessen ein JSON-Objekt aus und lesen Sie es in stdin. Das ist eigentlich sicherer als die Kommandozeile.
Jpaugh
1

Persönlich würde ich nicht empfehlen, Umgebungsvariablen in zu setzen .bashrc da diese für alle von der Shell gestarteten Prozesse sichtbar werden. Sie sollten jedoch auf Dämon- / Supervisor-Ebene (Init / RC-Skript, Systemd-Konfiguration) festgelegt werden, damit ihr Umfang auf den erforderlichen Bereich beschränkt wird .

Wenn separate Teams Vorgänge verwalten, bieten Umgebungsvariablen eine einfache Schnittstelle für Vorgänge zum Festlegen der Umgebung für die Anwendung, ohne die Konfigurationsdateien / -formate kennen zu müssen und / oder auf das Verwerfen ihres Inhalts zurückzugreifen. Dies gilt insbesondere für Einstellungen in mehreren Sprachen und mit mehreren Frameworks, bei denen die Betriebsteams das Bereitstellungssystem (Betriebssystem, Supervisor-Prozesse) basierend auf den betrieblichen Anforderungen (einfache Bereitstellung, Skalierbarkeit, Sicherheit usw.) auswählen können.

Eine weitere Überlegung betrifft CI / CD-Pipelines - da der Code verschiedene Umgebungen durchläuft(z. B. dev, test / qa, Staging, Produktion) Die Angaben zur Umgebung (Bereitstellungszonen, Angaben zur Datenbankverbindung, Anmeldeinformationen, IP-Adressen, Domänennamen usw.) werden am besten von dedizierten Konfigurationsverwaltungstools / -frameworks festgelegt und von der Anwendung verwendet Prozesse aus der Umgebung (in einem DRY, einmal schreiben, überall ausführen). In der Regel checken Entwickler Konfigurationsdateien oder -vorlagen neben Code ein, wenn sich die betrieblichen Anforderungen ändern (z. B. neue Umgebungen / Bereitstellungen / Standorte, Skalierbarkeit / Sicherheit) wiegen sie herein,

  • Env-Vars vereinfachen die Konfiguration / Komplexität im Maßstab.
  • Env-vars legt die Betriebskonfiguration direkt beim für den Nicht-Code zuständigen Team fest in einer einheitlichen (wenn nicht standardmäßigen) unverbindlichen Weise Aspekte der Anwendung .
  • Env-vars unterstützt das Auslagern der Master- / Supervisor-Prozesse (z. B. god, monit, supervisord, sysvinit, systemd usw.), die die Anwendung unterstützen, und sicherlich auch das Deployment-System (Betriebssysteme, Container-Images usw.) als Betriebsanforderungen entwickeln / ändern. Heutzutage hat jedes Sprach-Framework eine Art Prozesslaufzeit, diese sind jedoch in der Regel ineffizient, eher für Entwicklungsumgebungen geeignet und / oder erhöhen die Komplexität in Produktionsumgebungen mit mehreren Sprachen / Frameworks.

Für die Produktion favorisieren Einstellung ich die Anwendung env-Vars in einem EnvironmentFile wie , /etc/default/myapplication.confdass nur durch das Konfigurationsmanagement und setzen lesbar eingesetzt wird , rootso dass systemd(oder irgendetwas anderes für diese Angelegenheit) kann die Anwendung unter einem dedizierten laichen Deprivileged Systembenutzer in einem privaten Gruppe . Unterstützt mit dedizierten Benutzergruppen für opsund sudo- Diese Dateien sind standardmäßig nicht weltweit lesbar. Dies ist 12-Faktor-konform und unterstützt alle Vorteile von Dev + Ops sowie alle Vorteile angemessener Sicherheit, während Entwickler / Tester ihre eigenen EnvironmentFiles in den Umgebungen dev / qa / test ablegen können.

shalomb
quelle
0

Aus Entwicklersicht vereinfacht das Speichern von Konfigurationsdaten in Umgebungsvariablen die Bereitstellung in verschiedenen Umgebungen - Entwicklung, Qualitätssicherung und Produktion - und macht es Entwicklern leichter, sich Gedanken über die Bereitstellung der falschen Konfigurationsdatei zu machen.

Azure-Webanwendungen bieten die Möglichkeit, dieses Muster zu verwenden, und es funktioniert sehr gut.

Darüber hinaus werden potenziell sensible Daten außerhalb der Quellcodeverwaltung gehalten. Das Ignorieren dieser Dateien aus der Quellcodeverwaltung ist (zumindest in .NET) nicht wirklich machbar, da in diesen Dateien auch eine Menge der erforderlichen Boilerplate-Konfiguration vorhanden ist.

Derek Gusoff
quelle