it-swarm.com.de

Docker und Sicherung von Passwörtern

Ich habe in letzter Zeit mit Docker experimentiert, um ein paar Dienste zu entwickeln, mit denen man herumspielen kann. Eine Sache, die mich ständig nervt, ist das Einfügen von Passwörtern in ein Dockerfile. Ich bin ein Entwickler, und das Speichern von Passwörtern in der Quelle fühlt sich an wie ein Schlag ins Gesicht. Sollte das überhaupt ein Anliegen sein? Gibt es gute Konventionen für den Umgang mit Kennwörtern in Dockerfiles?

107
anthonator

Auf jeden Fall ist es ein Anliegen. Docker-Dateien werden normalerweise in Repositorys eingecheckt und mit anderen Personen geteilt. Eine Alternative besteht darin, alle Berechtigungsnachweise (Benutzernamen, Kennwörter, Token, sensible) als Umgebungsvariablen zur Laufzeit anzugeben. Dies ist über das Argument -e (für einzelne Variablen in der CLI) oder das Argument --env-file (für mehrere Variablen in einer Datei) an docker run möglich. Lesen Sie this , um die Umgebung mit Docker-Compose zu verwenden.

Die Verwendung von --env-file ist definitiv eine sicherere Option, da dies verhindert, dass die Geheimnisse in ps oder in Protokollen angezeigt werden, wenn set -x verwendet wird.

Env vars sind jedoch auch nicht besonders sicher. Sie sind über docker inspect sichtbar und daher für jeden Benutzer verfügbar, der docker-Befehle ausführen kann. (Natürlich hat jeder Benutzer, der Zugriff auf docker auf dem Host hat, auch mit root .)

Mein bevorzugtes Muster ist die Verwendung eines Wrapper-Skripts als ENTRYPOINT oder CMD. Das Wrapper-Skript kann zunächst zur Laufzeit Geheimnisse von außerhalb in den Container importieren, dann die Anwendung ausführen und die Geheimnisse bereitstellen. Die genaue Vorgehensweise hängt von Ihrer Laufzeitumgebung ab. In AWS können Sie eine Kombination aus IAM-Rollen, Key Management Service und S3 verwenden, um verschlüsselte Geheimnisse in einem S3-Bucket zu speichern. Etwas wie HashiCorp Vault oder credstash ist eine andere Option.

AFAIK gibt es kein optimales Muster für die Verwendung sensibler Daten als Teil des Erstellungsprozesses. Tatsächlich habe ich zu diesem Thema eine SO - Frage . Sie können docker-squash verwenden, um Ebenen aus einem Bild zu entfernen. Dafür gibt es in Docker keine native Funktionalität.

Shykes Kommentare zu config in Containern könnten nützlich sein. 

66
Ben Whaley

Unser Team vermeidet das Einfügen von Anmeldeinformationen in Repositorys. Dies bedeutet, dass sie in Dockerfile nicht zulässig sind. Bei Anwendungen ist es am besten, Creds aus Umgebungsvariablen zu verwenden.

Wir lösen dies mit docker-compose.

In docker-compose.yml können Sie eine Datei angeben, die die Umgebungsvariablen für den Container enthält:

 env_file:
- .env

Stellen Sie sicher, dass Sie .env zu .gitignore hinzufügen, und legen Sie dann die Berechtigungsnachweise in der .env-Datei fest:

SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd

Speichern Sie die .env-Datei lokal oder an einem sicheren Ort, wo der Rest des Teams sie abholen kann.

Siehe: https://docs.docker.com/compose/environment-variables/#/the-env-file

56
theUtherSide

Docker (Version 1.13 oder 17.06 und höher) unterstützt jetzt die Verwaltung geheimer Informationen. Hier ist eine Übersicht und detailliertere Dokumentation

Eine ähnliche Funktion gibt es in kubernetes und DCOS

27
Heather QC

Sie sollten niemals Anmeldeinformationen zu einem Container hinzufügen, es sei denn, Sie können die Creds an jeden senden, der das Bild herunterladen kann. Insbesondere ist das Ausführen von und ADD creds und später RUN rm creds nicht sicher, da die creds-Datei im endgültigen Bild in einer Zwischen-Dateisystemebene verbleibt. Jeder, der Zugriff auf das Bild hat, kann es leicht extrahieren.

Die typische Lösung, die ich gesehen habe, wenn Sie Creds zum Überprüfen von Abhängigkeiten benötigen und beispielsweise einen Container verwenden, um einen anderen Container zu erstellen. Das heißt, normalerweise haben Sie eine Build-Umgebung in Ihrem Basiscontainer, und Sie müssen diese aufrufen, um Ihren App-Container zu erstellen. Die einfache Lösung ist also, Ihre App-Quelle und dann RUN die Build-Befehle hinzuzufügen. Dies ist unsicher, wenn Sie Creds in dieser RUN benötigen. Stattdessen legen Sie Ihre Quelle in ein lokales Verzeichnis. Führen Sie (wie in docker run) den Container aus, um den Erstellungsschritt auszuführen, wobei das lokale Quellverzeichnis als Volume angehängt ist und die Creds entweder in ein anderes Volume eingefügt oder eingebunden sind. Sobald der Erstellungsschritt abgeschlossen ist, erstellen Sie Ihren endgültigen Container, indem Sie einfach das lokale Quellverzeichnis ADD eingeben, das jetzt die erstellten Artefakte enthält.

Ich hoffe, Docker fügt einige Funktionen hinzu, um all dies zu vereinfachen!

Update: Es sieht so aus, als würde die Methode in der Zukunft verschachtelte Builds sein. Kurz gesagt, die Docker-Datei würde einen ersten Container beschreiben, der zum Erstellen der Laufzeitumgebung verwendet wird, und dann einen zweiten verschachtelten Container-Build, der alle Teile zu dem endgültigen Container zusammenfügen kann. Auf diese Weise befindet sich das Build-Time-Material nicht im zweiten Container. Dies ist eine Java-App, bei der Sie das JDK zum Erstellen der App benötigen, aber nur die JRE, um sie auszuführen. Es wird eine Reihe von Vorschlägen diskutiert, die am besten von https://github.com/docker/docker/issues/7115 beginnen und einigen der Links für alternative Vorschläge folgen.

8
TvE

Mit Docker v1.9 können Sie die ARG-Anweisung verwenden, um Argumente abzurufen, die von der Befehlszeile an das Image von build action übergeben werden. Verwenden Sie einfach das Flag --build-arg. Sie können also vermeiden, explizite Kennwörter (oder andere vernünftige Informationen) in der Dockerfile zu speichern und sie im laufenden Betrieb weiterzugeben.

source: https://docs.docker.com/engine/reference/commandline/build/http://docs.docker.com/engine/reference/builder/#arg

Beispiel:

Dockerfile

FROM busybox
ARG user
RUN echo "user is $user"

build image Befehl

docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .

während des Builds drucken

$ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile .

Sending build context to Docker daemon 2.048 kB
Step 1 : FROM busybox
 ---> c51f86c28340
Step 2 : ARG user
 ---> Running in 43a4aa0e421d
 ---> f0359070fc8f
Removing intermediate container 43a4aa0e421d
Step 3 : RUN echo "user is $user"
 ---> Running in 4360fb10d46a
**user is capuccino**
 ---> 1408147c1cb9
Removing intermediate container 4360fb10d46a
Successfully built 1408147c1cb9

Ich hoffe es hilft! Tschüss.

5
NickGnd

Als Alternative zur Verwendung von Umgebungsvariablen, die bei vielen übermäßig unordentlich werden können, können Sie Volumes verwenden, um ein Verzeichnis auf dem Host im Container zugänglich zu machen.

Wenn Sie alle Ihre Anmeldeinformationen als Dateien in diesem Ordner ablegen, kann der Container die Dateien lesen und nach Belieben verwenden.

Zum Beispiel:

$ echo "secret" > /root/configs/password.txt
$ docker run -v /root/configs:/cfg ...

In the Docker container:

# echo Password is `cat /cfg/password.txt`
Password is secret

Viele Programme können ihre Anmeldeinformationen aus einer separaten Datei lesen. Auf diese Weise können Sie das Programm einfach auf eine der Dateien verweisen.

3
Malvineous

Mein Ansatz scheint zu funktionieren, ist aber wahrscheinlich naiv. Sag mir warum es falsch ist.

ARGs, die während des Docker-Builds festgelegt wurden, werden vom Unterbefehl "history" angezeigt. Wenn Sie einen Container ausführen, sind die im Ausführungsbefehl angegebenen Umgebungsvariablen für den Container verfügbar, jedoch nicht Teil des Images.

Nehmen Sie in der Dockerfile also ein Setup vor, das keine geheimen Daten beinhaltet. Legen Sie eine CMD von /root/finish.sh fest. Verwenden Sie im Ausführungsbefehl Umgebungsvariablen, um geheime Daten in den Container zu senden. finish.sh verwendet die Variablen im Wesentlichen, um Build-Aufgaben abzuschließen.

Um die Verwaltung der geheimen Daten zu vereinfachen, legen Sie sie in eine Datei, die von Docker geladen wird, der mit dem Schalter --env-file ausgeführt wird. Halten Sie die Datei natürlich geheim. .gitignore und so.

Für mich führt finish.sh ein Python-Programm aus. Es überprüft, ob es noch nicht ausgeführt wurde, und beendet dann das Setup (z. B. kopiert den Datenbanknamen in Djangos settings.py). 

1

Es gibt einen neuen Docker-Befehl [1] zur Verwaltung von "Geheimnissen", der jedoch nur für Schwarmcluster funktioniert.

docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
Microsoft/iis:nanoserver 

[1] https://docs.docker.com/engine/swarm/secrets/

0
José Ibañez

Ich bin völlig einverstanden, aber es gibt keine einfache Lösung. Es gibt immer noch einen einzigen Fehlerpunkt. Entweder die Docker-Datei, etcd usw. Apcera hat einen Plan, der wie Sidekick aussieht - duale Authentifizierung. Mit anderen Worten, zwei Container können nicht sprechen, es sei denn, es gibt eine Apcera-Konfigurationsregel. In ihrer Demo war die uid/pwd im Klartext und konnte erst wieder verwendet werden, wenn der Administrator die Verknüpfung konfiguriert hatte. Damit dies funktioniert, bedeutete dies wahrscheinlich das Patchen von Docker oder zumindest des Netzwerk-Plugins (falls es so etwas gibt). 

0
Richard

Die App-Methodik 12-Factor gibt an, dass jede Konfiguration in Umgebungsvariablen gespeichert werden soll. 

Docker compose könnte Variablensubstitution in der Konfiguration durchführen, um Passwörter von Host an Docker zu übergeben. 

0
Bunyk

Nur Laufzeitlösung

docker-compose bietet auch eine Lösung ohne Schwarmmodus (seit v1.11: Secrets mit Bind-Mount-Optionen ). 

Die Geheimnisse werden als Dateien unterhalb von /run/secrets/ von Docker-Compose eingehängt. Dies löst das Problem zur Laufzeit (Ausführen des Containers), jedoch nicht zur Build-Time (Erstellung des Images), da /run/secrets/ nicht zur Build-Zeit gemountet wird. Darüber hinaus hängt dieses Verhalten davon ab, dass der Container mit Docker-Compose ausgeführt wird.


Beispiel:

Dockerfile

FROM Alpine
RUN cat /run/secrets/password
CMD sleep inifinity

docker-compose.yml

version: '3.1'
services:
  app:
    build: .
    secrets:
      - password

secrets:
  password:
    file: password.txt

Um zu bauen, führen Sie Folgendes aus:

docker-compose up -d

Lesen Sie weiter:

0
Murmel