Eine der frustrierendsten Herausforderungen in der heutigen Anwendungsentwicklung ist die Umgebungsparität. Während die letzten Jahre gezeigt haben, dass Virtualisierungs- und Containerisierungstools wie Vagrant und Docker (und das ActiveState-eigene State Tool) sicherstellen können, dass die Betriebssysteme und Abhängigkeiten, die die Infrastruktur einer Anwendung antreiben, zwischen den Umgebungen konsistent sind, ist es nahezu unmöglich, externe Abhängigkeiten in einer Nicht-Produktionsumgebung zu replizieren.
In einer Welt, in der Abhängigkeiten von Drittanbietern unumkehrbar mit der Kerngeschäftslogik fast jedes Softwareprojekts verwoben sind, wird es immer schwieriger, Entwicklungs-, Staging- und Produktionsumgebungen konsistent zu halten. Während einige Produkte mit selbst gehosteten Lookalikes – wie z.B. Minio für Amazon S3 – die Verwaltung mehrerer Bereitstellungen eines einzelnen Dienstes erleichtern, tragen sie wenig dazu bei, die Herausforderung der Konfigurationsverwaltung über verschiedene Umgebungen hinweg zu erleichtern.
Wenn Produktion, Staging, Entwicklung, Bobs lokaler Rechner und die QE-Umgebung alle eine unterschiedliche Bereitstellung eines bestimmten Dienstes erfordern, wird es zunehmend unpraktisch, Konfigurationsdateien hin und her zu schieben oder sich auf komplexe Bedingungen zu verlassen, um zu bestimmen, mit welcher Bereitstellung eine bestimmte Umgebung sprechen soll. Der Bedarf an Flexibilität verdeutlicht auch die Schwierigkeit dieser Lösungen in einer groß angelegten Umgebung. Was ist, wenn zum Beispiel Bobs lokaler Rechner vorübergehend mit einem Dienst kommunizieren muss, der für die Staging-Umgebung reserviert ist?
Umgebungsvariablen in Python
Umgebungsübergreifende Konfiguration ist ein Problem, aber glücklicherweise sind die oben beschriebenen Probleme in den letzten Jahren so weit verbreitet, dass sie so gut wie gelöst sind. Dank der Unterstützung der Open-Source-Gemeinschaft und der Verbreitung von Best Practices wie der 12-Faktor-Anwendung hat sich in den letzten Jahren eine Verlagerung von der dateibasierten Anwendungsverwaltung zur umgebungsvariablenbasierten Konfigurationsverwaltung vollzogen.
Umgebungsvariablen sind – wie der Name schon sagt – Variablen, die auf der Umgebungsebene implementiert werden, um zu definieren, wie sich darunter laufende Anwendungen verhalten sollen. Einfacher ausgedrückt handelt es sich um anwendungsunabhängige Variablen, die außerhalb des Kontexts eines bestimmten Prozesses verwaltet werden. Der Hauptvorteil der Verwendung von Umgebungsvariablen besteht darin, dass Entwickler auf diese Weise festlegen können, wie eine Anwendung laufen soll, ohne eine Zeile Code zu ändern.
Wenn beispielsweise Bobs lokale Maschine mit dem CDN-Dienst sprechen muss, der für die Staging-Umgebung reserviert ist, kann er die CDN_URL
-Umgebungsvariable so ändern, dass sie das widerspiegelt, was in Staging definiert ist, ohne dass er verwalteten Code ändern muss. Noch wichtiger ist, dass Bob auf diese Weise Schein- oder interne Dienste für die Verwendung mit Unit- und Integrationstests definieren kann, ohne eine einzige Zeile zusätzlichen Codes schreiben zu müssen.
Definieren von Umgebungsvariablen
Während die Definition von Umgebungsvariablen im Allgemeinen vom Betriebssystem abhängt, haben die meisten Programmiersprachen diese Unterschiede durch die Verwendung von Entwicklungspaketen wie Pythons dotenv-Projekt abstrahiert. Anstatt zum Beispiel eine API_USER
Umgebungsvariable auf Betriebssystemebene zu definieren, kann eine lokal gitignored .env
Datei Umgebungsvariablen über Entwicklungsumgebungen hinweg verwalten. Dies ermöglicht es Entwicklern, eine lokal verwaltete Konfigurationsdatei zum Setzen von Umgebungsvariablen zu verwenden und gleichzeitig die Konfiguration über „echte“ Umgebungsvariablen in Nicht-Entwicklungsumgebungen zu ermöglichen.
Als Beispiel ist hier eine einfache .env
-Datei, die ein Entwickler in seiner lokalen Umgebung verwenden kann:
APP_ENVIRONMENT=localAPP_NAME=localhostQUEUE_DRIVER=syncAPI_USER=bob
Auf der anderen Seite kann die Produktionsumgebung ihre Umgebungsvariablen innerhalb einer Dockerdatei definieren, was beides gültige Methoden zur Verwaltung von Umgebungsvariablen sind.
Abrufen von Umgebungsvariablen
Unabhängig davon, wie Umgebungsvariablen definiert sind, können sie in Python immer mit der os.getenv()
-Methode abgerufen werden:
import os# Get environment variablesUSER = os.getenv('API_USER')
Beachten Sie, dass, falls die Umgebungsvariable undefiniert ist, der Wert standardmäßig auf None
gesetzt wird.
Einstieg mit Secrets
Obwohl Umgebungsvariablen eine hervorragende Lösung für die Verwaltung unterschiedlicher Konfigurationen in verschiedenen Umgebungen sind, sind sie kein Allheilmittel. In der heutigen Entwicklungsumgebung muss Sicherheit oberste Priorität haben, und sensible Daten müssen sicher aufbewahrt werden.
Leider sind Umgebungsvariablen allein nicht sicher. Sie eignen sich zwar hervorragend für die Speicherung von Konfigurationsdaten, aber die Art und Weise, wie wir sensiblere Daten wie Passwörter, API-Schlüssel und Verschlüsselungsschlüssel definieren, sollte mit mehr Sorgfalt behandelt werden. An dieser Stelle kommen Geheimnisse ins Spiel. Sie werden im Ruhezustand verschlüsselt und sollten nur bei Bedarf in einer einzigen Laufzeit abgerufen werden, um die Wahrscheinlichkeit einer Datenverletzung zu verringern. Auf diese Weise können Sie sicher sein, dass Ihre sensiblen Daten gut verschlüsselt sind, selbst wenn Ihr Hosting-Provider kompromittiert wird.
Erstellen &Verwalten von Geheimnissen mit dem State Tool
Wie erstellen und verwalten wir also Geheimnisse? Es gibt eine Reihe von Möglichkeiten, dieses Problem anzugehen, aber das State Tool von ActiveState ist eine hervorragende Lösung für die Sprache Python. Ähnlich wie virtualenv
oder pipenv
ist das State Tool eine Schnittstelle zur Verwaltung virtueller Umgebungen, die eine gegenseitige Verunreinigung von Python-Installationen und -Konfigurationen zwischen Projekten verhindert. Was es von anderen Tools zur Verwaltung virtueller Umgebungen unterscheidet, ist seine Integration in die ActiveState-Plattform, die eine zentrale Schnittstelle für die Verwaltung von Umgebungskonfigurationen und, ja, Geheimnissen ermöglicht.
Bevor wir die Möglichkeiten des State Tools zur Verwaltung von Geheimnissen nutzen können, müssen wir zunächst das State Tool verwenden, um eine virtuelle Umgebung in unserem Projektverzeichnis einzurichten. Wählen Sie dazu zunächst das ActiveState-Projekt aus, mit dem Sie arbeiten werden (für dieses Tutorial können Sie mein Projekt zachflower/envs-vs-secrets-demo
verwenden, sofern Sie über ein kostenloses ActiveState Platform-Konto verfügen, oder Sie können Ihr eigenes erstellen). Führen Sie dann den Befehl state activate
für Ihr Projekt aus:
$ state activate zachflower/envs-vs-secrets-demo Where would you like to checkout zachflower/envs-vs-secrets-demo? /home/zach/Projects/miscellaneous/activestate-variables/zachflower/envs-vs-secrets-demoActivating state: zachflower/envs-vs-secrets-demoThe State Tool is currently in beta, we are actively changing and adding features based on developer feedback.Downloading required artifactsDownloading 1 / 1 Installing 0 / 1 0 %You are now in an 'activated state', this will give you a virtual environment to work in that doesn't affect the rest of your system.Your 'activated state' allows you to define scripts, events and constants via the activestate.yaml file at the root of your project directory.To expand your language and/or package selection, or to define client-side encrypted secrets, please visit https://platform.activestate.com/zachflower/envs-vs-secrets-demo.To try out scripts with client-side encrypted secrets we've created a simple script for you in your activestate.yaml, try it out by running 'helloWorld'
Wie Sie sehen können, richtet der Befehl activate die virtuelle Umgebung so ein, wie sie in Ihrem ActiveState-Projekt definiert ist. Für den Fall, dass das Projekt noch nicht konfiguriert wurde, wird ein einfaches Projekt mit Standardparametern eingerichtet, um Ihnen ein Beispiel dafür zu geben, wie alles zusammenpassen sollte. Diese Konfiguration wird in einer Datei mit dem Namen activestate.yaml
im Stammverzeichnis Ihres Projekts gespeichert.
Konfigurationsdatei für Geheimnisse & Mehr
Die activestate.yaml
Datei definiert eine Entwicklungslaufzeit, unter der Ihre Anwendung laufen wird. Die Standarddatei definiert zum Beispiel ein einfaches Skript, das ein Geheimnis verwendet, sowie einige Ereignis-Listener, die Aktionen ausführen, wenn ein definiertes Ereignis eintritt:
project: https://platform.activestate.com/zachflower/envs-vs-secrets-demoscripts:# This script uses a secret. Note that you can define your own secrets at# https://platform.activestate.com/zachflower/envs-vs-secrets-demo/scripts - name: helloWorld value: echo ${secrets.user.world}events: # This is the ACTIVATE event, it will run whenever a new virtual environment is created (eg. by running `state activate`) # On Linux and macOS this will be ran as part of your shell's rc file, so you can use it to set up aliases, functions, environment variables, etc. - name: ACTIVATE constraints: os: macos,linux value: | echo "You are now in an 'activated state', this will give you a virtual environment to work in that doesn't affect the rest of your system." echo "" echo "Your 'activated state' allows you to define scripts, events and constants via the activestate.yaml file at the root of your project directory." echo "" echo "To expand your language and/or package selection, or to define client-side encrypted secrets, please visit https://platform.activestate.com/zachflower/envs-vs-secrets-demo." echo "" echo "To try out scripts with client-side encrypted secrets we've created a simple script for you in your activestate.yaml, try it out by running 'helloWorld'"
Während es hier nichts besonders Bahnbrechendes gibt, sollte die potenzielle Macht dieser Datei sofort offensichtlich sein. Das folgende Skript ist ein einfaches Beispiel für die Verwendung von Geheimnissen in der Konfigurationsdatei:
scripts:# This script uses a secret. Note that you can define your own secrets at# https://platform.activestate.com/zachflower/envs-vs-secrets-demo/scripts - name: helloWorld value: echo ${secrets.user.world}
Wenn der Befehl helloWorld
ausgeführt wird (in einem aktivierten Zustand), wird der Wert des Geheimnisses user.world
ausgegeben und, falls das Geheimnis noch nicht definiert ist, wird nach einem Wert gefragt:
$ helloWorldThe action you are taking uses a secret that has not been given a value yet.Name: worldDescription: - (This secret has no description, you can set one via the web dashboard)Scope: user (Only you can access the value) Please enter a value for secret "world": ******
Geheimnisse verwenden
Auch wenn das Beispiel relativ einfach ist, ergibt sich der wahre Wert von Geheimnissen aus den Aktivierungsereignissen. Anstatt einen geheimen Wert im Kontext eines Skripts abzurufen, können Umgebungsvariablen mit abgerufenen Geheimnissen definiert werden, ohne dass diese Geheimnisse jemals außerhalb dieser sicheren Umgebung preisgegeben werden:
project: https://platform.activestate.com/zachflower/envs-vs-secrets-demo?commitID=5fd1c161-c5a4-480c-8aba-29d8ab361b42events: - name: ACTIVATE constraints: os: macos,linux value: | export WORLD=${secrets.user.world}
Wenn nun das user.world
-Geheimnis definiert ist, wird die WORLD
-Umgebungsvariable definiert und kann wie jede andere Umgebungsvariable abgerufen werden:
$ echo $WORLDworld!
Wenn sie jedoch nicht definiert ist, wird der Benutzer aufgefordert, sie bei der Aktivierung der virtuellen ActiveState-Umgebung zu definieren:
The action you are taking uses a secret that has not been given a value yet.Name: helloDescription: - (This secret has no description, you can set one via the web dashboard)Scope: user (Only you can access the value) Please enter a value for secret "world": ******
Sehr cool, oder?
Weiter geht’s
Das Konfigurationsmanagement in der Anwendungsentwicklung ist größtenteils ein gelöstes Problem, aber das Management von Geheimnissen ist es eben noch nicht. Die Zahl der Projekte, bei denen sensible Daten in ein Versionskontroll-Repository eingecheckt wurden, ist schwindelerregend, und selbst hoch angesehene Unternehmen haben dies getan, aber durch den Einsatz einer angemessenen Sicherheitshygiene und von Produkten wie dem State Tool von ActiveState wird es von Tag zu Tag einfacher, sensible Konfigurationsdaten sicher zu halten und zu schützen.
- Testen Sie es selbst, indem Sie ein kostenloses ActiveState Platform Konto erstellen und das State Tool herunterladen, um die Verwaltung von Geheimnissen zu vereinfachen.
- Sie können sich auch unser Webinar über die Verwaltung gemeinsam genutzter Geheimnisse mit dem State Tool ansehen
Verwandte Blogs:
Das Geheimnis der Verwaltung gemeinsam genutzter Geheimnisse
Entwickler können Geheimnisse schnell und einfach gemeinsam nutzen, ohne die Sicherheit zu opfern