Який найкращий спосіб передавати облікові дані AWS до контейнера Docker?


104

Я запускаю докер-контейнер на Amazon EC2. Наразі я додав облікові дані AWS до Dockerfile. Не могли б ви повідомити мені найкращий спосіб зробити це?


2
Як щодо того, якщо я запускаю контейнер Docker на своєму ноутбуці, який також повинен магічно працювати в ECS, коли я його туди засовую? Я збираюся здогадуватися, що використовую прапор --volume ... хтось, мабуть, уже відповів ...
Randy L

Відповіді:


107

Найкращий спосіб - використовувати IAM Role і взагалі не мати справу з обліковими даними. (див. http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )

Облікові дані можна отримати з http://169.254.169.254..... Оскільки це приватна ip-адреса, вона може бути доступна лише з екземплярів EC2.

Усі сучасні бібліотеки клієнтів AWS "знають", як отримати, оновити та використовувати облікові дані звідти. Тож у більшості випадків про це навіть не потрібно знати. Просто запустіть ec2 з правильною роллю IAM, і ви готові піти.

Як варіант, ви можете передавати їх під час виконання як змінні середовища (тобто docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage)

Ви можете отримати доступ до цих змінних середовища, запустивши printenv на терміналі.


35
Чи є хороший спосіб зробити це під час місцевої розробки / тестування, який не загрожує безпеці виробництва? Я хотів би переконатися, що зображення працює, не розгортаючи його повністю.
honktronic

3
альтернатива, яку я опублікував із змінними середовища, чудово працює у dev / local середовищі.
Злодій

5
Цікаво, чи це помилка, але мені потрібно ввести AWS_SECRET_ACCESS_KEY, ні AWS_SECRET_KEY, у будь-якому разі ваша відповідь була дуже корисною. Спасибі.
Акавалл

14
Простіше кажучи (для тих, хто дійшов до цієї відповіді так само, як і я); Контейнер докера, що працює на EC2, успадкує ту саму роль, що і екземпляр хоста. (Мені потрібен був такий "ELI5", коли команди AWS CLI у моїх контейнерах загадково працювали, незважаючи на те, що їм не передавали жодних облікових даних!)
Адам Вестбрук,

8
Простий спосіб отримати ключові значення з вашого локального профілю, щоб призначити змінну середовища для цілей розробки (як пропонується в cameroneckelberry.co/words/… ): "aws --profile configure get aws_access_key_id"
Altair7852

92

З моменту того, як було задано це питання, у Docker багато що змінилося, тож ось спробу оновленої відповіді.

По-перше, зокрема, з обліковими даними AWS для контейнерів, які вже запущені всередині хмари, використання ролей IAM, як вважає Вор, є дійсно хорошим варіантом. Якщо ви можете це зробити, додайте ще один плюс один до його відповіді і пропустіть решту цього.


Як тільки ви починаєте запускати речі поза хмарою або використовуєте інший тип секрету, є два ключових місця, які я рекомендую не зберігати:

  1. Змінні середовища: коли вони визначені в контейнері, кожен процес всередині контейнера має до них доступ, вони видно через / proc, програми можуть скидати своє середовище в stdout, де воно зберігається в журналах, і найголовніше, що вони відображаються в чіткий текст при огляді контейнера.

  2. В самому зображенні: зображення часто надсилаються до реєстрів, де багато користувачів мають доступ для витягування, іноді без будь-яких облікових даних, необхідних для витягування зображення. Навіть якщо ви видалите секрет з одного шару, зображення можна розібрати за допомогою звичайних утиліт Linux, наприклад, tarі секрет можна знайти з кроку, де він був вперше доданий до зображення.


То які ще є варіанти секретів у контейнерах Docker?

Варіант A: Якщо вам потрібен цей секрет лише під час збірки вашого зображення, ви не можете використовувати секрет до початку збірки і ще не маєте доступу до BuildKit, то багатоступенева збірка - найкращий з поганих варіантів. Ви повинні додати секрет до початкових етапів збірки, використовувати його там, а потім скопіювати висновок цього етапу без секрету до етапу випуску і лише просунути цей етап випуску на сервери реєстру. Цей секрет все ще знаходиться в кеші зображень на сервері збірки, тому я, як правило, використовую це лише в крайньому випадку.

Варіант B: Також під час побудови, якщо ви можете використовувати BuildKit, який був випущений в 18.09, на даний момент існують експериментальні функції, які дозволяють вводити секрети як об'ємне кріплення для однієї лінії RUN. Це монтування не записується на шари зображення, тому ви можете отримати доступ до секрету під час побудови, не турбуючись, що він буде перенесений на загальнодоступний сервер реєстру. Отриманий файл Docker виглядає так:

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

І ви створюєте його за допомогою команди 18.09 або новішої, наприклад:

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

Варіант C:Під час виконання на одному вузлі, без режиму зграї чи іншої оркестрації, ви можете змонтувати облікові дані як том, призначений лише для читання. Доступ до цих облікових даних вимагає того самого доступу, який ви мали б за межами докера до того самого файлу облікових даних, тому він не кращий і не гірший за сценарій без докера. Найголовніше, що вміст цього файлу не повинен бути видимим під час перевірки контейнера, перегляду журналів або надсилання зображення на сервер реєстру, оскільки обсяг не відповідає такому в кожному сценарії. Для цього потрібно скопіювати свої облікові дані на хост докера, окремо від розгортання контейнера. (Зверніть увагу, будь-хто, хто має можливість запускати контейнери на цьому хості, може переглядати ваші облікові дані, оскільки доступ до API докера є root на хості, а root може переглядати файли будь-якого користувача. Якщо ви не довіряєте користувачам root на хості ,

Для docker run, це виглядає так:

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

Або для файлу для складання у вас буде:

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

Варіант D:Завдяки інструментам оркестрації, таким як Swarm Mode та Kubernetes, ми тепер маємо підтримку секретів, яка краща за обсяг. У режимі зграї файл шифрується у файловій системі менеджера (хоча там часто є і ключ розшифровки, що дозволяє перезапустити менеджер без введення адміністратором ключа розшифровки). Що ще важливіше, секрет надсилається лише працівникам, яким потрібен секрет (запуск контейнера з цим секретом), він зберігається лише в пам’яті на робочому місці, ніколи не на диску, і вводиться як файл у контейнер за допомогою tmpfs кріплення. Користувачі на хості поза роєм не можуть монтувати цей секрет безпосередньо у свій власний контейнер, однак, маючи відкритий доступ до API докера, вони можуть витягти секрет із запущеного контейнера на вузлі, тому знову обмежте, хто має цей доступ до API. З композиції ця секретна ін’єкція виглядає так:

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

Ви вмикаєте ройовий режим docker swarm initдля одного вузла, а потім дотримуєтесь інструкцій щодо додавання додаткових вузлів. Ви можете створити секрет зовні за допомогою docker secret create aws_creds $HOME/.aws/credentials. І ви розгортаєте файл написання за допомогою docker stack deploy -c docker-compose.yml stack_name.

Я часто викладаю свої секрети, використовуючи скрипт за адресою : https://github.com/sudo-bmitch/docker-config-update

Варіант E: Існують інші інструменти для управління секретами, і мій улюблений - Сейф, оскільки він дає можливість створювати обмежені в часі секрети, які автоматично закінчуються. Потім кожна програма отримує власний набір токенів для запиту секретів, і ці маркери дають їм можливість запитувати ці обмежені в часі секрети до тих пір, поки вони можуть дістатися до сервера сховища. Це зменшує ризик, якщо секрет коли-небудь буде вилучено з вашої мережі, оскільки він або не буде працювати, або швидко закінчиться. Функціональність, специфічна для AWS для Сейфу, задокументована за адресою https://www.vaultproject.io/docs/secrets/aws/index.html


22

Іншим підходом є передача ключів від хост-машини до контейнера докера. Ви можете додати наступні рядки до docker-composeфайлу.

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}

3
Правильною змінною середовища регіону є AWS_REGION. Дивіться stackoverflow.com/questions/44151982/…
Джон Камерін,

3
Будь ласка, перевірте офіційний документ, в якому згадується AWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/…
Прафі

7
Коли я використовував AWS_DEFAULT_REGION, я отримав виняток, що область за замовчуванням не може бути знайдена. Мій пошук привів до docs.aws.amazon.com/sdk-for-java/v1/developer-guide/…, який визначає змінну середовища AWS_REGION, і це спрацювало для мене.
Джон Камерін

Якщо ви використовуєте тимчасові дані, тоді вам також можуть знадобитисяAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Давос,

14

Ще один підхід полягає у створенні тимчасового тому, доступного лише для читання, у docker-compose.yaml. AWS CLI та SDK (наприклад, boto3 або AWS SDK для Java тощо) шукають defaultпрофіль у ~/.aws/credentialsфайлі.

Якщо ви хочете використовувати інші профілі, вам потрібно також експортувати змінну AWS_PROFILE перед запуском docker-composeкоманди

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

У цьому прикладі я використовував root користувача на docker. Якщо ви використовуєте іншого користувача, просто перейдіть /root/.awsдо домашнього каталогу користувача

:ro - означає обсяг докера, доступний лише для читання

Дуже корисно, коли у вас є кілька профілів, ~/.aws/credentialsі ви також використовуєте MFA. Також корисно, коли ви хочете локально протестувати докер-контейнер перед розгортанням його на ECS, на якому у вас є ролі IAM, але локально - ні.


На вікні розміщений каталог .aws "%UserProfile%\.aws". Тож я припускаю, що вам доведеться змінити: - ~/.aws/:/root/.aws:roна- %UserProfile%\.aws:/root/.aws:ro
Artur Siepietowski

1
Це буде працювати лише з одними процесами побудови, а не багатоступеневими.
wlarcheveque

@wlarcheveque Докладно розробити?
ErikE

Будьте ДУЖЕ обережні, використовуючи - host:containerсинтаксис, якщо файл / папка не існує на хості, який він створює (як корінь), і awscli не подякує вам за подання йому нульового байтового файлу. Ви повинні використовувати "довгу форму", яка визначає тип bind, шлях хосту та шлях контейнера в окремих рядках, це не вдається, якщо файл не існує, саме цього ви хочете у своєму docker-compose.dev. yml, але не у вашому docker-compose.yml (розгортання prod / AWS).
dragon788

0

Ви можете створити ~/aws_env_credsвміст

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

додати значення нижче (Замінити ключ свого)

AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C

"esc", щоб зберегти файл.

Запустіть і протестуйте контейнер

 my_service:
      build: .
      image: my_image
      env_file:
        - ~/aws_env_creds
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.