Używam docker-container na Amazon EC2. Obecnie dodałem poświadczenia AWS do Dockerfile. Czy możesz mi powiedzieć, jak najlepiej to zrobić?
Używam docker-container na Amazon EC2. Obecnie dodałem poświadczenia AWS do Dockerfile. Czy możesz mi powiedzieć, jak najlepiej to zrobić?
Odpowiedzi:
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.
AWS_SECRET_ACCESS_KEY
, nie AWS_SECRET_KEY
, w każdym razie Twoja odpowiedź była bardzo pomocna. Dziękuję Ci.
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:
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.
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 run
wyglą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 init
za 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
Innym podejściem jest przekazanie kluczy z komputera hosta do kontenera Dockera. Możesz dodać następujące wiersze do docker-compose
pliku.
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}
AWS_DEFAULT_REGION
docs.aws.amazon.com/cli/latest/userguide/ ...
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
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ą default
profilu w ~/.aws/credentials
pliku.
Jeśli chcesz używać innych profili, wystarczy wyeksportować zmienną AWS_PROFILE przed uruchomieniem docker-compose
polecenia
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/.aws
do katalogu domowego użytkownika
:ro
- oznacza tylko do odczytu objętość dockera
Jest to bardzo przydatne, gdy masz wiele profili w ~/.aws/credentials
pliku 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.
"%UserProfile%\.aws"
. Zakładam więc, że trzeba się przesiąść: - ~/.aws/:/root/.aws:ro
na- %UserProfile%\.aws:/root/.aws:ro
- host:container
skł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).
Możesz stworzyć ~/aws_env_creds
zawierają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