为什么不建议在DOCKERFILE中使用ARG来传递秘密?

时间:2015-11-10 01:14:55

标签: docker credentials dockerfile

http://docs.docker.com/engine/reference/builder/#arg中,它建议秘密不通过ARGS传递。

  

注意:建议不要使用构建时变量来传递github密钥,用户凭据等秘密。

什么时候秘密通过构建时变量传递到危险之中?

4 个答案:

答案 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

但是,commentedSteve 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重申:

  

构建时环境变量:构建时环境变量不是为处理机密而设计的。由于缺乏其他选择,人们计划将其用于此目的。为了防止给人以适合保密的印象,我们决定故意不加密这些变量。

9176 comments中所述:

  

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!

希望这有帮助。