Docker和保护密码

ant*_*tor 139 security build docker

我最近一直在尝试使用Docker构建一些服务来解决这个问题,并且一直在唠叨我的一直是将密码放在Dockerfile中.我是一名开发人员,因此在源代码中存储密码感觉就像一拳.这应该是一个问题吗?关于如何在Dockerfiles中处理密码有什么好的约定吗?

Ben*_*ley 84

绝对是一个值得关注的问题.Dockerfiles通常签入存储库并与其他人共享.另一种方法是在运行时提供任何凭据(用户名,密码,令牌,任何敏感的)作为环境变量.这可以通过-e参数(对于CLI上的单个变量)或--env-file参数(对于文件中的多个变量)来实现docker run.阅读此内容,了解使用docker-compose的环境.

使用--env-file绝对是一个更安全的选择,因为这可以防止出现ps在日志中或在日志中使用的秘密set -x.

然而,env vars也不是特别安全.它们是可见的docker inspect,因此可供任何可以运行docker命令的用户使用.(当然,任何有权访问docker主机的用户也都有root.)

我首选的模式是使用包装器脚本作为ENTRYPOINTCMD.包装器脚本可以在运行时首先将秘密从外部位置导入容器,然后执行应用程序,提供机密.具体的机制根据您的运行时环境而有所不同.在AWS中,您可以结合使用IAM角色,密钥管理服务和S3将加密的密钥存储在S3存储桶中.像HashiCorp Vault或者credstash这样的东西是另一种选择.

AFAIK没有使用敏感数据作为构建过程的一部分的最佳模式.事实上,我对这个话题有一个问题.您可以使用docker-squash从图像中删除图层.但是为了这个目的,Docker中没有本机功能.

您可能会发现shykes 对容器中配置的评论很有用.

  • 我担心如果你的密码是env变量,它会出现在`docker inspect`中. (4认同)
  • @GrandOpener仅适用于有攻击者使用您的系统的情况.如果我将一个泊坞窗图像推送到存储库,并且它被其他人拉出,我不在乎他们是否在他们自己的系统上有sudo但是我非常关心他们是否在env中看到了不再存在的秘密. (4认同)
  • 环境参数的问题之一不是它们本质上被复制到所有后代进程,包括孙进程吗?因此,docker 容器中使用的脚本或插件会意外访问这些密码吗? (3认同)

the*_*ide 67

我们的团队避免将凭据放在存储库中,这意味着他们不被允许进入Dockerfile.我们在应用程序中的最佳实践是使用来自环境变量的信用.

我们解决这个问题docker-compose.

在其中docker-compose.yml,您可以指定包含容器的环境变量的文件:

 env_file:
- .env
Run Code Online (Sandbox Code Playgroud)

确保添加.env.gitignore,然后在.env文件中设置凭据,如:

SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd
Run Code Online (Sandbox Code Playgroud)

.env文件存储在本地或存储在团队其他成员可以获取的安全位置.

请参阅:https://docs.docker.com/compose/environment-variables/#/the-env-file

  • 如果您愿意,也可以在没有.env文件的情况下执行此操作.只需在docker-compose.yml文件中使用[environment属性](https://docs.docker.com/compose/compose-file/#environment)即可._"只有一个键的环境变量被解析为它们在机器上运行的值,这对于秘密或特定于主机的值很有帮助."_ (12认同)
  • Docker 团队本身不鼓励使用环境变量,因为可以通过 /proc/<pid>/environ 和 docker inspect 看到 env var。它只会混淆获得 root 访问权限的攻击者获取凭据的方式。当然,CVS 永远不应该跟踪凭据。我想防止 root 用户获得信任的唯一方法是从加密文件中读取 Web 应用程序内的凭据(希望它不会更新其 proc 环境文件),解密过程安全地要求输入密码。我想我会尝试使用坟墓:https://github.com/dyne/Tomb (5认同)
  • @theUtherSide 如果您能为我们提供您所指的“方式/工具”的任何示例或链接,那就太好了。 (4认同)

Hea*_* QC 33

Docker现在(版本1.13或17.06及更高版本)支持管理机密信息.这是一个概述和更详细的文档

kubernetesDCOS中存在类似的特征

  • 这是一个很好的答案,但需要更多的信息来链接到答案本身. (10认同)
  • 这仅适用于docker swarm,对吧? (7认同)
  • 如果它仅适用于群体,则不确定这是否是可接受的答案.许多人不使用群,但仍需要传递秘密. (5认同)
  • 是的,您需要设置一个群组来使用Docker机密 (2认同)

TvE*_*TvE 9

您永远不应该向容器添加凭据,除非您可以向任何可以下载图像的人广播信用.特别是,执行和ADD creds以后RUN rm creds不安全,因为creds文件保留在中间文件系统层的最终图像中.任何有权访问图像的人都可以轻松提取图像.

我看到的典型解决方案,当你需要信誉来检查依赖关系时,就是使用一个容器来构建另一个容器.即,通常您的基础容器中有一些构建环境,您需要调用它来构建您的应用程序容器.所以简单的解决方案是添加您的应用程序源,然后添加RUN构建命令.如果你需要信用,这是不安全的RUN.相反,您所做的是将源放入本地目录,运行(如在docker run)容器中执行构建步骤,将本地源目录作为卷挂载,并将creds注入或挂载为另一个卷.构建步骤完成后,只需通过简单ADD的本地源目录(现在包含构建的工件)来构建最终容器.

我希望Docker增加一些功能来简化这一切!

更新:看起来前进的方法将是嵌套构建.简而言之,dockerfile将描述用于构建运行时环境的第一个容器,然后描述可以将所有部分组装到最终容器中的第二个嵌套容器构建.这样构建时间的东西不在第二个容器中.这是一个Java应用程序,您需要JDK来构建应用程序,但只需要JRE来运行它.有很多提议正在讨论中,最好从https://github.com/docker/docker/issues/7115开始,并按照一些替代提案的链接.


Mal*_*ous 6

使用环境变量的一种替代方法是使用卷以使容器中的主机目录可访问,如果环境变量过多,则可能会造成混乱。

如果将所有凭据作为文件放在该文件夹中,则容器可以读取文件并根据需要使用它们。

例如:

$ 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
Run Code Online (Sandbox Code Playgroud)

许多程序可以从一个单独的文件中读取其凭据,因此您可以将程序指向其中一个文件。


Mur*_*mel 6

仅运行时解决方案

docker-compose 还提供了非 swarm 模式解决方案(自 v1.11: Secrets using bind mounts)。

这些秘密被/run/secrets/docker-compose挂载为下面的文件。这在运行时(运行容器)解决了问题,但不能在构建时(构建映像)解决,因为/run/secrets/它不是在构建时挂载的。此外,此行为取决于使用 docker-compose 运行容器。


例子:

文件

FROM alpine
RUN cat /run/secrets/password
CMD sleep inifinity
Run Code Online (Sandbox Code Playgroud)

docker-compose.yml

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

secrets:
  password:
    file: password.txt
Run Code Online (Sandbox Code Playgroud)

要构建,请执行:

docker-compose up -d
Run Code Online (Sandbox Code Playgroud)

进一步阅读: