Liman işçisi ve şifreleri koruma


162

Son zamanlarda Docker ile oynamak için bazı hizmetler geliştirmeye çalışıyorum ve beni rahatsız eden bir şey Dockerfile'da parolalar koyuyor. Ben bir geliştiriciyim, böylece parolaları kaynakta saklamak karşısında bir yumruk gibi geliyor. Bu bir endişe bile olmalı mı? Dockerfiles'da parolaların nasıl ele alınacağına dair iyi kurallar var mı?


Yanıtlar:


93

Kesinlikle bir sorun. Docker dosyaları genellikle depolara teslim edilir ve başkalarıyla paylaşılır. Bir alternatif, çalışma zamanında ortam değişkenleri olarak herhangi bir kimlik bilgisini (kullanıcı adları, şifreler, jetonlar, hassas her şey) sağlamaktır . Bu, -e(CLI'daki bireysel değişkenler için) veya --env-file(bir dosyadaki birden çok değişken için ) bağımsız değişkeni ile mümkündür docker run. Docker-compose ile çevre kullanımı için bunu okuyun .

Kullanımı --env-filekesinlikle daha güvenli bir seçenektir, çünkü bu, pseğer kullanılıyorsa, günlüklerde veya günlüklerde gösterilen sırlara karşı korur set -x.

Ancak, env değişkenleri de özellikle güvenli değildir. Bunlar üzerinden görülebilir docker inspectve bu nedenle dockerkomut çalıştırabilen herhangi bir kullanıcı tarafından kullanılabilir . (Tabii ki, dockerana bilgisayarda erişimi olan herhangi bir kullanıcının yine de kökü vardır .)

Tercih ettiğim desen, ENTRYPOINTveya olarak bir sarmalayıcı komut dosyası kullanmaktır CMD. Sarma betiği, ilk olarak, çalışma zamanında kapsayıcıya dış bir konumdan kapsayıcıya aktarabilir, ardından sırları sağlayarak uygulamayı yürütebilir. Bunun tam mekaniği, çalışma zamanı ortamınıza bağlı olarak değişir. AWS'de, şifrelenmiş sırları bir S3 kovasında saklamak için IAM rollerinin, Anahtar Yönetim Hizmetinin ve S3'ün bir birleşimini kullanabilirsiniz . HashiCorp Vault veya credstash gibi bir şey başka bir seçenektir.

AFAIK, hassas verilerin oluşturma sürecinin bir parçası olarak kullanılması için en uygun kalıp yoktur. Aslında, bu konuda bir SO sorum var. Görüntüdeki katmanları kaldırmak için docker-squash kullanabilirsiniz . Ancak Docker'da bu amaçla yerel bir işlevsellik yoktur.

Yapılandırmalarda utangaç yorumları kapsayıcılarda yararlı bulabilirsiniz.


Diğer yorumlarda belirtildiği gibi, .configdosya içeren 2 katman (EKLE sonra ve ilk ÇALIŞTIR sonra) olacaktır .
Petr Gladkikh

1
Yer, env değişkenleri en iyi yol gibi görünüyor. Bunu TDDing Dockerfile geliştirme bağlamında inceliyorum.
gnoll110

5
Şifreniz bir env değişkeni ise, içinde görünmesinden endişe duyuyorum docker inspect.
ince

Varsayılan docker kurulumu (linux'da), sudoer ayrıcalıklarının çalışmasını gerektirir docker inspect. Saldırgan zaten sudo yapabilirse, parolanızı docker denetiminden koparmak, muhtemelen yanlış gidebilecek şeyler listenizde oldukça düşüktür. Bu ayrıntı benim için kabul edilebilir bir risk gibi görünüyor.
GrandOpener

7
@GrandOpener Bu yalnızca sisteminizi kullanan bir saldırganın olduğu durumlar için geçerlidir. Bir havuzcu imajını bir depoya itersem ve başka biri tarafından çekilirse, kendi sistemlerinde sudo olup olmadıkları umrumda değil, ancak artık env'de artık olması gerekmeyen sırları görüp görmediklerini umursamıyorum.
vee_ess

75

Ekibimiz depolara kimlik bilgilerini koymaktan kaçınır, bu yüzden içeri girmelerine izin verilmez Dockerfile. Uygulamalar içindeki en iyi uygulamamız ortam değişkenlerinden kredileri kullanmaktır.

Bunu kullanarak çözüyoruz docker-compose.

İçinde docker-compose.yml, kapsayıcıya ilişkin ortam değişkenlerini içeren bir dosya belirtebilirsiniz:

 env_file:
- .env

Emin eklemek olun .envüzere .gitignore, daha sonra içinde kimlik bilgilerini ayarlamak .envgibi dosyaya:

SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd

Mağaza .envyerel olarak veya takımın geri kalanı yakala güvenli bir konumda dosya.

Bkz. Https://docs.docker.com/compose/environment-variables/#/the-env-file


15
İsterseniz bunu .env dosyası olmadan da yapabilirsiniz. Sadece docker-compose.yml dosyanızdaki ortam özelliğini kullanın . "Yalnızca bir anahtarı olan ortam değişkenleri, Compose'un çalıştığı makinedeki değerlerine çözümlenir, bu da gizli veya ana bilgisayara özgü değerler için yararlı olabilir."
D. Visser

1
bu adama bir kurabiye ver! :) evet bu gerçekten iyi bir uygulama Sadece docs.docker.com/compose/env-file bu otomatik olarak çalışması gerektiğini eklemek istiyorum ama docker compose sürüm 2'de bu cevapta açıklandığı gibi ilan etmeniz gerekiyor gibi görünüyor.
equivalent8

5
Env var / proc / <pid> / environ ve docker incelemesi ile görülebildiğinden, ortam değişkenlerini kullanmak Docker ekibinin kendisi tarafından önerilmez. Yalnızca kök erişimi elde eden bir saldırganın kimlik bilgilerini alma yolunu gizler. Elbette kimlik bilgileri asla CVS tarafından izlenmemelidir. Bir kök kullanıcının kredi almasını önlemenin tek yolu, şifrelenmiş bir dosyadan şifrelenmiş bir işlemden web uygulamasından (proc environ dosyasını güncellemeyeceğini umarak) kimlik bilgilerini okumaktır, şifre çözme işlemi güvenli bir şekilde şifre istemektir. Sanırım bir mezarla deneyeceğim: github.com/dyne/Tomb
pawamoy

.gitignoreböylece .envhassas bilgileri içeren dosya GitHub'a iade edilmez. Eğer eklerseniz bunun işe yaramayacağından eminim.dockerignore
theUtherSide

hi @theUtherSide, Cevabınız için teşekkürler, .envdosyayı kontrol etmediğimde ve yerinde bir sunucuya dağıtım yaptığımda, .envdosyayı tekrar sunucuda manuel olarak oluşturmayı önerir misiniz ?
opensource-developer

37

Docker şimdi (sürüm 1.13 veya 17.06 ve üstü) gizli bilgileri yönetme desteğine sahiptir. İşte genel bir bakış ve daha ayrıntılı belgeler

Benzer özellik var Kubernetes ve DKG


Yukarıdaki bağlantılardan bazı yararlı komutlar docker secret create:: bir sır oluştur: bir sır docker secret inspecthakkında ayrıntılı bilgi göster docker secret ls: tüm sırları görüntüle docker secret rm: için belirli bir gizli --secretbayrağı kaldır docker service create: hizmet oluşturma sırasında bir sır oluştur --secret-addve --secret-rmbayrakları docker service update: bir sırrın değerini güncelle veya bir sırrı kaldır hizmet güncelleme görevi sırasında. Docker sırları yönetici düğümlerinde beklemede korunur ve kapsayıcı başlatılırken çalışan düğümlere sağlanır.
PJ

7
Evet, Docker sırlarını kullanmak için bir sürü kurmanız gerekiyor
Heather QC

11
Bu, bir yanıt için iyi bir başlangıçtır, ancak yanıtın kendisinde görünmesi için bağlantılı olandan çok daha fazla bilgiye ihtiyaç duyar.
Jeff Lambert

7
Sadece sürülerle çalışırsa bunun kabul edilen cevap olabileceğinden emin değilim. Birçok insan sürüsü kullanmıyor, ancak yine de sırları geçmesi gerekiyor.
John Y

9

Görüntüyü kimlerin indirebileceği kredileri yayınlamadığınız sürece hiçbir zaman kapsayıcıya kimlik bilgisi eklememelisiniz. Özellikle, ADD credsve daha sonra RUN rm credsyapmak güvenli değildir, çünkü creds dosyası bir ara dosya sistemi katmanındaki son görüntüde kalır. Görüntüye erişimi olan herkesin görüntüyü ayıklaması kolaydır.

Ödeme bağımlılıkları için krediye ihtiyaç duyduğunuzda gördüğüm tipik çözüm, başka bir konteyner oluşturmak için bir kap kullanmaktır. Yani, genellikle temel kabınızda bazı oluşturma ortamınız vardır ve uygulama kabınızı oluşturmak için bunu çağırmanız gerekir. Bu nedenle basit çözüm, uygulama kaynağınızı ve ardından RUNderleme komutlarını eklemektir . Bu konuda krediye ihtiyacınız varsa, bu güvensizdir RUN. Bunun yerine, kaynağınızı yerel bir dizine koymak docker run, yerel kaynak dizini birim olarak ve krediler enjekte edilmiş veya başka bir birim olarak bağlanmış olarak oluşturma adımını gerçekleştirmek için kapsayıcıyı çalıştırın (olduğu gibi ). Derleme adımı tamamlandığında, son konteynerinizi, ADDşimdi derlenmiş yapıları içeren yerel kaynak dizinini oluşturarak derlersiniz.

Docker'ın tüm bunları basitleştirmek için bazı özellikler eklemesini umuyorum!

Güncelleme: İleriye dönük yöntem iç içe geçmiş yapılara sahip olacak gibi görünüyor. Kısacası, dockerfile, çalışma zamanı ortamını oluşturmak için kullanılan bir ilk kapsayıcı ve daha sonra tüm parçaları son kap içine birleştirebilen ikinci bir iç içe kap yapısını tarif eder. Bu şekilde oluşturma süresi ikinci kapsayıcıda yer almaz. Uygulamayı oluşturmak için JDK'ya, ancak çalıştırmak için sadece JRE'ye ihtiyacınız olan bir Java uygulaması. Tartışılan birkaç teklif var, en iyisi https://github.com/docker/docker/issues/7115 adresinden başlamak ve alternatif teklifler için bazı bağlantıları izlemek.


7

Çok sayıda ortamınız varsa dağınık olabilen ortam değişkenlerini kullanmanın bir alternatifi, ana bilgisayardaki bir dizinin kapta erişilebilir olmasını sağlamak için birimler kullanmaktır.

Tüm kimlik bilgilerinizi bu klasöre dosya olarak koyarsanız, kapsayıcı dosyaları okuyabilir ve istediği gibi kullanabilir.

Örneğin:

$ echo "secret" > /root/configs/password.txt
$ docker run -v /root/configs:/cfg ...

In the Docker container:

# echo Password is `cat /cfg/password.txt`
Password is secret

Birçok program kimlik bilgilerini ayrı bir dosyadan okuyabilir, böylece programı dosyalardan birine yönlendirebilirsiniz.


5

yalnızca çalışma zamanı çözümü

docker-compose ayrıca küme dışı bir mod çözümü de sağlar (v1.11: Bağlama bağlarını kullanan sırlar ).

Sırlar /run/secrets/docker-compose tarafından aşağıdaki dosyalar olarak eklenir. Bu, çalışma zamanında (kapsayıcıyı çalıştırırken) sorunu çözer, ancak oluşturma zamanında (görüntüyü oluşturma) /run/secrets/değil , çünkü oluşturma zamanında monte edilmez. Ayrıca bu davranış, docker-compose ile kapsayıcı çalıştırılmasına bağlıdır.


Misal:

Dockerfile

FROM alpine
RUN cat /run/secrets/password
CMD sleep inifinity

liman işçisi-compose.yml

version: '3.1'
services:
  app:
    build: .
    secrets:
      - password

secrets:
  password:
    file: password.txt

Oluşturmak için yürütün:

docker-compose up -d

Daha fazla okuma:


2

Docker v1.9 ile , komut satırı tarafından derleme eyleminde görüntüye iletilen bağımsız değişkenleri almak için ARG komutunu kullanabilirsiniz . Basitçe kullanmak --build-arg bayrağı. Böylece Dockerfile'da açık şifreyi (veya diğer mantıklı bilgileri) saklamaktan ve bunları anında iletmekten kaçınabilirsiniz.

kaynak: https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg

Misal:

Dockerfile

FROM busybox
ARG user
RUN echo "user is $user"

görüntü komutu oluştur

docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .

inşa sırasında baskı

$ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile .

Sending build context to Docker daemon 2.048 kB
Step 1 : FROM busybox
 ---> c51f86c28340
Step 2 : ARG user
 ---> Running in 43a4aa0e421d
 ---> f0359070fc8f
Removing intermediate container 43a4aa0e421d
Step 3 : RUN echo "user is $user"
 ---> Running in 4360fb10d46a
**user is capuccino**
 ---> 1408147c1cb9
Removing intermediate container 4360fb10d46a
Successfully built 1408147c1cb9

Umarım yardımcı olur! Hoşçakal.


26
Göre Docker en ARG docs : "Bu github tuşları, kullanıcı kimlik vb gibi sırlarını geçirilmesi için kullanılması inşa zamanlı değişkenlere tavsiye edilmez"
Yalan Ryan

3
Docker'ın --build-arg var=secretbir SSH özel anahtarını bir görüntüye aktarmak için neden kullanılmayı reddettiğini merak ederek , belgelenmiş bir gerekçe yoktur. Herkes açıklayabilir mi?
Henk Wiersema

2
@HenkWiersema İşlem bilgileri, günlükleri ve komut geçmişi güvenli değildir. İşlem bilgileri herkese açıktır ve tüm komut satırı parametrelerini içerir. Genellikle bu çağrılar herkese açık olabilecek günlüklerle sonuçlanır. Bir saldırganın çalışan işlemler hakkındaki bilgileri incelemesi ve genel günlük dosyalarını sırlar için trol etmesi nadir değildir. Herkese açık olmasa bile, komut geçmişinizde saklanabilir, bu da birisinin yönetici olmayan bir hesap aracılığıyla sırlarını almasını kolaylaştırabilir.
tu-Reinstate Monica-dor duh

2
Oluşturma sırasında gereken kimlik bilgilerini sağlamanın önerilen yolu nedir? Örneğin, resmin içinde yer alacak büyük bir veri kümesi getirmek için ss erişimine ihtiyaç duyan bir görüntü?
ely

4
Önerilmemesinin sebebinin docker historymaruz kalma build-arg/ ARGdeğişken olması nedeniyle olduğunu hayal ediyorum . Herhangi bir görüntüyü çekebilir, inceleyebilir ve derleme sırasında iletilen sırları build-arg/ ARGparametresi olarak görebilirsiniz.
vee_ess

2

Benim yaklaşımım işe yarıyor gibi gözüküyor ama muhtemelen naif. Bana bunun neden yanlış olduğunu söyle.

Liman işçisi inşası sırasında ayarlanan ARG'ler geçmiş alt komutları tarafından ortaya çıkar, o yüzden oraya gitmeyin. Ancak, bir kapsayıcı çalıştırılırken, çalıştırma komutunda verilen ortam değişkenleri kapsayıcı tarafından kullanılabilir, ancak görüntünün bir parçası değildir.

Bu nedenle, Dockerfile'da gizli verileri içermeyen kurulum yapın. Gibi bir şey bir CMD ayarlayın /root/finish.sh. Run komutunda, kapsayıcıya gizli veriler göndermek için çevresel değişkenleri kullanın. finish.shdeğişkenleri temel olarak derleme görevlerini bitirmek için kullanır.

Gizli verilerin yönetimini kolaylaştırmak için, --env-fileanahtarla çalışan docker tarafından yüklenen bir dosyaya koyun . Tabii ki, dosyayı gizli tutun. .gitignoreve benzeri.

Benim için finish.shbir Python programı çalıştırıyor. Daha önce çalışmadığından emin olmak için kontrol eder, ardından kurulumu bitirir (örn. Veritabanı adını Django's'a kopyalar settings.py).


2

"Sırlar" yönetimi için yeni bir docker komutu var . Ancak bu sadece küme kümeleri için işe yarar.

docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver 


-2

Tamamen katılıyorum ama basit bir çözüm yok. Tek bir başarısızlık noktası olmaya devam ediyor. Ya dockerfile, etcd vb. Apcera'nın yardımcı - çift kimlik doğrulaması gibi görünen bir planı vardır. Başka bir deyişle, bir Apcera yapılandırma kuralı olmadığı sürece iki kap konuşamaz. Demolarında uid / pwd açıktı ve yönetici bağlantıyı yapılandırana kadar yeniden kullanılamadı. Ancak bunun çalışması için, muhtemelen Docker veya en azından ağ eklentisini yamalamak anlamına geliyordu (böyle bir şey varsa).


2
Sorulan sorunun bir yerinde bir cevap var mı?
Abhijit Sarkar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.