Jaki jest najlepszy sposób przekazywania danych uwierzytelniających AWS do kontenera Docker?

107

Używam docker-container na Amazon EC2. Obecnie dodałem poświadczenia AWS do Dockerfile. Czy możesz mi powiedzieć, jak najlepiej to zrobić?

suraj chopade
źródło
2
A co z kontem Dockera na moim laptopie, który ma magicznie działać w ECS, kiedy go tam wrzucę? Zgaduję, że używam flagi --volume ... ktoś musiał już odebrać ...
Randy L

Odpowiedzi:

112

Najlepszym sposobem jest użycie roli IAM i nie zajmowanie się w ogóle poświadczeniami. (patrz http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )

Poświadczenia można pobrać z http://169.254.169.254..... Ponieważ jest to prywatny adres IP, może być dostępny tylko z instancji EC2.

Wszystkie nowoczesne biblioteki klienckie AWS „wiedzą”, jak z tego miejsca pobierać, odświeżać i używać poświadczeń. W większości przypadków nie musisz nawet o tym wiedzieć. Po prostu uruchom ec2 z właściwą rolą IAM i gotowe.

Opcjonalnie możesz przekazać je w czasie wykonywania jako zmienne środowiskowe (tj. docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage)

Możesz uzyskać dostęp do tych zmiennych środowiskowych, uruchamiając printenv na terminalu.

Vor
źródło
38
Czy istnieje dobry sposób na zrobienie tego podczas lokalnego programowania / testowania, który nie zagraża bezpieczeństwu w środowisku produkcyjnym? Chciałbym się upewnić, że obraz działa bez pełnego wdrażania.
honktronic
3
alternatywa, którą zamieściłem ze zmiennymi środowiskowymi, działa dobrze w środowisku deweloperskim / lokalnym.
Vor
5
Zastanawiam się, czy to pomyłka, ale muszę wpisać AWS_SECRET_ACCESS_KEY, nie AWS_SECRET_KEY, w każdym razie Twoja odpowiedź była bardzo pomocna. Dziękuję Ci.
Akavall,
14
Mówiąc prościej (dla tych, którzy dostają tę odpowiedź w ten sam sposób, jak ja); Kontener Dockera działający na platformie EC2 odziedziczy tę samą rolę, co instancja hosta. (Potrzebowałem takiego „ELI5”, gdy komendy AWS CLI w moich kontenerach w tajemniczy sposób działały pomimo braku danych uwierzytelniających!)
Adam Westbrook
8
Łatwy sposób na uzyskanie wartości kluczy z profilu lokalnego w celu przypisania ich do zmiennej środowiskowej w celach programistycznych (zgodnie z sugestią w cameroneckelberry.co/words/… ): „aws --profile default configure get aws_access_key_id”
Altair7852
100

Wiele się zmieniło w Dockerze od czasu zadania tego pytania, więc oto próba zaktualizowanej odpowiedzi.

Po pierwsze, w szczególności z poświadczeniami AWS na kontenerach już uruchomionych w chmurze, użycie ról IAM, jak sugeruje Vor, jest naprawdę dobrą opcją. Jeśli możesz to zrobić, dodaj jeszcze jeden plus jeden do jego odpowiedzi i pomiń resztę.


Gdy zaczniesz uruchamiać rzeczy poza chmurą lub masz inny typ sekretu, są dwa kluczowe miejsca, w których odradzam przechowywanie sekretów:

  1. Zmienne środowiskowe: kiedy są zdefiniowane w kontenerze, każdy proces wewnątrz kontenera ma do nich dostęp, są widoczne przez / proc, aplikacje mogą zrzucić swoje środowisko na standardowe wyjście, gdzie jest przechowywane w dziennikach, a co najważniejsze, pojawiają się w czysty tekst podczas sprawdzania kontenera.

  2. W samym obrazie: obrazy często są wypychane do rejestrów, w których wielu użytkowników ma dostęp do ściągania, czasami bez żadnych poświadczeń wymaganych do pobrania obrazu. Nawet jeśli usuniesz sekret z jednej warstwy, obraz można zdemontować za pomocą typowych narzędzi Linuksa, takich jaktar a sekret można znaleźć w kroku, w którym został po raz pierwszy dodany do obrazu.


Więc jakie są inne opcje dla wpisów tajnych w kontenerach Docker?

Opcja A: Jeśli potrzebujesz tego sekretu tylko podczas budowania obrazu, nie możesz użyć sekretu przed rozpoczęciem kompilacji i nie masz jeszcze dostępu do BuildKit, wtedy kompilacja wieloetapowa jest najlepszą ze złych opcji. Należy dodać sekret do początkowych etapów kompilacji, użyć go tam, a następnie skopiować dane wyjściowe tego etapu bez klucza tajnego do etapu wydania i tylko wypchnąć ten etap wydania na serwery rejestru. Ten sekret nadal znajduje się w pamięci podręcznej obrazu na serwerze kompilacji, więc używam go tylko w ostateczności.

Opcja B: Również w czasie kompilacji, jeśli możesz użyć BuildKita, który został wydany w 18.09, istnieją obecnie eksperymentalne funkcje umożliwiające wstrzykiwanie sekretów jako montowanie woluminu dla pojedynczej linii RUN. To mocowanie nie jest zapisywane na warstwach obrazu, więc możesz uzyskać dostęp do sekretu podczas kompilacji bez obawy, że zostanie on przesłany na publiczny serwer rejestru. Wynikowy plik Dockerfile wygląda następująco:

# 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://... ...

Budujesz go za pomocą polecenia w wersji 18.09 lub nowszej, na przykład:

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

Opcja C:W czasie wykonywania na pojedynczym węźle, bez trybu Swarm lub innej aranżacji, możesz zamontować poświadczenia jako wolumin tylko do odczytu. Dostęp do tego poświadczenia wymaga takiego samego dostępu, jaki miałbyś poza platformą Docker do tego samego pliku poświadczeń, więc nie jest lepszy ani gorszy niż scenariusz bez platformy Docker. Co najważniejsze, zawartość tego pliku nie powinna być widoczna podczas sprawdzania kontenera, przeglądania dzienników lub wysyłania obrazu na serwer rejestru, ponieważ w każdym scenariuszu wolumin jest poza tym. Wymaga to skopiowania poświadczeń na hoście platformy Docker, niezależnie od wdrożenia kontenera. (Uwaga: każdy, kto może uruchamiać kontenery na tym hoście, może zobaczyć twoje poświadczenia, ponieważ dostęp do interfejsu docker API ma root na hoście, a root może przeglądać pliki dowolnego użytkownika. Jeśli nie ufasz użytkownikom z rootem na hoście ,

Dla a docker runwygląda to tak:

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

Lub w przypadku pliku redagowania miałbyś:

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

Opcja D:Dzięki narzędziom do orkiestracji, takim jak Swarm Mode i Kubernetes, mamy teraz obsługę sekretów, która jest lepsza niż wolumen. W trybie Swarm plik jest szyfrowany w systemie plików menedżera (chociaż klucz odszyfrowywania również jest tam często, co pozwala na ponowne uruchomienie menedżera bez wprowadzania klucza deszyfrowania przez administratora). Co ważniejsze, sekret jest wysyłany tylko do pracowników, którzy go potrzebują (uruchamianie kontenera z tym sekretem), jest przechowywany tylko w pamięci pracownika, nigdy na dysku i jest wstrzykiwany jako plik do kontenera z tmpfs uchwyt. Użytkownicy na hoście spoza roju nie mogą zamontować tego sekretu bezpośrednio do własnego kontenera, jednak mając otwarty dostęp do interfejsu API platformy docker, mogliby wyodrębnić sekret z kontenera działającego w węźle, więc ponownie ogranicz dostęp do API. Z redagowania ten tajny zastrzyk wygląda tak:

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

Włączasz tryb roju docker swarm initza pomocą dla pojedynczego węzła, a następnie postępuj zgodnie ze wskazówkami dotyczącymi dodawania kolejnych węzłów. Możesz utworzyć sekret na zewnątrz za pomocą docker secret create aws_creds $HOME/.aws/credentials. I wdrażasz plik redagowania z docker stack deploy -c docker-compose.yml stack_name.

Często tworzę moje sekrety za pomocą skryptu z: https://github.com/sudo-bmitch/docker-config-update

Opcja E: Istnieją inne narzędzia do zarządzania tajemnicami, a moim ulubionym jest Vault, ponieważ daje możliwość tworzenia ograniczonych czasowo sekretów, które automatycznie wygasają. Każda aplikacja otrzymuje wtedy swój własny zestaw tokenów do żądania sekretów, a tokeny te dają im możliwość żądania tych ograniczonych czasowo sekretów tak długo, jak mogą dotrzeć do serwera repozytorium. Zmniejsza to ryzyko, jeśli sekret zostanie kiedykolwiek usunięty z sieci, ponieważ albo nie zadziała, albo szybko wygaśnie. Funkcjonalność specyficzna dla AWS for Vault jest udokumentowana pod adresem https://www.vaultproject.io/docs/secrets/aws/index.html

BMitch
źródło
22

Innym podejściem jest przekazanie kluczy z komputera hosta do kontenera Dockera. Możesz dodać następujące wiersze do docker-composepliku.

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}
prafi
źródło
3
Prawidłowa zmienna środowiskowa regionu to AWS_REGION. Zobacz stackoverflow.com/questions/44151982/…
John Camerin
3
Sprawdź oficjalny dokument, w którym wspomniano o AWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/ ...
prafi
7
Kiedy użyłem AWS_DEFAULT_REGION, wystąpił wyjątek, że nie można znaleźć domyślnego regionu. Moje wyszukiwanie doprowadziło do docs.aws.amazon.com/sdk-for-java/v1/developer-guide/…, który określa zmienną środowiskową AWS_REGION, i to zadziałało.
John Camerin
Jeśli używasz tymczasowych poświadczeń, możesz również potrzebowaćAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Davos
16

Jeszcze innym podejściem jest utworzenie tymczasowego woluminu tylko do odczytu w docker-compose.yaml. AWS CLI i SDK (jak boto3 lub AWS SDK dla Java itp.) Szukają defaultprofilu w ~/.aws/credentialspliku.

Jeśli chcesz używać innych profili, wystarczy wyeksportować zmienną AWS_PROFILE przed uruchomieniem docker-composepolecenia

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

W tym przykładzie użyłem użytkownika root w dockerze. Jeśli używasz innego użytkownika, po prostu przejdź /root/.awsdo katalogu domowego użytkownika

:ro - oznacza tylko do odczytu objętość dockera

Jest to bardzo przydatne, gdy masz wiele profili w ~/.aws/credentialspliku i używasz również usługi MFA. Jest to również przydatne, gdy chcesz przetestować lokalnie docker-container przed wdrożeniem go w ECS, na którym masz role uprawnień, ale lokalnie tego nie robisz.

Artur Siepietowski
źródło
W systemie Windows znajduje się katalog .aws "%UserProfile%\.aws". Zakładam więc, że trzeba się przesiąść: - ~/.aws/:/root/.aws:rona- %UserProfile%\.aws:/root/.aws:ro
Artur Siepietowski
1
Będzie to działać tylko w przypadku pojedynczych procesów kompilacji, a nie wieloetapowych.
wlarcheveque
@wlarcheveque Chcesz rozwinąć?
ErikE
Bądź BARDZO ostrożny używając - host:containerskładni, jeśli plik / folder nie istnieje na hoście, który został utworzony (jako root), a awscli nie podziękuje ci za podanie mu zerobajtowego pliku. Powinieneś użyć "długiej formy", która określa typ to bind, ścieżkę hosta i ścieżkę kontenera w oddzielnych wierszach, to się nie powiedzie, jeśli plik nie istnieje, co chcesz w swoim docker-compose.dev. yml, ale nie w pliku docker-compose.yml (wdrożenie prod / AWS).
dragon788
0

Możesz stworzyć ~/aws_env_credszawierającą

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

dodaj poniżej wartość (Zastąp swój klucz)

AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C

„esc”, aby zapisać plik.

Uruchom i przetestuj pojemnik

 my_service:
      build: .
      image: my_image
      env_file:
        - ~/aws_env_creds
Manimaran Samuthirapandi
źródło