【问题标题】:Pass AWS credentials (IAM role credentials) to code running in docker container将 AWS 凭证(IAM 角色凭证)传递给在 docker 容器中运行的代码
【发布时间】:2014-11-12 16:41:48
【问题描述】:

在 EC2 实例上运行代码时,您用来访问 AWS 资源的开发工具包会自动与 169.254.169.254 上的本地链接 Web 服务器对话,并获取与其他实例对话所需的 AWS 凭证(access_key、secret) AWS 服务。

还有其他选项,例如在 ENV 变量中设置凭据或将它们作为命令行参数传递...

这里的最佳做法是什么?我真的更喜欢让容器访问 169.254.169.254(通过路由请求),或者甚至更好地运行一个代理容器来模仿真实服务器在 169.254.169.254 的行为。

已经有解决方案了吗?

【问题讨论】:

    标签: amazon-web-services docker amazon-iam


    【解决方案1】:

    EC2 元数据服务通常可在 docker 中使用(除非您使用更自定义的网络设置 - 请参阅 this answer 的类似问题)。

    如果您的 docker 网络设置阻止它被访问,您可以在 Dockerfile 中使用 ENV 指令或在运行期间直接传递它们,但请记住,来自 IAM 角色的凭证会由 AWS 自动轮换。

    【讨论】:

    • 嗯,所以我想我的误解来自我对 boot2docker(在 Mac 上)的实验,其中网络尴尬或至少不同。所以基本上事情应该可以正常工作。嗯,我需要试试这个。
    • @Ali 在那里您可以看到它在 docker 中正常工作而无需将原始密钥发送到 boto ?
    • 我在使用此架构时遇到的一个问题(让容器内的 AWS SDK/CLI 访问 EC2 元数据端点以获取凭证)是我想要对容器将拥有的权限进行细粒度控制。一个容器可能只能写入 S3,而另一个我可能不想拥有任何 S3 权限,而只是让它发布到 SNS。这种设计意味着我需要向 EC2 添加权限超集,并且我的所有容器都将具有相同的权限。
    【解决方案2】:

    Amazon 确实有一些机制允许容器通过 SDK 访问 IAM 角色,并通过 ECS 代理容器或主机路由/转发请求。复制和粘贴的内容太多了,但使用--net host 是最不推荐的选项,因为没有额外的过滤器允许您的容器完全访问它的主机有权执行的任何操作。

    https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html

    declare -a ENVVARS
    declare AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
    get_aws_creds_local () {
       # Use this to get secrets on a non AWS host assuming you've set credentials via some mechanism in the past, and then don't pass in a profile to gitlab-runner because it doesn't see the ~/.aws/credentials file where it would look up profiles
       awsProfile=${AWS_PROFILE:-default}
       AWS_ACCESS_KEY_ID=$(aws --profile $awsProfile configure get aws_access_key_id)
       AWS_SECRET_ACCESS_KEY=$(aws --profile $awsProfile configure get aws_secret_access_key)
       AWS_SESSION_TOKEN=$(aws --profile $awsProfile configure get aws_session_token)
       
    }
    
    get_aws_creds_iam () {
      TEMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::123456789012:role/example-role" --role-session-name AWSCLI-Session)
      AWS_ACCESS_KEY_ID=$(echo $TEMP_ROLE | jq -r . Credentials.RoleAccessKeyID)
      AWS_SECRET_ACCESS_KEY=$(echo $TEMP_ROLE | jq -r . Credentials.RoleSecretKey)
      AWS_SESSION_TOKEN=$(echo $TEMP_ROLE | jq -r . Credentials.RoleSessionToken)
    }
    
    get_aws_creds_local
    
    get_aws_creds_iam
    
    ENVVARS=("AWS_ACCESS_KEY_ID=$ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY=$ACCESS_SECRET_ACCESS_KEY" "AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN")
    
    # passing creds into GitLab runner
     gitlab-runner exec docker stepName $(printf " --env %s" "${ENVVARS[@]}")
    
    # using creds with a docker container
    docker run -it --rm $(printf " --env %s" "${ENVVARS[@]}") amazon/aws-cli sts get-caller-identity
    

    【讨论】:

    • 你能举个小例子吗?我应该把--net host 部分放在哪里?
    • docker run 之后和您正在运行的容器名称之前的任何位置,例如 ubuntu 或 redis。
    • 我正在使用docker-in-docker,所以在这种情况下,这会起作用吗?
    • 您是否在 docker 中为 GitLab 运行器或类似或其他用例使用 docker?通过不添加 --net host,您的容器应该能够访问元数据 URL 以自动检索 IAM 实例凭证。
    • @dragon788 aws sts get-caller-identity
    猜你喜欢
    • 1970-01-01
    • 2018-01-07
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 2020-12-01
    相关资源
    最近更新 更多