GitLab流水线中旧版AWS CLI无法定位凭证问题求助
问题背景
同样的GitLab流水线任务,使用搭载新版AWS CLI(aws-cli/1.25.32)的镜像时,能正常通过aws sts get-caller-identity验证;但使用旧版AWS CLI(aws-cli/1.16.181)的镜像时,会报错Unable to locate credentials。两者均无本地~/.aws/credentials和~/.aws/config文件,且已手动清空AWS_ACCESS_KEY_ID等常规凭证环境变量。
任务定义如下:
aws-credentials: image: name: ${BASE_IMAGE_REGISTRY_PATH} stage: credentials-check script: - cat ~/.aws/credentials || true - cat ~/.aws/config || true - aws --version - unset AWS_ACCESS_KEY_ID - unset AWS_SECRET_ACCESS_KEY - unset AWS_SESSION_TOKEN - unset AWS_ACCESS_KEY - unset AWS_SECRET_KEY - aws sts get-caller-identity
核心原因
旧版AWS CLI(及对应botocore版本)不支持GitLab流水线默认的Web Identity凭证自动加载机制:
当GitLab流水线配置了AWS角色关联(比如在AWS托管的Runner上运行,或通过GitLab的IAM角色集成),会自动注入两个关键环境变量:
AWS_ROLE_ARN:要扮演的IAM角色ARNAWS_WEB_IDENTITY_TOKEN_FILE:包含Web Identity令牌的文件路径
新版AWS CLI(botocore 1.13+,对应AWS CLI v1.17+)会自动识别这两个变量,调用STS服务获取临时凭证;但旧版botocore(如失败镜像中的1.12.171)没有实现这个自动加载逻辑,因此即使这两个变量存在,旧版CLI也不会使用,最终导致凭证找不到。
验证步骤
在失败的流水线任务中添加以下脚本,确认这两个环境变量是否存在:
# 检查GitLab注入的Web Identity相关变量 echo "AWS_ROLE_ARN: $AWS_ROLE_ARN" echo "AWS_WEB_IDENTITY_TOKEN_FILE: $AWS_WEB_IDENTITY_TOKEN_FILE" ls -l "$AWS_WEB_IDENTITY_TOKEN_FILE" || true
如果输出能看到有效的ARN和存在的令牌文件,即可确认是旧版CLI不支持该机制导致的问题。
解决方案
方案1:升级AWS CLI版本(推荐)
直接使用支持Web Identity自动加载的新版AWS CLI镜像,这也是已验证可行的方式,确保镜像中的AWS CLI版本不低于v1.17(或botocore版本不低于1.13)。
方案2:手动获取临时凭证(兼容旧版CLI)
如果必须使用旧版CLI,可在脚本中手动调用STS命令获取临时凭证,再设置对应的环境变量:
aws-credentials: image: name: ${BASE_IMAGE_REGISTRY_PATH} stage: credentials-check script: - cat ~/.aws/credentials || true - cat ~/.aws/config || true - aws --version - unset AWS_ACCESS_KEY_ID - unset AWS_SECRET_ACCESS_KEY - unset AWS_SESSION_TOKEN - unset AWS_ACCESS_KEY - unset AWS_SECRET_KEY # 手动通过Web Identity获取临时凭证 - | if [ -n "$AWS_ROLE_ARN" ] && [ -f "$AWS_WEB_IDENTITY_TOKEN_FILE" ]; then CREDS=$(aws sts assume-role-with-web-identity \ --role-arn "$AWS_ROLE_ARN" \ --role-session-name "gitlab-ci-session" \ --web-identity-token file://"$AWS_WEB_IDENTITY_TOKEN_FILE") export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | jq -r '.Credentials.AccessKeyId') export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | jq -r '.Credentials.SecretAccessKey') export AWS_SESSION_TOKEN=$(echo "$CREDS" | jq -r '.Credentials.SessionToken') fi - aws sts get-caller-identity
注意:需确保镜像中安装了
jq工具,用于解析STS返回的JSON结果;如果没有jq,也可以用grep+awk等工具提取凭证信息。
内容的提问来源于stack exchange,提问作者Rob Wilkinson

