Was ist die bevorzugte Methode zum Speichern von Anwendungskonfigurationen?

38

Die meiste Zeit speichere ich die Konfiguration der Entwicklungsanwendung wie folgt im Stammverzeichnis des Projekts:

app
|-- config.json

Dies scheint jedoch nicht der beste Ansatz zu sein, da diese Konfiguration letztendlich im Versionskontrollsystem gespeichert wird - was möglicherweise zu einem Verlust von Benutzernamen, Passwörtern und anderen sensiblen Inhalten führt.

Im 12 Factor App- Handbuch wird empfohlen, die Konfigurationsdateien vollständig zu löschen und Umgebungsvariablen für die Konfiguration zu verwenden:

... speichert die Konfiguration in Umgebungsvariablen. Env-Vars können zwischen Bereitstellungen problemlos geändert werden, ohne dass Code geändert werden muss. Im Gegensatz zu Konfigurationsdateien besteht nur eine geringe Wahrscheinlichkeit, dass sie versehentlich in das Code-Repo eingecheckt werden. Im Gegensatz zu benutzerdefinierten Konfigurationsdateien oder anderen Konfigurationsmechanismen wie Java-Systemeigenschaften sind sie ein sprach- und betriebssystemunabhängiger Standard.

Das hört sich für mich wirklich gut an, aber wo speichert man die Umgebungsvariablen, ohne sie in die Quellcodeverwaltung einzuchecken? Und mit welchen Tools kann ich diese Variablen an die App übergeben? Es kann Dutzende von Konfigurationsoptionen geben, und es ist nicht schön, sie bei jedem Start der App von Hand einzugeben - sie müssen also irgendwo in einer Datei gespeichert werden. Die Datei wird somit in der Quellcodeverwaltung enden und wir kehren zu dem Punkt zurück, an dem wir begonnen haben.

Gibt es eine allgemein akzeptierte Möglichkeit, mit Konfigurationsoptionen umzugehen, die nicht das Risiko birgt, lokale Konfigurationen in der Quellcodeverwaltung zu speichern?

Rogach
quelle
1
Na ja, zumindest hat git so etwas wie .gitignorewo ich Dateien oder Ordner definieren kann, die nicht in die Versionskontrolle eingecheckt werden sollen. Wie Sie sagen, sehe ich nicht, wo Env-Vars wirklich helfen sollten, z. B. haben Sie ein Skript, um sie festzulegen, und sollten zusammen mit dem Projekt gespeichert werden, oder Sie haben sie "irgendwo" auf Ihrem System (Basisverzeichnis oder sogar beim Starten des Computers) Skripte), die für sich genommen eine Menge Probleme aufwerfen, insbesondere wenn eine Menge Konfiguration erforderlich ist. In jedem Fall würde ich die Konfigurationsdateien so aufteilen, dass vertrauliche Informationen in verschiedenen Dateien gespeichert werden.
thorsten müller
@ thorstenmüller - einziges problem mit .gitignore, dass die base / template-konfiguration noch gespeichert werden muss, was bedeutet, dass die app zwei configs lesen muss - base one mit standardoptionen (in scm gespeichert) und local one, die base (und überschreiben) ist nicht in scm gespeichert). Ich stelle mir vor, dass die Massenbereitstellung mit env vars einfacher wird - es ist einfacher, Umgebungsvariablen für die Einrichtung neuer virtueller Maschinen anzugeben, als etwas in eine nicht standardmäßige Datei zu schreiben.
Rogach
Gute Frage, nachdem ich damit angefangen hatte, den normalen benutzerspezifischen Anwendungsdatenspeicher zu verwenden, wurde das Leben einfacher ;-)
Wolf
1
Haben Sie versucht "Redis" redis.io . Es ist speziell nur für die Speicherung von Schlüsselwerten gedacht.
Karan,
2
@jporcenaluk - Ich mag Speicher mit Schlüsselwerten, aber das Hinzufügen eines vollständigen Redis zu einer Anwendung, nur um die Konfigurationsverwaltung zu handhaben, fühlt sich wie ein bisschen übertrieben an. Andererseits habe ich vielleicht nie an ausreichend großen Projekten gearbeitet.
Rogach

Antworten:

16

Möglicherweise gibt es keine gute Antwort darauf. Es scheint, dass Sie diese Daten an einem sicheren Ort speichern müssen, da sie eines Tages für Disaster Recovery-Zwecke benötigt werden. Dies gilt gleichermaßen für Eigenschaftendateien und Skripts, mit denen Umgebungsvariablen festgelegt werden.

  • Mit dem Quellcode (in SVN / GIT usw.) ist eine wirklich schlechte Idee, da diese Daten Produktionsdatenbank-Passwörter und dergleichen enthalten.
  • Das nächtliche Backup Ihres Unternehmens ist zwar ausreichend, es ist jedoch unwahrscheinlich, dass ein leicht zugänglicher Änderungsverlauf vorliegt.
  • Die Daten müssen separat zur konsumierenden Software versioniert werden. In unserem aktuellen System führt eine Änderung der Konfiguration zu einer neuen Anwendungserstellung, und dies ist einfach falsch.

Wir suchen derzeit nach Lösungen für dieses Problem und tendieren zu einem Code-Repository mit eingeschränktem Zugriff. Dieses Repository würde nur Konfigurationsdaten enthalten. Haben andere Erfahrungen zu teilen?

Kiwiron
quelle
2
Es scheint keine gute Idee zu sein, zwei separate Repositorys für ein Projekt zu haben - Sie können keine bereinigten Rollbacks durchführen oder mit Zweigen arbeiten, da Sie dann zwei Repositorys gleichzeitig bearbeiten müssen (z. B. erfordert ein anderer Zweig eine neue Konfigurationsoption) Wechseln Sie zu diesem neuen Zweig, ohne auch das Konfigurations-Repository zu wechseln.
Rogach
2
@ Rogach Ich nehme Ihren Punkt. Es gibt triftige Gründe, den Code in irgendeiner Konfiguration zu belassen, aber wie Sie in Ihrer Frage sagen, müssen vertrauliche Dinge anderswo abgelegt werden. Zwei Repositories scheinen also unvermeidlich. Außerdem habe ich nicht erwähnt, dass App-Server hier oft helfen. Datenquellen und JNDI-Variablen können vom Administrator eingerichtet werden und sind nicht öffentlich.
Kiwiron
Ein zweiter Laden macht Sinn. Möglicherweise werden andere, auch vertrauliche Arten von Daten zusammen mit der Konfiguration gespeichert (z. B. Produktionsdaten, die analysiert werden, um Kundenprobleme zu beheben).
Wolf
1
@Rogach Sie scheinen viel Hass auf sich zu ziehen, aber Git-Submodule würden das in Ordnung bringen, denke ich - wenn das Haupt-Repo richtig eingerichtet wäre und das Repo mit eingeschränktem Zugriff nur darin leben könnte.
SeldomNeedy
9

Bei der Untersuchung von Problemen und möglichen Lösungen hilft es mir, eine Methode anzuwenden Wenn von Jeff Atwood verbreitete anwenden : Wenn Gott eine Möglichkeit schaffen würde, vertrauliche Konfigurationsinformationen zu speichern, wie würde er das tun?

Nun, er würde wissen, wer Konfigurationsinformationen benötigt, und diese nur an diese Personen weitergeben, und auf die Informationen könnte von niemand anderem zugegriffen werden.

Der erste Teil sollte bereits erledigt sein: Ihr Versionsverwaltungssystem sollte Benutzer authentifizieren. Und dieser Ansatz wird auch nach # 10 in Gültigkeit gegeben Troy Hunts 10 Geboten der Quellcodeverwaltung bestätigt : "Abhängigkeiten müssen in der Quellcodeverwaltung sein".

Aber wie hält man es sicher, wenn es durchgesickert ist? Nun, es muss dort nicht im Klartext gespeichert werden! Verwenden Sie die Verschlüsselung. In .NET können Sie Schritte ausführen, um Verbindungszeichenfolgendaten in Ihren Konfigurationsdateien zu verschlüsseln . Sie müssten die entsprechenden Methoden finden, um dies mit der Technologie Ihrer Wahl zu tun.

jporcenaluk
quelle
3
Wollte nur klären - wie hilft die Verschlüsselungskonfiguration? Soweit ich weiß, müssen Sie für alle Entwickler dasselbe Entschlüsselungskennwort verwenden, und das klingt, als würden Sie Probleme melden.
Rogach
Wenn jemand außerhalb Ihres Unternehmens Zugriff auf Ihr Repository erhält, werden Ihre Kennwörter verschleiert. Wenn jemand die Dateien von einem Projekt auf ein USB-Laufwerk kopiert und sie irgendwo liegen lässt, ist das dasselbe. Es wird natürlich mehr Arbeit zu warten sein. Mehr Sicherheit geht in der Regel mit Komfort einher. Diese Lösung ist etwas unhandlich, das gebe ich Ihnen. Ich bin offen für einen besseren Weg, um die Frage des OP zu lösen!
jporcenaluk
5

Viele Leute kritisieren das Speichern der Konfiguration in regulären Dateien zusammen mit Ihrem Quellcode, aber meiner Erfahrung nach ist dies eine ziemlich gute Lösung:

  • Einfach in jeder Sprache zu implementieren. In vielen Fällen erhalten Sie sofort Unterstützung für komplexe Konfigurationsdateien. Im Fall von Java mit Spring Boot erhalten Sie beispielsweise YAML-Unterstützung, die jede baumartige Struktur ausdrücken kann, und es ist einfach, separate Konfigurationsdateien für verschiedene Umgebungen sowie eine Basiskonfiguration zu haben, von der umgebungsspezifische Dateien erben können.
  • Zum Ausführen Ihrer Software ist eine Konfiguration erforderlich. Änderungen am Code erfordern häufig das Hinzufügen / Ändern von Konfigurationseinstellungen. Daher ist es natürlich, Konfiguration und Code zusammen zu halten.
  • Das Speichern der Konfiguration mit der Quelle bietet Ihnen alle Vorteile der Quellcodeverwaltung, z. B. das Wissen, wer welche Einstellung geändert hat und wann oder in der Lage ist, die Konfigurationen während einer regelmäßigen Codeüberprüfung zu überprüfen.
  • Wenn Sie nicht für die CIA arbeiten, scheint mir das Sicherheitsargument übertrieben. Ihr Datenbankkennwort wird also in einer Datei auf dem Computer gespeichert, auf dem Ihre App ausgeführt wird. Nun, wenn jemand mit Ihrer App Zugriff auf den Computer erhält, sind Sie wahrscheinlich bereits in großen Schwierigkeiten - er kann z. B. Ihre App herunterfahren und an seiner Stelle am selben Port eine eigene App starten. In einem solchen Szenario ist der Zugriff auf das DB-Kennwort möglicherweise kein so großes Problem. Sofern nicht alle Ihre Verbindungen vollständig verschlüsselt sind und Zugriff auf Ihr Gerät haben, können sie trotzdem einen Großteil der interessanten Daten von Netzwerkschnittstellen abrufen.
  • Mit einem Tool wie Hiera können Sie eine Textkonfigurationsdatei erstellen, in der jedoch keine Kennwörter oder andere vertrauliche Daten gespeichert sind.

In vielen Fällen ist die in der Quellcodeverwaltung gespeicherte Textkonfiguration zusammen mit dem Code ein guter Anfang.

Wenn Sie sich für verteilte Systeme interessieren oder Ihre Konfiguration im laufenden Betrieb austauschen möchten, ohne Ihre Anwendungen erneut bereitstellen zu müssen, finden Sie möglicherweise eine Lösung, die auf einem Konfigurationsserver basiert. Spring Cloud unterstützt solche Mechanismen , und die Back-End-Serving-Konfigurationen können ein Git-Repository oder Eureka sein . Sie können auch Ihre eigenen mit zB Zookeeper rollen . Jede dieser Methoden erleichtert die Verwaltung konsistenter Konfigurationen auf vielen Servern, um Konfigurationen zu aktualisieren, ohne dass die Software neu erstellt und bereitgestellt werden muss. Dies ist natürlich mit Kosten verbunden, da der Konfigurationsserver und seine Verwendung von Ihren Anwendungen sowie von einem weiteren zu implementierenden und zu wartenden System gelernt werden.

Michał Kosmulski
quelle
Aber der Code wechselt die Hand zu jemandem, der nicht die Geheimnisse in den Konfigurationsdateien besitzt, es wird ein echtes Durcheinander geben.
Tim Ludwinski
@TimLudwinski Schlüssel / Geheimnisse gehören der Firma, nicht einzelnen Entwicklern, daher sollten sie so gepflegt werden, dass sie nicht verloren gehen, wenn eine einzelne Person abreist. Dies können Probleme sein, die beispielsweise von Administratoren / Sicherheitsteams verwaltet werden, sodass eine zentrale Registrierung vorhanden ist.
Michał Kosmulski
5

Wir haben das gleiche Problem, wo ich arbeite. Im Moment sind alle unsere Konfigurationen dateibasiert und werden von den einzelnen Anwendungen, die sie verwenden, als Quelle gesteuert. Dies führt dazu, dass Duplikate erstellt werden und die Entwickler Zugriff auf Produktions- / QA-Kennwörter haben, anstatt nur auf die Entwicklung.

Trotzdem denke ich, dass wir in Zukunft eine gute Lösung gefunden haben. Wir verschieben unsere Konfigurationsdateien in ein separates Git-Repo (das als Config-Repo bezeichnet wird). Wir haben dann einen Spring-Cloud-Config-Server (Java) eingerichtet, der einfach die Dateien aus dem Konfigurations-Repository basierend auf den an ihn übergebenen Profilen bereitstellt. Dies ist ideal für Java-Anwendungen, die den Client verwenden und diese beim Start herunterladen können. Für unsere PHP / Non-Java-Apps ziehen wir die Datei direkt herunter. (Nicht ideal). In Zukunft werden wir vielleicht etwas schreiben, mit dem die PHP-Anwendung die Configs von sich aus herunterladen und irgendwo zwischenspeichern kann, aber es hat keine hohe Priorität für den ersten Durchlauf. Ich betrachte diese Lösung als Config-as-a-Service, der die 12-Faktor-Apps-Empfehlungen nicht explizit verletzt.

Ich glaube, Zookeeper kann für die gleiche Sache verwendet werden (ich habe ein Setup mit Kubernetes + Zookeeper gesehen), also bin ich mir nicht ganz sicher, warum diese Antwort oben ein -1 bekam.

Links:

https://spring.io/guides/gs/centralized-configuration/

https://cloud.spring.io/spring-cloud-config/

ssjcory
quelle
3

Speichern Sie die gesamte Konfiguration nicht in einer Datei, sondern in mehreren Dateien.

  • Haben Sie ein Konfigurationsverzeichnis . Alle Dateien dort werden als Konfigurationsdateien interpretiert, außer vielleicht README*.
  • Alle Dateinamen sind alphabetisch sortiert und die Dateien werden in dieser Reihenfolge geladen. Aus diesem Grunde Dateien in solchen Fällen oft mit einer Ziffer oder zwei beginnen: 01-logging.json. 02-database.json, etc.
  • Daten aus allen Dateien werden in dieselbe Konfigurationsstruktur geladen, die der Anwendung zur Verfügung steht. Auf diese Weise können mehrere Dateien die Einstellungen der anderen ergänzen und sogar vorhersehbar überschreiben.
  • Speichern Sie die Konfigurationsdateien nur mit sicheren Werten oder Standardwerten im VCS. Fügen Sie die Konfigurationsdateien während der Bereitstellung mit Geheimnissen hinzu, oder verwenden Sie noch besser einen authentifizierten Geheimnisse-Speicherdienst.

Schauen Sie sich auf Ihrer nächsten Linux-Box /etc/sudoers.doder an /etc/nginx/conf.d. Es zeigt das gleiche Muster.

Secrets Management ist ein anderes Biest. Sie können sie als manuellen Schritt verwalten, während Sie klein sind. Sie können Dinge wie Zookeeper verwenden. Sie können die Geheimnisse sogar in verschlüsselter Form in ein VCS einchecken und sie als Bereitstellungsschritt entschlüsseln. Es gibt eine Reihe weiterer Optionen.

(Außerdem ein Kommentar: JSON ist kein gutes Konfigurationsdateiformat, da es keine Kommentare zulässt. Kommentare sind von entscheidender Bedeutung. TOML-, YAML- und sogar INI-Formate sind in der Praxis besser geeignet.)

9000
quelle
2

Ich denke, Ihre Optionen werden in gewisser Weise von dem Betriebssystem bestimmt, auf dem Sie die Bereitstellung durchführen

Ich würde vorschlagen, die Werte ja in die Quellcodeverwaltung zu stellen. ABER nur die 'dev' Versionen. Sie möchten, dass Ihr Quellcode kompiliert UND funktioniert! keine zusätzlichen geheimen Schritte enthalten

Ihr Erstellungs- und Bereitstellungsprozess sollte diese Werte dann während der Bereitstellung pro Umgebung austauschen. (Krake hat diese Art von Modell)

Ewan
quelle
0

Apache zookeeper bietet wundervolle Optionen zum Speichern der Anwendungskonfigurationen für verteilte Systeme. Am Zookeeper vorgenommene Änderungen können erfasst und verarbeitet werden, indem ein Kurator oder ein Zookeeper-Listener am Anwendungsende anwesend ist.

Geld
quelle
6
Wie lauten die Optionen? wie funktioniert es? Wo lagert es sie? Wird einer dem anderen vorgezogen? Was sind die verschiedenen Vor- und Nachteile jeder Option? Wie interagiert dies auf verschiedenen Betriebssystemen?
3
@Gangz - Ich wäre an einer ausführlicheren Antwort interessiert. Lassen Sie sich von den Abstimmungen nicht entmutigen und verbessern Sie Ihre Antwort, damit sie hilfreich sein kann.
Jay Elston