AWS CodeBuild中Boto3的凭据来源及跨账号ECS部署问题
解决AWS CodeBuild跨账号ECS部署的凭据问题
看起来你碰到了跨账号部署时凭据不生效的典型问题,我来一步步拆解原因和解决方案:
为什么printenv看不到你设置的AWS环境变量?
如果你的临时凭证是在Python脚本里通过os.environ设置的,那这些变量只会存在于当前Python进程的内存中,不会传递到外部的shell环境。而printenv是一个独立的shell命令,自然读取不到Python进程内部的环境变量。
如果想在shell层面看到这些变量,你需要在shell脚本里直接设置(比如用export命令),而不是在Python代码里设置。
为什么资源还是创建在dev账号?
核心问题是Boto3没有使用你获取的临时跨账号凭据,而是继续使用CodeBuild默认的执行角色(dev账号的)。这和Boto3的凭据优先级规则有关:
Boto3会按以下顺序查找凭据,找到第一个有效就用:
- 调用
boto3.client()时显式传入的aws_access_key_id/aws_secret_access_key/aws_session_token参数 - 系统环境变量中的
AWS_ACCESS_KEY_ID等 ~/.aws/credentials文件里的配置- IAM角色(比如CodeBuild的执行角色,通过实例元数据服务自动获取)
所以如果你的临时凭据没有被Boto3读到,或者优先级低于默认的执行角色,就会继续用dev账号的权限创建资源。
最可靠的解决方案
方案1:显式在Boto3客户端调用中传入凭据(推荐)
这是最不容易出错的方式,直接跳过所有凭据优先级规则,强制使用跨账号临时凭证:
import boto3 # 先通过dev账号的角色获取prod账号的临时凭据 sts_client = boto3.client('sts') assumed_role_resp = sts_client.assume_role( RoleArn="arn:aws:iam::PROD_ACCOUNT_ID:role/YourCrossAccountRole", RoleSessionName="CodeBuildCrossAccountDeploy" ) temp_creds = assumed_role_resp['Credentials'] # 显式传入临时凭据创建ECS客户端 ecs_client = boto3.client( 'ecs', aws_access_key_id=temp_creds['AccessKeyId'], aws_secret_access_key=temp_creds['SecretAccessKey'], aws_session_token=temp_creds['SessionToken'] ) # 接下来用这个ecs_client操作prod账号的资源就没问题了 ecs_client.register_task_definition(...) ecs_client.update_service(...)
方案2:在shell层面设置环境变量,让Python继承
如果你不想每个客户端都显式传参,可以在buildspec.yml的shell命令里先获取临时凭证并设置环境变量,再执行Python脚本:
version: 0.2 phases: build: commands: # 通过AWS CLI获取跨账号临时凭证,用jq解析出密钥 - | ASSUMED_ROLE=$(aws sts assume-role \ --role-arn arn:aws:iam::PROD_ACCOUNT_ID:role/YourCrossAccountRole \ --role-session-name CodeBuildCrossAccountDeploy) export AWS_ACCESS_KEY_ID=$(echo "$ASSUMED_ROLE" | jq -r '.Credentials.AccessKeyId') export AWS_SECRET_ACCESS_KEY=$(echo "$ASSUMED_ROLE" | jq -r '.Credentials.SecretAccessKey') export AWS_SESSION_TOKEN=$(echo "$ASSUMED_ROLE" | jq -r '.Credentials.SessionToken') # 这里执行printenv就能看到这些变量了 - printenv | grep AWS_ # 运行你的部署脚本,Python会自动继承这些环境变量 - python your_deployment_script.py
这种方式下,Boto3会优先读取环境变量里的临时凭证,而不是用CodeBuild的执行角色。
额外检查:跨账号角色的信任策略
别忘了确认prod账号里的目标角色的信任策略是否允许dev账号的CodeBuild执行角色扮演它:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::DEV_ACCOUNT_ID:role/codebuild-YourProjectRole" }, "Action": "sts:AssumeRole" } ] }
内容的提问来源于stack exchange,提问作者Robin




