将AWS凭据传递给Docker容器的最佳方法是哪种?

sur*_*ade 68 amazon-web-services docker docker-compose

我在Amazon EC2上运行docker-container.目前,我已将AWS Credentials添加到Dockerfile.你能告诉我最好的办法吗?

Vor*_*Vor 76

最好的方法是使用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来访问这些环境变量.

  • 在本地开发/测试期间有没有一种好的方法可以在不影响生产安全性的情况下做到这一点?我希望确保图像能够在不完全部署的情况下工作. (24认同)
  • 简单地说(对于那些以与我相同的方式获得此答案的人);在EC2上运行的Docker容器将继承与主机实例相同的角色。(当我的容器中的AWS CLI命令神秘地工作时,尽管没有凭据传递给我,我需要这样的“ ELI5”!) (7认同)
  • 从本地配置文件中获取键值并分配给环境变量以进行开发的简便方法(如https://cameroneckelberry.co/words/getting-aws-credentials-into-a-docker-container-without-hardcoding中的建议-it):“ aws --profile默认配置获取aws_access_key_id” (4认同)
  • 我发布的带有环境变量的替代方法在开发人员/本地环境中效果很好。 (3认同)
  • 我想知道这是不是一个错字,但我需要输入`AWS_SECRET_ACCESS_KEY`,而不是`AWS_SECRET_KEY`,无论如何你的回答非常有帮助.谢谢. (3认同)
  • 虽然通过环境变量传递密钥和秘密绝对是最简单的,但不鼓励这样做,因为您现在将依赖于长期凭据。IMO,整个讨论凸显了在本地使用 SDK、开发期间以及在您可能使用的任何服务中的实例之一上的生产环境中所出现的可怕脱节(AWS SDK 文档中根本没有解决) 。至少可以说,这是不幸的。我的意思是,只要阅读解决方法就可以看出这是多么糟糕。本地、本地 docker、容器化部署……全都不同……嗯 (3认同)

BMi*_*tch 43

自从提出此问题以来,Docker发生了许多变化,因此,本文尝试了一个更新的答案。

首先,特别是对于已经在云内部运行的容器使用AWS凭证,按照Vor的建议使用IAM角色是一个非常好的选择。如果可以的话,请在他的答案中再加上一个加一个,然后跳过其余的内容。


一旦您开始在云外部运行事物或拥有其他类型的秘密,建议您针对两个关键位置存储秘密:

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

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


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

选项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://... ...
Run Code Online (Sandbox Code Playgroud)

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

DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .
Run Code Online (Sandbox Code Playgroud)

选项C:在没有Swarm Mode或其他编排的单个节点上运行时,可以将凭据作为只读卷安装。访问此凭据需要与在docker外部对同一凭据文件的访问相同的权限,因此,与没有docker的情况相比,这没有比这更好或更糟的了。最重要的是,当您检查容器,查看日志或将映像推送到注册表服务器时,此文件的内容应该不可见,因为在每种情况下该卷均超出该范围。这确实要求您将凭据复制到Docker主机上,与容器的部署分开。(请注意,任何能够在该主机上运行容器的人都可以查看您的凭据,因为对Docker API的访问权限是主机上的root用户,而root用户可以查看任何用户的文件。如果您不信任主机上具有root用户的用户, ,

对于docker run,它看起来像:

docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image
Run Code Online (Sandbox Code Playgroud)

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

version: '3'
services:
  app:
    image: your_image
    volumes:
    - $HOME/.aws/credentials:/home/app/.aws/credentials:ro
Run Code Online (Sandbox Code Playgroud)

选项D:借助编组工具(如Swarm Mode和Kubernetes),我们现在拥有比容量更好的秘密支持。使用“群存模式”时,文件在管理器文件系统上被加密(尽管解密密钥也经常存在于此,从而无需管理员输入解密密钥即可重新启动管理器)。更重要的是,机密仅发送给需要该机密的工作程序(使用该机密运行一个容器),它仅存储在该工作程序的内存中,而不是磁盘上,并且通过tmpfs作为文件注入到容器中安装。swarm之外的主机上的用户无法将该秘密直接安装到自己的容器中,但是,通过对docker API的开放访问,他们可以从节点上正在运行的容器中提取秘密,因此,再次限制谁有权访问该秘密。 API。从撰写的内容来看,这种秘密注入看起来像:

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

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服务器即可。如果机密不起作用或很快就会过期,那么这将降低从机密中删除机密的风险。https://www.vaultproject.io/docs/secrets/aws/index.html记录了适用于Vault的AWS的特定功能

  • 我在 Mac 上,我将容器路径更改为 root 而不是 `/home/app/` 并且它有效。`docker run -v $HOME/.aws/credentials:/root/.aws/credentials:ro -it -p 8080:8080 imageName:tagName` 你知道我如何访问该根目录吗?我使用了 `docker exec imageId ls -la` 但我在那里找不到我的 aws 凭证文件 (4认同)

pra*_*afi 8

另一种方法是将密钥从主机传递到docker容器。您可以在docker-compose文件中添加以下行。

services:
  web:
    build: .
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
Run Code Online (Sandbox Code Playgroud)

  • 当我使用 AWS_DEFAULT_REGION 时,我遇到了无法找到默认区域的异常。我的搜索导致 https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html 指定 AWS_REGION 环境变量,这对我有用。 (7认同)
  • 正确的区域环境变量是 AWS_REGION。请参阅 /sf/ask/3090638771/ (5认同)
  • 请检查提到`AWS_DEFAULT_REGION`的官方文档 https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html (4认同)
  • 您是否需要使用“export AWS_ACCESS_KEY_ID =“myaccesskeyid”导出AWS_ACCESS_KEY_ID等?AWS_ACCESS_KEY_ID 环境变量对我来说是未定义的。 (3认同)
  • 如果您使用临时凭证,那么您可能还需要 `AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}` (2认同)

0x9*_*x90 6

即使我的凭证是由aws-oktasaml2aws设置的,以下一行对我也适用:

$ docker run -v$HOME/.aws:/root/.aws:ro \
            -e AWS_ACCESS_KEY_ID \
            -e AWS_CA_BUNDLE \
            -e AWS_CLI_FILE_ENCODING \
            -e AWS_CONFIG_FILE \
            -e AWS_DEFAULT_OUTPUT \
            -e AWS_DEFAULT_REGION \
            -e AWS_PAGER \
            -e AWS_PROFILE \
            -e AWS_ROLE_SESSION_NAME \
            -e AWS_SECRET_ACCESS_KEY \
            -e AWS_SESSION_TOKEN \
            -e AWS_SHARED_CREDENTIALS_FILE \
            -e AWS_STS_REGIONAL_ENDPOINTS \
            amazon/aws-cli s3 ls 
Run Code Online (Sandbox Code Playgroud)

请注意,对于高级用例,您可能需要允许rw(读写)权限,因此在安装卷时忽略ro(只读)限制.aws-v$HOME/.aws:/root/.aws:ro


Art*_*ski 5

另一种方法是在docker-compose.yaml中创建临时只读卷。AWS CLI和SDK(例如boto3或Java的AWS开发工具包等)正在default文件中寻找配置~/.aws/credentials文件。

如果要使用其他配置文件,则只需要在运行docker-compose命令之前导出AWS_PROFILE变量

export AWS_PROFILE=some_other_profile_name

version: '3'

services:
  service-name:
    image: docker-image-name:latest
    environment:
      - AWS_PROFILE=${AWS_PROFILE}
    volumes:
      - ~/.aws/:/root/.aws:ro
Run Code Online (Sandbox Code Playgroud)

在此示例中,我在docker上使用了root用户。如果您正在使用其他用户,只需更改/root/.aws到用户主目录

:ro -代表只读docker卷

当文件中有多个配置~/.aws/credentials文件并且还使用MFA 时,这将非常有用。当您要在具有IAM角色的ECS上部署docker-container之前对其进行本地测试时,这也很有帮助。

  • 在 Windows 上,.aws` 目录位于“%UserProfile%\.aws”。所以我假设您必须将: `- ~/.aws/:/root/.aws:ro` 更改为 `- %UserProfile%\.aws:/root/.aws:ro` (2认同)