在http://docs.docker.com/engine/reference/builder/#arg中,它建议秘密不通过ARGS传递。
注意:建议不要使用构建时变量来传递github密钥,用户凭据等秘密。
什么时候秘密通过构建时变量传递到危险之中?
答案 0 :(得分:31)
2018年8月更新:
您现在拥有码头 build --secret id=mysecret,src=/secret/file
请参阅" safe way to use build-time argument in Docker"。
2017年1月更新:
Docker(swarm)1.13有docker secret
。
但是,commented为Steve Hoffman (bacoboy
):
[...] secret命令只能帮助swarm用户提供更通用的解决方案(就像他们附加持久卷一样)。
你如何管理你的秘密(它们是什么以及谁有权访问它们)是非常依赖于系统的,取决于你拼凑的付费和/或OSS的哪些部分来制作你的平台"。
随着Docker公司开始提供一个平台,我并不感到意外,因为Hashicorp将Vault整合到Atlas中,他们的第一次实施是基于swarm的 - 这是有意义的。秘密如何通过
docker run
以外的空间 AWS使用角色和策略来授予/拒绝权限以及SDK 厨师使用加密的数据库和加密" bootstrapping"认证。
K8S有自己的1.13版本 我确定mesos会及时添加类似的实现。这些实施似乎属于两个阵营。
- 通过音量安装传递秘密"平台"提供或(厨师/码头秘密/ k8s
- 传递凭据与外部服务通信,以便在启动时获取内容(iam / credstash / etc)
原始答案:2015年11月
这是commit 54240f8(2015年11月,码头工具1.9)中引入的,来自PR 15182,
构建环境被添加到中间合并程序的命令字符串中,以帮助缓存查找 它还有助于构建可追溯性。但是,从传递构建时间秘密的角度来看,这也使得该功能的安全性降低。
issue 13490重申:
构建时环境变量:构建时环境变量不是为处理机密而设计的。由于缺乏其他选择,人们计划将其用于此目的。为了防止给人以适合保密的印象,我们决定故意不加密这些变量。
env变量是传递秘密的错误方法。我们不应该试图重新发明轮子并立即提供一种残缺的安全分配机制。
当您将密钥存储在环境中时,您很容易意外地暴露它们 - 这正是我们想要避免的:
- 鉴于该流程隐含可用环境,跟踪访问以及内容如何暴露是非常困难的(如果不是不可能的话)
- 应用程序抓取整个环境并将其打印出来是非常常见的,因为它可用于调试,甚至可以将其作为错误报告的一部分发送。如此多的秘密被泄露给PagerDuty,他们有一个润滑良好的内部流程,可以从他们的基础设施中擦除它们。
- 环境变量向下传递给子进程,这允许非预期的访问并违反最小权限原则。想象一下,作为应用程序的一部分,您可以调用第三方工具来执行某些操作,突然之间第三方工具可以访问您的环境,上帝知道它将如何处理它。
- 对于崩溃的应用程序来说,将环境变量存储在日志文件中以供以后调试是很常见的。这意味着在磁盘上以纯文本形式保密。
- 将env变量中的秘密快速转化为部落知识。新工程师不知道他们在那里,并且不知道他们在处理环境变量时应该小心(将它们过滤到子流程等)。
总的来说,env变量中的秘密打破了最不惊讶的原则,这是一种不好的做法,会导致最终泄密。
答案 1 :(得分:9)
简单的原因是只要在图像上运行history
,图像的任何人都可以看到秘密的价值。
拿这个示例泊坞文件:
FROM alpine
ARG secret
RUN echo "${secret}"
(很简单,只是为了说明你如何使用秘密。)
然后我们构建它$ docker build --build-arg secret=S3CR3T - < Dockerfile
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM alpine
---> 13e1761bf172
Step 2 : ARG secret
---> Running in 695b7a931445
---> 5414c15a1cb6
Removing intermediate container 695b7a931445
Step 3 : RUN echo "${secret}"
---> Running in c90cf0d1414b
s3cr3t
---> f2bcff49ac09
Removing intermediate container c90cf0d1414b
Successfully built f2bcff49ac09
以及如何获得&#34;秘密&#34;退出(在第一行查找 |1 secret=
):
$ docker history f2bcff49ac09
IMAGE CREATED CREATED BY SIZE COMMENT
f2bcff49ac09 8 seconds ago |1 secret=S3CR3T /bin/sh -c echo "${secret}" 0 B
5414c15a1cb6 8 seconds ago /bin/sh -c #(nop) ARG secret 0 B
13e1761bf172 6 months ago /bin/sh -c #(nop) ADD file:614a9122187935fccf 4.797 MB
如果您已在本地构建图像或从注册表中提取图像,则会出现这种情况。
如果您的目标是将构建时间秘密保留在正在运行的容器之外,那么使用ARG会对您有所帮助 - 请考虑以下事项:
$ docker run --rm -ti f2bcff49ac09 sh
/ # env
HOSTNAME=7bc772fd0f56
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
$ # Note no secret in the above output
答案 2 :(得分:3)
我认为新的(17.05)docker功能多阶段构建(https://docs.docker.com/engine/userguide/eng-image/multistage-build/)减轻了关于简单地使用--build-arg的这些(有效)问题。
FROM mybuildertools
ADD my-git-creds /root/.ssh
RUN git clone git@bitbucket.org:example/foo /src
FROM mybuildertools
COPY --from=0 /src /src
RUN ...build /src with no git credentials ending up in final image...
不幸的是,除非你拥有&#34; my-git-creds&#34;否则它似乎不是允许后续重建的简单方法(例如更改Dockerfile中的构建步骤)。 。目录
答案 3 :(得分:2)
我写了https://github.com/abourget/secrets-bridge来解决构建时间机密问题。
它创建了一个可以作为构建参数传递的丢弃配置,在构建过程中,它将连接到主机并获取机密,使用它们,然后您可以终止主机桥。即使build-args被保存在某个地方,它们也会在服务器退出时变得无用。
服务器支持SSH代理转发,通过TLS websocket通信进行隧道传输。它也适用于Windows!
希望这有帮助。