Wie lassen sich AWS-Anmeldeinformationen am besten an den Docker-Container übergeben?


102

Ich verwende Docker-Container auf Amazon EC2. Derzeit habe ich AWS Credentials zu Dockerfile hinzugefügt. Könnten Sie mir bitte den besten Weg dazu mitteilen?


2
Wie wäre es, wenn ich einen Docker-Container auf meinem Laptop laufen lasse, der auch in ECS magisch funktionieren soll, wenn ich ihn dorthin schiebe? Ich schätze, ich benutze die - Volume-Flagge ... jemand muss bereits geantwortet haben ...
Randy L

Antworten:


105

Der beste Weg ist, die IAM-Rolle zu verwenden und überhaupt nicht mit Anmeldeinformationen umzugehen. (sehen http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )

Anmeldeinformationen konnten von abgerufen werden http://169.254.169.254..... Da dies eine private IP-Adresse ist, kann nur von EC2-Instanzen aus darauf zugegriffen werden.

Alle modernen AWS-Client-Bibliotheken "wissen", wie Anmeldeinformationen von dort abgerufen, aktualisiert und verwendet werden. In den meisten Fällen müssen Sie also nicht einmal darüber Bescheid wissen. Führen Sie einfach ec2 mit der richtigen IAM-Rolle aus und los geht's.

Optional können Sie sie zur Laufzeit als Umgebungsvariablen übergeben (z docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage )

Sie können auf diese Umgebungsvariablen zugreifen, indem Sie printenv am Terminal ausführen.


35
Gibt es eine gute Möglichkeit, dies während der lokalen Entwicklung / Tests zu tun, ohne die Sicherheit in der Produktion zu beeinträchtigen? Ich würde gerne sicherstellen, dass ein Image funktioniert, ohne es vollständig bereitzustellen.
Honktronic

3
Eine Alternative, die ich mit Umgebungsvariablen gepostet habe, funktioniert in der dev / local-Umgebung einwandfrei.
Vor dem

5
Ich frage mich, ob dies ein Tippfehler ist, aber ich muss AWS_SECRET_ACCESS_KEYnicht eingeben AWS_SECRET_KEY, trotzdem war Ihre Antwort sehr hilfreich. Danke.
Akavall

14
Einfach ausgedrückt (für diejenigen, die diese Antwort genauso erhalten wie ich); Ein Docker-Container, der auf EC2 ausgeführt wird, erbt dieselbe Rolle wie die Hostinstanz. (Ich brauchte eine "ELI5" wie diese, als AWS CLI-Befehle in meinen Containern auf mysteriöse Weise funktionierten, obwohl ihnen keine Anmeldeinformationen übergeben wurden!)
Adam Westbrook

8
Einfache Möglichkeit, die Schlüsselwerte aus Ihrem lokalen Profil abzurufen , um sie für Entwicklungszwecke einer Umgebungsvariablen zuzuweisen (wie in cameroneckelberry.co/words/… vorgeschlagen ): "aws --profile default configure get aws_access_key_id"
Altair7852

88

In Docker hat sich viel geändert, seit diese Frage gestellt wurde. Hier ist ein Versuch, eine aktualisierte Antwort zu finden.

Erstens, insbesondere mit AWS-Anmeldeinformationen für Container, die bereits in der Cloud ausgeführt werden, ist die Verwendung von IAM-Rollen, wie Vor vorschlägt, eine wirklich gute Option. Wenn Sie das können, fügen Sie seiner Antwort ein weiteres plus eins hinzu und überspringen Sie den Rest.


Sobald Sie anfangen, Dinge außerhalb der Cloud auszuführen oder eine andere Art von Geheimnis haben, gibt es zwei wichtige Stellen, die ich gegen das Speichern von Geheimnissen empfehle :

  1. Umgebungsvariablen: Wenn diese in einem Container definiert sind, hat jeder Prozess im Container Zugriff auf sie, sie sind über / proc sichtbar, Apps können ihre Umgebung an stdout ausgeben, wo sie in den Protokollen gespeichert wird, und vor allem in Klartext, wenn Sie den Behälter inspizieren.

  2. Im Bild selbst: Bilder werden häufig in Register verschoben, in denen viele Benutzer Zugriff auf das Bild haben, manchmal ohne Anmeldeinformationen, die zum Abrufen des Bildes erforderlich sind. Selbst wenn Sie das Geheimnis aus einer Ebene löschen, kann das Image mit gängigen Linux-Dienstprogrammen wie zerlegt werden, tarund das Geheimnis kann in dem Schritt gefunden werden, in dem es dem Image zum ersten Mal hinzugefügt wurde.


Welche anderen Optionen gibt es für Geheimnisse in Docker-Containern?

Option A: Wenn Sie dieses Geheimnis nur während der Erstellung Ihres Images benötigen, das Geheimnis vor Beginn der Erstellung nicht verwenden können und noch keinen Zugriff auf BuildKit haben, ist eine mehrstufige Erstellung die beste der schlechten Optionen. Sie würden das Geheimnis zu den Anfangsphasen des Builds hinzufügen, es dort verwenden und dann die Ausgabe dieser Stufe ohne das Geheimnis in Ihre Release-Phase kopieren und diese Release-Phase nur auf die Registrierungsserver übertragen. Dieses Geheimnis befindet sich immer noch im Image-Cache auf dem Build-Server, daher verwende ich dies normalerweise nur als letzten Ausweg.

Option B: Wenn Sie während der Build-Zeit BuildKit verwenden können, das am 18.09 veröffentlicht wurde, gibt es derzeit experimentelle Funktionen , mit denen Sie Geheimnisse als Volume-Mount für eine einzelne RUN-Zeile einfügen können. Dieser Mount wird nicht in die Image-Ebenen geschrieben, sodass Sie während des Builds auf das Geheimnis zugreifen können, ohne befürchten zu müssen, dass es auf einen öffentlichen Registrierungsserver übertragen wird. Das resultierende Dockerfile sieht folgendermaßen aus:

# syntax = docker/dockerfile:experimental
FROM python:3
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...

Und Sie erstellen es mit einem Befehl in 18.09 oder neuer wie:

DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .

Option C:Zur Laufzeit auf einem einzelnen Knoten ohne Swarm-Modus oder andere Orchestrierung können Sie die Anmeldeinformationen als schreibgeschütztes Volume bereitstellen. Für den Zugriff auf diese Anmeldeinformationen ist derselbe Zugriff erforderlich, den Sie außerhalb von Docker auf dieselbe Anmeldeinformationsdatei haben würden. Daher ist er nicht besser oder schlechter als das Szenario ohne Docker. Am wichtigsten ist, dass der Inhalt dieser Datei nicht sichtbar sein sollte, wenn Sie den Container untersuchen, die Protokolle anzeigen oder das Image an einen Registrierungsserver senden, da das Volume in jedem Szenario außerhalb davon liegt. Dies erfordert, dass Sie Ihre Anmeldeinformationen getrennt von der Bereitstellung des Containers auf den Docker-Host kopieren. (Beachten Sie, dass jeder, der Container auf diesem Host ausführen kann, Ihre Anmeldeinformationen anzeigen kann, da der Zugriff auf die Docker-API root auf dem Host ist und root die Dateien aller Benutzer anzeigen kann. Wenn Sie Benutzern mit root auf dem Host nicht vertrauen ,

Für a docker runsieht das so aus:

docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image

Oder für eine Erstellungsdatei hätten Sie:

version: '3'
services:
  app:
    image: your_image
    volumes:
    - $HOME/.aws/credentials:/home/app/.aws/credentials:ro

Option D:Mit Orchestrierungswerkzeugen wie Swarm Mode und Kubernetes haben wir jetzt Unterstützung für Geheimnisse, die besser ist als ein Volume. Im Schwarmmodus wird die Datei im Manager-Dateisystem verschlüsselt (obwohl der Entschlüsselungsschlüssel häufig auch vorhanden ist, sodass der Manager neu gestartet werden kann, ohne dass ein Administrator einen Entschlüsselungsschlüssel eingibt). Noch wichtiger ist, dass das Geheimnis nur an die Mitarbeiter gesendet wird, die das Geheimnis benötigen (einen Container mit diesem Geheimnis ausführen), nur im Speicher des Arbeiters gespeichert wird, niemals auf der Festplatte, und als Datei mit einem tmpfs in den Container eingefügt wird montieren. Benutzer auf dem Host außerhalb von Swarm können dieses Geheimnis nicht direkt in ihren eigenen Container einbinden. Mit offenem Zugriff auf die Docker-API können sie das Geheimnis jedoch aus einem laufenden Container auf dem Knoten extrahieren. Beschränken Sie also erneut, wer diesen Zugriff auf das hat API. Nach dem Verfassen sieht diese geheime Injektion so aus:

version: '3.7'

secrets:
  aws_creds:
    external: true

services:
  app:
    image: your_image
    secrets:
    - source: aws_creds
      target: /home/user/.aws/credentials
      uid: '1000'
      gid: '1000'
      mode: 0700

Sie aktivieren den Schwarmmodus mit docker swarm initfür einen einzelnen Knoten und folgen dann den Anweisungen zum Hinzufügen weiterer Knoten. Sie können das Geheimnis extern mit erstellen docker secret create aws_creds $HOME/.aws/credentials. Und Sie stellen die Erstellungsdatei mit bereit docker stack deploy -c docker-compose.yml stack_name.

Ich versioniere meine Geheimnisse oft mit einem Skript von: https://github.com/sudo-bmitch/docker-config-update

Option E: Es gibt andere Tools zum Verwalten von Geheimnissen. Mein Favorit ist Vault, da damit zeitlich begrenzte Geheimnisse erstellt werden können, die automatisch ablaufen. Jede Anwendung erhält dann einen eigenen Satz von Token, um Geheimnisse anzufordern, und diese Token geben ihnen die Möglichkeit, diese zeitlich begrenzten Geheimnisse anzufordern, solange sie den Tresorserver erreichen können. Dies verringert das Risiko, wenn jemals ein Geheimnis aus Ihrem Netzwerk entfernt wird, da es entweder nicht funktioniert oder schnell abläuft. Die für AWS for Vault spezifischen Funktionen sind unter https://www.vaultproject.io/docs/secrets/aws/index.html dokumentiert


20

Ein anderer Ansatz besteht darin, die Schlüssel vom Host-Computer an den Docker-Container zu übergeben. Sie können der docker-composeDatei folgende Zeilen hinzufügen .

services:
  web:
    build: .
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}

2
Die richtige Umgebungsvariable für die Region ist AWS_REGION. Siehe stackoverflow.com/questions/44151982/…
John Camerin

3
Bitte überprüfen Sie das offizielle Dokument, in dem AWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/…
prafi

6
Bei der Verwendung von AWS_DEFAULT_REGION wurde die Ausnahme angezeigt, dass eine Standardregion nicht gefunden wurde. Meine Suche führte zu docs.aws.amazon.com/sdk-for-java/v1/developer-guide/…, das die Umgebungsvariable AWS_REGION angibt, und das hat bei mir funktioniert.
John Camerin

Wenn Sie temporäre Anmeldeinformationen verwenden, benötigen Sie möglicherweise auchAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Davos

11

Ein weiterer Ansatz besteht darin, ein temporäres schreibgeschütztes Volume in docker-compose.yaml zu erstellen. AWS CLI und SDK (wie Boto3 oder AWS SDK für Java usw.) suchen nach defaultProfilen in ~/.aws/credentialsDateien.

Wenn Sie andere Profile verwenden möchten, müssen Sie nur die Variable AWS_PROFILE exportieren, bevor Sie den docker-composeBefehl ausführen

export AWS_PROFILE=some_other_profile_name

version: '3'

services:
  service-name:
    image: docker-image-name:latest
    environment:
      - AWS_PROFILE=${AWS_PROFILE}
    volumes:
      - ~/.aws/:/root/.aws:ro

In diesem Beispiel habe ich Root-Benutzer auf Docker verwendet. Wenn Sie einen anderen Benutzer verwenden, wechseln Sie einfach in das Basisverzeichnis /root/.awsdes Benutzers

:ro - steht für schreibgeschütztes Docker-Volume

Dies ist sehr hilfreich, wenn Sie mehrere Profile in der ~/.aws/credentialsDatei haben und auch MFA verwenden. Auch hilfreich, wenn Sie Docker-Container lokal testen möchten, bevor Sie ihn auf ECS bereitstellen, auf dem Sie IAM-Rollen haben, lokal jedoch nicht.


Unter Windows befindet sich der Katalog von .aws "%UserProfile%\.aws". Also - ~/.aws/:/root/.aws:ro- %UserProfile%\.aws:/root/.aws:ro
gehe

1
Dies funktioniert nur mit einzelnen Build-Prozessen und nicht mit mehrstufigen.
Wlarcheveque

@wlarcheveque Pflege zu erarbeiten?
ErikE

Seien Sie SEHR vorsichtig mit der - host:containerSyntax, wenn die Datei / der Ordner nicht auf dem Host vorhanden ist, der erstellt wird (als Root), und die awscli wird Ihnen nicht dafür danken, dass Sie ihr eine Null-Byte-Datei zugeführt haben. Sie sollten die "lange Form" verwenden, die angibt, dass der Typ bind, der Hostpfad und der Containerpfad in separaten Zeilen sind. Dies schlägt fehl, wenn die Datei nicht vorhanden ist. Dies ist das, was Sie in Ihrer docker-compose.dev möchten. yml aber nicht in Ihrer docker-compose.yml (prod / AWS-Bereitstellung).
dragon788

0

Sie könnten ~/aws_env_credsenthalten erstellen

touch ~/aws_env_creds
chmod 777 ~/aws_env_creds
vi ~/aws_env_creds

Fügen Sie den folgenden Wert hinzu (Ersetzen Sie Ihren Schlüssel)

AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C

"esc" zum Speichern der Datei.

Führen Sie den Container aus und testen Sie ihn

 my_service:
      build: .
      image: my_image
      env_file:
        - ~/aws_env_creds
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.