在EC2实例上运行代码时,我用来访问AWS资源的SDK会自动与169.254.169.254
上的本地链接web服务器进行对话,并获取与其他AWS服务对话所需的实例AWS凭据(access_key,secret)。
还有其他选项,比如在环境变量中设置凭据或将其作为命令行参数传递。
这里的最佳做法是什么?我真的更喜欢让容器访问169.254.169.254
(通过路由请求),或者更好地运行一个模仿169.254.169.254
上真实服务器行为的代理容器。
已经有解决方案了吗?
EC2元数据服务通常可以从docker中获得(除非您使用更自定义的网络设置-请参阅类似问题的答案)。
如果您的docker网络设置阻止访问它,您可以在Dockerfile
中使用ENV
指令,或者在运行期间直接传递它们,但请记住,IAM角色的凭据由AWS自动轮换。
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