Saya telah bereksperimen dengan Docker baru-baru ini untuk membangun beberapa layanan untuk bermain-main dengan dan satu hal yang terus mengganggu saya telah memasukkan kata sandi di Dockerfile. Saya seorang pengembang sehingga menyimpan kata sandi di sumber terasa seperti pukulan di wajah. Haruskah ini menjadi perhatian? Apakah ada konvensi yang baik tentang bagaimana menangani kata sandi di Dockerfiles?
162
Jawaban:
Jelas itu adalah masalah. Dockerfiles biasanya masuk ke repositori dan dibagikan dengan orang lain. Alternatifnya adalah memberikan kredensial (nama pengguna, kata sandi, token, apa pun yang sensitif) sebagai variabel lingkungan saat runtime . Ini dimungkinkan melalui
-e
argumen (untuk masing-masing vars pada CLI) atau--env-file
argumen (untuk beberapa variabel dalam file) kedocker run
. Baca ini untuk menggunakan lingkungan dengan komposisi buruh pelabuhan.Menggunakan
--env-file
jelas merupakan pilihan yang lebih aman karena ini melindungi terhadap rahasia yang muncul dips
atau dalam log jika digunakanset -x
.Namun, env vars juga tidak terlalu aman. Mereka terlihat melalui
docker inspect
, dan karenanya mereka tersedia untuk setiap pengguna yang dapat menjalankandocker
perintah. (Tentu saja, setiap pengguna yang memiliki akses kedocker
host juga memiliki root .)Pola pilihan saya adalah menggunakan skrip pembungkus sebagai
ENTRYPOINT
atauCMD
. Skrip pembungkus dapat pertama-tama mengimpor rahasia dari lokasi luar ke dalam wadah pada saat run time, kemudian menjalankan aplikasi, memberikan rahasia. Mekanik yang tepat untuk ini berbeda-beda berdasarkan lingkungan waktu kerja Anda. Di AWS, Anda dapat menggunakan kombinasi peran IAM, Layanan Manajemen Kunci , dan S3 untuk menyimpan rahasia terenkripsi dalam keranjang S3. Sesuatu seperti HashiCorp Vault atau credstash adalah pilihan lain.AFAIK tidak ada pola optimal untuk menggunakan data sensitif sebagai bagian dari proses pembangunan. Bahkan, saya punya pertanyaan SO tentang topik ini. Anda dapat menggunakan docker-squash untuk menghapus lapisan dari suatu gambar. Tetapi tidak ada fungsi asli di Docker untuk tujuan ini.
Anda mungkin menemukan komentar shykes tentang konfigurasi dalam wadah berguna.
sumber
.config
file.docker inspect
.docker inspect
. Jika penyerang sudah bisa sudo, mengambil kata sandi Anda dari pemeriksaan buruh pelabuhan mungkin cukup rendah pada daftar hal-hal yang sekarang bisa salah. Detail khusus ini sepertinya risiko yang dapat diterima bagi saya.Tim kami menghindari memasukkan kredensial ke dalam repositori, sehingga itu berarti mereka tidak diizinkan masuk
Dockerfile
. Praktik terbaik kami dalam aplikasi adalah menggunakan kredit dari variabel lingkungan.Kami memecahkan ini menggunakan
docker-compose
.Di dalam
docker-compose.yml
, Anda dapat menentukan file yang berisi variabel lingkungan untuk wadah:Pastikan untuk menambahkan
.env
ke.gitignore
, kemudian mengatur kredensial dalam.env
file seperti:Simpan
.env
file secara lokal atau di lokasi yang aman tempat anggota tim lainnya dapat mengambilnya.Lihat: https://docs.docker.com/compose/environment-variables/#/the-env-file
sumber
.gitignore
sehingga.env
file dengan informasi sensitif tidak bisa masuk ke GitHub. Saya cukup yakin ini tidak akan berhasil jika Anda menambahkannya.dockerignore
.env
file dan saya melakukan penyebaran ke server di tempat, apakah Anda menyarankan untuk membuat.env
file lagi di server secara manual?Docker sekarang (versi 1.13 atau 17.06 dan lebih tinggi) memiliki dukungan untuk mengelola informasi rahasia. Berikut ini ikhtisar dan dokumentasi yang lebih rinci
Fitur serupa ada di kubernet dan DCOS
sumber
docker secret create
:: buat rahasiadocker secret inspect
: tampilkan informasi terperinci tentang rahasiadocker secret ls
: lihat semua rahasiadocker secret rm
: hapus--secret
bendera rahasia khusus untukdocker service create
: buat rahasia selama pembuatan layanan--secret-add
dan--secret-rm
tanda untukdocker service update
: perbarui nilai rahasia atau hapus rahasia selama tugas pembaruan layanan. Rahasia buruh pelabuhan dilindungi saat istirahat di node manajer dan disediakan untuk node pekerja saat selama wadah startup.Anda tidak boleh menambahkan kredensial ke wadah kecuali Anda menyiarkan kredibilitas kepada siapa pun yang dapat mengunduh gambar. Secara khusus, melakukan dan
ADD creds
dan kemudianRUN rm creds
tidak aman karena file kredit tetap pada gambar akhir di lapisan sistem file menengah. Mudah bagi siapa saja yang memiliki akses ke gambar untuk mengekstraknya.Solusi khas yang saya lihat ketika Anda membutuhkan kredit untuk checkout dependensi dan sejenisnya adalah dengan menggunakan satu wadah untuk membangun yang lain. Yaitu, biasanya Anda memiliki beberapa lingkungan build di wadah dasar Anda dan Anda harus memohonnya untuk membangun wadah aplikasi Anda. Jadi solusi sederhana adalah menambahkan sumber aplikasi Anda dan kemudian
RUN
membangun perintah. Ini tidak aman jika Anda membutuhkan kredit dalam hal ituRUN
. Alih-alih apa yang Anda lakukan adalah memasukkan sumber Anda ke direktori lokal, jalankan (seperti dalamdocker run
) wadah untuk melakukan langkah pembangunan dengan direktori sumber lokal dipasang sebagai volume dan kredibilitasnya disuntikkan atau dipasang sebagai volume lain. Setelah langkah pembangunan selesai, Anda membangun wadah akhir Anda hanyaADD
dengan memasukkan direktori sumber lokal yang sekarang berisi artefak bawaan.Saya berharap Docker menambahkan beberapa fitur untuk menyederhanakan semua ini!
Pembaruan: sepertinya metode yang akan datang adalah untuk membangun bersarang. Singkatnya, buruh pelabuhan akan menjelaskan wadah pertama yang digunakan untuk membangun lingkungan run-time dan kemudian membangun wadah bersarang kedua yang dapat merakit semua potongan ke dalam wadah akhir. Dengan demikian, barang bawaan tidak ada dalam wadah kedua. Ini aplikasi Java di mana Anda memerlukan JDK untuk membangun aplikasi tetapi hanya JRE untuk menjalankannya. Ada sejumlah proposal yang sedang dibahas, sebaiknya dimulai dari https://github.com/docker/docker/issues/7115 dan ikuti beberapa tautan untuk proposal alternatif.
sumber
Alternatif untuk menggunakan variabel lingkungan, yang bisa berantakan jika Anda memiliki banyak variabel, adalah dengan menggunakan volume untuk membuat direktori pada host yang dapat diakses dalam wadah.
Jika Anda meletakkan semua kredensial Anda sebagai file di folder itu, maka wadah itu dapat membaca file dan menggunakannya sesuai keinginan.
Sebagai contoh:
Banyak program dapat membaca kredensial mereka dari file terpisah, jadi dengan cara ini Anda bisa mengarahkan program ke salah satu file.
sumber
solusi run-time saja
docker-compose juga menyediakan solusi mode non-swarm (sejak v1.11: Rahasia menggunakan bind mounts ).
Rahasia dipasang sebagai file di bawah ini
/run/secrets/
oleh susunan buruh pelabuhan. Ini menyelesaikan masalah saat run-time (menjalankan wadah), tetapi tidak pada build-time (membangun gambar), karena/run/secrets/
tidak dipasang pada build-time. Selanjutnya perilaku ini tergantung pada menjalankan wadah dengan menyusun buruh pelabuhan.Contoh:
Dockerfile
docker-compose.yml
Untuk membangun, jalankan:
Bacaan lebih lanjut:
sumber
Dengan Docker v1.9 Anda dapat menggunakan instruksi ARG untuk mengambil argumen yang dilewatkan oleh baris perintah ke gambar saat dibuat . Cukup gunakan flag --build-arg . Jadi Anda dapat menghindari untuk menyimpan kata sandi eksplisit (atau informasi masuk akal lainnya) di Dockerfile dan meneruskannya dengan cepat.
sumber: https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg
Contoh:
Dockerfile
membangun perintah gambar
selama build it print
Semoga ini bisa membantu! Sampai jumpa.
sumber
--build-arg var=secret
untuk melewatkan kunci pribadi SSH ke gambar, tidak ada alasan yang didokumentasikan. Adakah yang bisa menjelaskannya?docker history
mengeksposbuild-arg
/ARG
variabel. Satu dapat menarik gambar apapun, memeriksanya dan melihat rahasia berlalu selama membangun sebagaibuild-arg
/ARG
parameter.Pendekatan saya tampaknya berhasil, tetapi mungkin naif. Katakan padaku mengapa itu salah.
ARG yang ditetapkan selama pembuatan buruh pelabuhan terpapar oleh perintah sejarah, jadi jangan pergi ke sana. Namun, saat menjalankan wadah, variabel lingkungan yang diberikan dalam perintah jalankan tersedia untuk wadah, tetapi bukan bagian dari gambar.
Jadi, di Dockerfile, lakukan pengaturan yang tidak melibatkan data rahasia. Tetapkan CMD dari sesuatu seperti
/root/finish.sh
. Dalam menjalankan perintah, gunakan variabel lingkungan untuk mengirim data rahasia ke dalam wadah.finish.sh
menggunakan variabel dasarnya untuk menyelesaikan membangun tugas.Untuk mempermudah mengelola data rahasia, masukkan ke dalam file yang dimuat oleh buruh pelabuhan dengan
--env-file
sakelar. Tentu saja, jaga kerahasiaannya..gitignore
dan seperti.Bagi saya,
finish.sh
jalankan program Python. Itu memeriksa untuk memastikan itu belum berjalan sebelumnya, kemudian menyelesaikan pengaturan (misalnya, menyalin nama database ke Djangosettings.py
).sumber
Ada perintah buruh pelabuhan baru untuk manajemen "rahasia". Tapi itu hanya berfungsi untuk kelompok swarm.
sumber
The 12-Factor metodologi aplikasi mengatakan, bahwa konfigurasi harus disimpan dalam variabel lingkungan.
Penulisan Docker dapat melakukan substitusi variabel dalam konfigurasi, sehingga dapat digunakan untuk meneruskan kata sandi dari host ke docker.
sumber
Sementara saya setuju sepenuhnya, tidak ada solusi sederhana. Terus ada satu titik kegagalan. Entah dockerfile, etcd, dan sebagainya. Apcera memiliki rencana yang mirip dengan sidekick - otentikasi ganda. Dengan kata lain dua wadah tidak dapat berbicara kecuali ada aturan konfigurasi Apcera. Dalam demo mereka, uid / pwd jelas dan tidak dapat digunakan kembali sampai admin mengkonfigurasi tautannya. Agar ini berfungsi, mungkin berarti menambal Docker atau setidaknya plugin jaringan (jika ada hal seperti itu).
sumber