Manakah cara terbaik untuk meneruskan kredensial AWS ke kontainer Docker?

104

Saya menjalankan docker-container di Amazon EC2. Saat ini saya telah menambahkan Kredensial AWS ke Dockerfile. Bisakah Anda memberi tahu saya cara terbaik untuk melakukan ini?

suraj chopade
sumber
2
Bagaimana jika saya menjalankan kontainer Docker di laptop saya yang seharusnya juga bekerja secara ajaib di ECS ketika saya mendorongnya ke sana? Saya kira saya menggunakan - bendera volume ... seseorang pasti sudah menjawab ...
Randy L

Jawaban:

107

Cara terbaik adalah menggunakan Peran IAM dan tidak berurusan dengan kredensial sama sekali. (lihat http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )

Kredensial dapat diambil dari http://169.254.169.254..... Karena ini adalah alamat ip pribadi, ini hanya dapat diakses dari instans EC2.

Semua pustaka klien AWS modern "tahu" cara mengambil, menyegarkan, dan menggunakan kredensial dari sana. Jadi dalam banyak kasus Anda bahkan tidak perlu mengetahuinya. Jalankan saja ec2 dengan peran IAM yang benar dan Anda siap melakukannya.

Sebagai opsi, Anda dapat meneruskannya pada waktu proses sebagai variabel lingkungan (mis. docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage)

Anda dapat mengakses variabel lingkungan ini dengan menjalankan printenv di terminal.

Vor
sumber
35
Apakah ada cara yang baik untuk melakukan ini selama pengembangan / pengujian lokal yang tidak membahayakan keamanan dalam produksi? Saya ingin memastikan gambar berfungsi tanpa menerapkannya sepenuhnya.
honktronic
3
alternatif yang saya posting dengan variabel lingkungan berfungsi dengan baik di lingkungan dev / lokal.
Vor
5
Saya ingin tahu apakah ini salah ketik, tetapi saya harus memasukkan AWS_SECRET_ACCESS_KEY, tidak AWS_SECRET_KEY, bagaimanapun juga jawaban Anda sangat membantu. Terima kasih.
Akavall
14
Sederhananya (bagi mereka yang mendapatkan jawaban ini dengan cara yang sama seperti saya); Kontainer buruh pelabuhan yang berjalan pada EC2 akan mewarisi peran yang sama sebagai instance host. (Saya membutuhkan "ELI5" seperti ini ketika perintah AWS CLI di penampung saya bekerja secara misterius meskipun tidak ada kredensial yang diberikan kepada mereka!)
Adam Westbrook
8
Cara mudah untuk mendapatkan nilai kunci dari profil lokal Anda untuk ditetapkan ke variabel lingkungan untuk tujuan pengembangan (seperti yang disarankan di cameroneckelberry.co/words/… ): "aws --profile default configure get aws_access_key_id"
Altair7852
92

Banyak yang telah berubah di Docker sejak pertanyaan ini diajukan, jadi inilah upaya untuk jawaban yang diperbarui.

Pertama, khususnya dengan kredensial AWS pada kontainer yang sudah berjalan di dalam cloud, menggunakan peran IAM seperti yang disarankan Vor adalah opsi yang sangat bagus. Jika Anda bisa melakukan itu, tambahkan satu tambah satu pada jawabannya dan lewati sisanya.


Setelah Anda mulai menjalankan sesuatu di luar cloud, atau memiliki jenis rahasia yang berbeda, ada dua tempat utama yang saya rekomendasikan untuk tidak menyimpan rahasia:

  1. Variabel lingkungan: ketika ini didefinisikan pada sebuah penampung, setiap proses di dalam penampung memiliki akses ke sana, mereka terlihat melalui / proc, aplikasi dapat membuang lingkungannya ke stdout di mana ia disimpan di log, dan yang terpenting, mereka muncul di hapus teks saat Anda memeriksa wadah.

  2. Dalam gambar itu sendiri: gambar sering didorong ke registri di mana banyak pengguna memiliki akses tarik, terkadang tanpa kredensial yang diperlukan untuk menarik gambar. Bahkan jika Anda menghapus rahasia dari satu lapisan, gambar tersebut dapat dibongkar dengan utilitas Linux umum seperti tardan rahasianya dapat ditemukan dari langkah pertama kali ditambahkan ke gambar.


Jadi pilihan apa lagi yang tersedia untuk rahasia di kontainer Docker?

Opsi A: Jika Anda memerlukan rahasia ini hanya selama pembuatan gambar, tidak dapat menggunakan rahasia sebelum build dimulai, dan belum memiliki akses ke BuildKit, build multi-tahap adalah pilihan terbaik dari yang buruk. Anda akan menambahkan rahasia ke tahap awal pembuatan, menggunakannya di sana, lalu menyalin keluaran tahap tersebut tanpa rahasia ke tahap rilis Anda, dan hanya mendorong tahap rilis tersebut ke server registri. Rahasia ini masih ada di cache gambar di server build, jadi saya cenderung menggunakan ini hanya sebagai pilihan terakhir.

Opsi B: Juga selama waktu pembuatan, jika Anda dapat menggunakan BuildKit yang dirilis pada 18.09, saat ini terdapat fitur eksperimental yang memungkinkan injeksi rahasia sebagai pemasangan volume untuk satu baris RUN. Pemasangan itu tidak ditulis ke lapisan gambar, jadi Anda dapat mengakses rahasia selama pembuatan tanpa khawatir itu akan didorong ke server registri publik. Dockerfile yang dihasilkan terlihat seperti:

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

Dan Anda membangunnya dengan perintah di 18.09 atau yang lebih baru seperti:

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

Opsi C:Saat runtime di satu node, tanpa Swarm Mode atau orkestrasi lainnya, Anda dapat memasang kredensial sebagai volume hanya baca. Akses ke kredensial ini memerlukan akses yang sama dengan yang Anda miliki di luar buruh pelabuhan ke file kredensial yang sama, jadi tidak lebih baik atau lebih buruk daripada skenario tanpa buruh pelabuhan. Yang terpenting, konten file ini tidak boleh terlihat saat Anda memeriksa penampung, melihat log, atau mendorong gambar ke server registri, karena volumenya berada di luar itu di setiap skenario. Ini mengharuskan Anda menyalin kredensial Anda pada host buruh pelabuhan, terpisah dari penerapan penampung. (Catatan, siapa pun dengan kemampuan untuk menjalankan kontainer pada host tersebut dapat melihat kredensial Anda karena akses ke API pekerja pelabuhan adalah root pada host dan root dapat melihat file dari setiap pengguna. Jika Anda tidak mempercayai pengguna dengan root pada host ,

Untuk a docker run, ini terlihat seperti:

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

Atau untuk file tulis, Anda akan memiliki:

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

Opsi D:Dengan alat orkestrasi seperti Swarm Mode dan Kubernetes, kami sekarang memiliki dukungan rahasia yang lebih baik daripada volume. Dengan Swarm Mode, file dienkripsi pada sistem file manajer (meskipun kunci dekripsi juga sering ada, memungkinkan manajer untuk memulai ulang tanpa admin memasukkan kunci dekripsi). Lebih penting lagi, rahasia hanya dikirim ke pekerja yang membutuhkan rahasia (menjalankan wadah dengan rahasia itu), itu hanya disimpan di memori pada pekerja, tidak pernah disk, dan itu disuntikkan sebagai file ke dalam wadah dengan tmpfs meningkat. Pengguna pada host di luar swarm tidak dapat memasang rahasia itu langsung ke wadah mereka sendiri, namun, dengan akses terbuka ke API buruh pelabuhan, mereka dapat mengekstrak rahasia dari wadah yang berjalan di simpul, jadi sekali lagi, batasi siapa yang memiliki akses ini ke API. Dari penulisan, injeksi rahasia ini terlihat seperti:

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

Anda mengaktifkan mode swarm dengan docker swarm inituntuk satu node, lalu ikuti petunjuk untuk menambahkan node tambahan. Anda dapat membuat rahasia secara eksternal dengan docker secret create aws_creds $HOME/.aws/credentials. Dan Anda menerapkan file tulis dengan docker stack deploy -c docker-compose.yml stack_name.

Saya sering membuat versi rahasia saya menggunakan skrip dari: https://github.com/sudo-bmitch/docker-config-update

Opsi E: Ada alat lain untuk mengelola rahasia, dan favorit saya adalah Vault karena memberikan kemampuan untuk membuat rahasia terbatas waktu yang kedaluwarsa secara otomatis. Setiap aplikasi kemudian mendapatkan set tokennya sendiri untuk meminta rahasia, dan token tersebut memberi mereka kemampuan untuk meminta rahasia terbatas waktu tersebut selama mereka dapat mencapai server vault. Itu mengurangi risiko jika sebuah rahasia diambil dari jaringan Anda karena rahasia itu tidak akan berfungsi atau cepat kedaluwarsa. Fungsionalitas khusus untuk AWS untuk Vault didokumentasikan di https://www.vaultproject.io/docs/secrets/aws/index.html

BMitch
sumber
22

Pendekatan lain adalah meneruskan kunci dari mesin host ke container buruh pelabuhan. Anda dapat menambahkan baris berikut ke docker-composefile.

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
sumber
3
Variabel lingkungan wilayah yang benar adalah AWS_REGION. Lihat stackoverflow.com/questions/44151982/…
John Camerin
3
Silakan periksa dokumen resmi yang menyebutkan AWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/…
prafi
7
Ketika saya menggunakan AWS_DEFAULT_REGION, saya mendapat pengecualian bahwa wilayah default tidak dapat ditemukan. Pencarian saya mengarah ke docs.aws.amazon.com/sdk-for-java/v1/developer-guide/… yang menentukan variabel lingkungan AWS_REGION, dan itu berhasil untuk saya.
John Camerin
Jika Anda menggunakan kredensial sementara maka Anda mungkin juga perluAWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Davos
14

Namun pendekatan lain adalah membuat volume hanya-baca sementara di docker-compose.yaml. AWS CLI dan SDK (seperti boto3 atau AWS SDK untuk Java dll.) Sedang mencari defaultprofil dalam ~/.aws/credentialsfile.

Jika Anda ingin menggunakan profil lain, Anda hanya perlu mengekspor variabel AWS_PROFILE sebelum menjalankan docker-composeperintah

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

Dalam contoh ini saya menggunakan pengguna root di buruh pelabuhan. Jika Anda menggunakan pengguna lain, cukup ubah /root/.awske direktori home pengguna

:ro - singkatan dari volume buruh pelabuhan hanya-baca

Ini sangat membantu bila Anda memiliki banyak profil dalam ~/.aws/credentialsfile dan Anda juga menggunakan MFA. Juga berguna saat Anda ingin menguji docker-container sebelum menerapkannya di ECS tempat Anda memiliki Peran IAM, tetapi secara lokal tidak.

Artur Siepietowski
sumber
Pada jendela katalog .aws` terletak "%UserProfile%\.aws". Jadi saya berasumsi bahwa Anda harus mengubah: - ~/.aws/:/root/.aws:romenjadi- %UserProfile%\.aws:/root/.aws:ro
Artur Siepietowski
1
Ini hanya akan bekerja dengan proses build tunggal dan bukan multistage.
wlarcheveque
@wlarcheveque Mau menjelaskan lebih lanjut?
ErikE
Berhati-hatilah saat menggunakan - host:containersintaks, jika file / folder tidak ada pada host, file akan dibuat (sebagai root) dan awscli tidak akan berterima kasih karena Anda telah memberinya file nol byte. Anda harus menggunakan "bentuk panjang" yang menentukan jenis mengikat, jalur host, dan jalur kontainer pada baris terpisah, ini gagal jika file tidak ada, yang Anda inginkan di docker-compose.dev Anda. yml tetapi tidak di docker-compose.yml (prod / AWS deploy) Anda.
dragon788
0

Anda bisa membuat ~/aws_env_credsberisi

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

tambahkan nilai di bawah (Ganti kunci Anda)

AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C

"esc" untuk menyimpan file.

Jalankan dan uji wadahnya

 my_service:
      build: .
      image: my_image
      env_file:
        - ~/aws_env_creds
Manimaran Samuthirapandi
sumber