将 AWS 凭证传递给 Docker 容器的最佳方式是什么?

新手上路,请多包涵

我在 Amazon EC2 上运行 docker-container。目前我已将 AWS 凭证添加到 Dockerfile。你能告诉我最好的方法吗?

原文由 suraj chopade 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 722
2 个回答

最好的方法是使用 IAM 角色并且根本不处理凭证。 (请参阅 http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html

可以从 http://169.254.169.254..... 检索凭证,因为这是一个私有 IP 地址,它只能从 EC2 实例访问。

所有现代 AWS 客户端库都“知道”如何从那里获取、刷新和使用凭证。所以在大多数情况下,你甚至不需要知道它。只需使用正确的 IAM 角色运行 ec2 即可。

作为一个选项,您可以在运行时将它们作为环境变量传递(即 docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage

您可以通过在终端运行 printenv 来访问这些环境变量。

原文由 Vor 发布,翻译遵循 CC BY-SA 4.0 许可协议

自从提出这个问题以来,Docker 发生了很多变化,所以这里尝试更新答案。

首先,特别是对于已经在云内部运行的容器上的 AWS 凭证,使用 Vor 建议 的 IAM 角色是一个非常好的选择。如果你能做到这一点,那么在他的答案中再加一加一并跳过其余部分。


一旦你开始在云之外运行东西,或者拥有不同类型的机密,我 建议不要 在两个关键位置存储机密:

  1. 环境变量:当这些在容器上定义时,容器内的每个进程都可以访问它们,它们可以通过 /proc 看到,应用程序可以将它们的环境转储到 stdout 并存储在日志中,最重要的是,它们出现在检查容器时的明文。

  2. 在镜像本身中:镜像通常被推送到许多用户具有拉取访问权限的注册表,有时不需要任何凭据来拉取镜像。即使您从一层中删除秘密,也可以使用常见的 Linux 实用程序(如 tar 反汇编该图像,并且可以从首次将其添加到图像的步骤中找到该秘密。


那么 Docker 容器中的秘密还有哪些其他选择呢?

选项 A: 如果您仅在构建映像期间需要此密钥,在构建开始之前无法使用该密钥,并且还没有访问 BuildKit 的权限,那么 多阶段构建 是最好的选择。您可以将秘密添加到构建的初始阶段,在那里使用它,然后将没有秘密的该阶段的输出复制到您的发布阶段,并且仅将该发布阶段推送到注册表服务器。这个秘密仍然在构建服务器上的图像缓存中,所以我倾向于仅将其用作最后的手段。

选项 B: 同样在构建期间,如果您可以使用在 18.09 中发布的 BuildKit,目前有 实验性功能 允许将秘密注入作为单个 RUN 行的卷挂载。该挂载不会写入映像层,因此您可以在构建期间访问该密钥,而不必担心它将被推送到公共注册表服务器。生成的 Dockerfile 如下所示:

 # syntax = docker/dockerfile:experimental
FROM python:3
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...

然后您使用 18.09 或更高版本中的命令构建它,例如:

 DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .

选项 C: 在单个节点上运行时,无需 Swarm 模式或其他编排,您可以将凭证挂载为只读卷。访问此凭据需要与您在 docker 之外对同一凭据文件具有相同的访问权限,因此与没有 docker 的情况相比,它没有更好或更差。最重要的是,当您检查容器、查看日志或将映像推送到注册表服务器时,该文件的内容不应该是可见的,因为在每种情况下该卷都在此之外。这确实需要您在 docker 主机上复制您的凭据,与容器的部署分开。 (请注意,任何能够在该主机上运行容器的人都可以查看您的凭据,因为对 docker API 的访问权限是主机上的 root 并且 root 可以查看任何用户的文件。如果您不信任主机上具有 root 的用户,那么不要给他们 docker API 访问权限。)

对于 docker run ,这看起来像:

 docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image

或者对于撰写文件,您将拥有:

 version: '3'
services:
  app:
    image: your_image
    volumes:
    - $HOME/.aws/credentials:/home/app/.aws/credentials:ro

选项 D: 使用 Swarm Mode 和 Kubernetes 等编排工具,我们现在拥有比卷更好的秘密支持。使用 Swarm 模式,文件在管理器文件系统上加密(尽管解密密钥通常也在那里,允许管理员在没有管理员输入解密密钥的情况下重新启动管理器)。更重要的是,秘密只发送给需要秘密的工作人员(运行具有该秘密的容器),它只存储在工作人员的内存中,而不是磁盘中,并且它作为文件注入到具有 tmpfs 的容器中山。 swarm 之外的主机上的用户不能直接将该秘密挂载到他们自己的容器中,但是,通过对 docker API 的开放访问,他们可以从节点上正在运行的容器中提取秘密,因此,再次限制谁可以访问API。从 compose 来看,这个秘密注入看起来像:

 version: '3.7'

secrets:
  aws_creds:
    external: true

services:
  app:
    image: your_image
    secrets:
    - source: aws_creds
      target: /home/user/.aws/credentials
      uid: '1000'
      gid: '1000'
      mode: 0700

您使用 docker swarm init 为单个节点打开集群模式,然后按照说明添加其他节点。您可以使用 docker secret create aws_creds $HOME/.aws/credentials 在外部创建密钥。然后使用 docker stack deploy -c docker-compose.yml stack_name 部署撰写文件。

我经常使用以下脚本对我的秘密进行版本控制: https ://github.com/sudo-bmitch/docker-config-update

选项 E: 存在其他管理机密的工具,我最喜欢的是 Vault ,因为它能够创建自动过期的限时机密。然后,每个应用程序都会获得自己的一组令牌来请求机密,这些令牌使他们能够在可以到达保险库服务器的情况下请求这些时间有限的机密。如果秘密从您的网络中取出,这会降低风险,因为它要么不起作用,要么很快就会过期。特定于 AWS for Vault 的功能记录在 https://www.vaultproject.io/docs/secrets/aws/index.html

原文由 BMitch 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题