为什么不建议DOCKERFILE中的ARG用于传递机密?

为什么不建议DOCKERFILE中的ARG用于传递机密?,docker,credentials,dockerfile,Docker,Credentials,Dockerfile,在中,建议不要通过ARGS传递机密 注意:不建议使用构建时变量传递机密,如github密钥、用户凭据等 什么时候通过构建时变量传递的秘密处于危险状态?2018年8月更新: 现在您有了docker构建--secret id=mysecret,src=/secret/file 见“” 2017年1月更新: Docker(swarm)1.13已经发布 然而,正如: […]secret命令只帮助swarm用户,而不是一个更通用的解决方案(就像连接持久卷一样)。 你如何管理你的秘密(它们是什么以及谁有权访

在中,建议不要通过ARGS传递机密

注意:不建议使用构建时变量传递机密,如github密钥、用户凭据等

什么时候通过构建时变量传递的秘密处于危险状态?

2018年8月更新:

现在您有了docker
构建--secret id=mysecret,src=/secret/file

见“”

2017年1月更新:

Docker(swarm)1.13已经发布

然而,正如:

[…]secret命令只帮助swarm用户,而不是一个更通用的解决方案(就像连接持久卷一样)。
你如何管理你的秘密(它们是什么以及谁有权访问它们)是非常依赖于系统的,取决于你拼凑成“平台”的付费和/或操作系统的部分。
随着Docker公司开始提供一个平台,正如Hashicorp将Vault集成到Atlas中一样,他们的第一个实现是基于swarm的,这一点我并不感到惊讶——这是有道理的

实际上,秘密的传递方式超出了docker run的范围

AWS通过角色和策略来授予/拒绝权限和SDK来实现这类功能。
Chef使用加密数据包和加密“引导”进行身份验证。
K8S在1.13版中发布了自己的版本。
我相信mesos会及时添加类似的实现

这些实现似乎分为两大阵营

  • 通过“平台”提供的卷挂载或(厨师/docker secret/k8s)传递机密
  • 传递凭据以与外部服务对话以在启动时获取内容(iam/credstash/etc)

原始答复:2015年11月

这是在(docker 1.92015年11月)中引入的

生成环境在中间continer的命令字符串之前,用于帮助缓存查找。
它也有助于构建跟踪,但从传递构建时机密的角度来看,这也会降低该功能的安全性

重申:

构建时环境变量:构建时环境变量不是为处理机密而设计的。由于缺乏其他选项,人们正计划使用它们。为了避免给人留下适合机密的印象,我们决定在此过程中故意不加密这些变量

如中所述:

env变量是传递秘密的错误方式。我们不应该试图重新发明轮子,提供一个现成的、有缺陷的安全分发机制

当您将密钥存储在环境中时,您很容易意外地将其公开--这正是我们想要避免的:

  • 考虑到环境对流程是隐式可用的,跟踪访问和内容如何公开即使不是不可能,也是非常困难的
  • 让应用程序获取整个环境并打印出来是非常常见的,因为它对调试非常有用,甚至可以作为错误报告的一部分发送。有太多的秘密泄露给PagerDuty,以至于他们有一个完善的内部流程将其从基础架构中清除
  • 环境变量被传递到子进程,这允许意外访问,并打破了最小特权原则。想象一下,作为应用程序的一部分,您调用第三方工具执行某些操作,突然第三方工具可以访问您的环境,天知道它将如何处理它
  • 对于崩溃的应用程序来说,将环境变量存储在日志文件中以供以后调试是很常见的。这意味着磁盘上的明文机密
  • 将秘密放入环境变量中很快就会变成部落知识。新工程师不知道它们在那里,也不知道在处理环境变量时应该小心(将它们过滤到子进程中,等等)
总的来说,env变量中的秘密违反了最小意外原则,这是一种不好的做法,最终会导致秘密泄漏


原因很简单,只要在图像上运行
history
,任何人都可以看到秘密的价值

以docker文件为例:

FROM alpine

ARG secret

RUN echo "${secret}"
(很好,很简单,只是为了说明如何使用秘密。)

然后我们构建它
$docker build--build arg secret=S3CR3T-

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
以及如何取回“秘密”的示例(请在第一行查找
| 1 secret=
):

如果您已在本地构建映像或从注册表中提取映像,则会出现这种情况

如果你的目标是将构建时间秘密隐藏在运行容器中,那么使用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
我认为新的(17.05)docker特性Multi-stage Builds()减轻了关于简单使用--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...
不幸的是,除非您有“my git creds”目录,否则似乎没有一种简单的方法来允许后续重建(例如Dockerfile中构建步骤的更改)。

我写这篇文章是为了解决构建时机密问题

它创建一个一次性配置,您可以将其作为构建参数传递,在构建过程中,它将连接到主机并获取机密,使用它们,然后您可以终止主机网桥。即使构建参数保存在某个位置,它们在服务器退出时也会变得无用

服务器支持SSH代理转发,通过TLS websocket通信进行隧道传输。它也在Windows上工作


希望这能有所帮助。

当您以明文形式将它们输入终端时?这是否也适用于将文件键入环境变量并将其传递给环境变量?我认为键入文件很好。有些人会放置他们的密钥(例如
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...