AWS S3 PutObject CLI执行正常但Boto3调用报AccessDenied问题
错误原因定位
- 未显式指定S3客户端的服务区域:如果目标S3桶不在AWS默认的us-east-1区域,手动构造S3客户端时未指定
region_name参数会导致请求签名区域不匹配,触发AccessDenied。AWS CLI会自动适配桶所在区域,因此可以正常执行。 - 上传操作缺少ACL相关权限:Boto3的
upload_file方法默认会尝试设置对象ACL,若跨账号角色仅被授予s3:PutObject权限、未被授予s3:PutObjectAcl权限就会被拦截。AWS CLI的aws s3 cp默认不会主动设置额外ACL,因此不会触发该校验。 - 硬编码的我方凭证与配置文件凭证不一致:若代码中填写的
OUR-ACCOUNT-ACCESSKEY、OUR-SECRET对应的IAM账号,不在跨账号角色的信任关系允许列表中,即使AssumeRole接口暂时返回凭证,实际资源操作时也会被权限校验拦截。 - 临时凭证参数传递错误:若获取AssumeRole返回结果时,
SessionToken等关键字段取值错误、未正确传递到S3客户端构造参数中,会导致请求使用无效凭证。
对应解决方案
- 构造S3客户端时显式指定目标桶所在区域,代码示例:
# 替换为实际桶所在的AWS区域,比如ap-southeast-1、cn-northwest-1等 s3_client = boto3.client( 's3', aws_access_key_id=credentials['AccessKeyId'], aws_secret_access_key=credentials['SecretAccessKey'], aws_session_token=credentials['SessionToken'], region_name='目标桶所属区域' )
- 上传时显式指定ACL,避免触发额外权限校验,代码示例:
# 若需要客户侧桶所有者拥有对象权限,指定bucket-owner-full-control;无需额外ACL则指定private response = s3_client.upload_file( filename, bucketname, objectname, ExtraArgs={'ACL': 'bucket-owner-full-control'} )
也可以在客户侧的跨账号角色权限策略中,新增s3:PutObjectAcl权限解决该问题。
- 核对代码中硬编码的我方IAM凭证与
~/.aws/credentials中[client]配置的凭证完全一致,确认该账号在跨账号角色的信任策略中被允许调用AssumeRole接口。 - 打印AssumeRole返回的凭证字段,校验
AccessKeyId、SecretAccessKey、SessionToken三个字段均被正确取值和传递。
简化替代方案
直接复用本地AWS配置文件中的client-car配置,和CLI逻辑完全一致,避免手动AssumeRole的参数错误:
import boto3 session = boto3.Session(profile_name='client-car') s3_client = session.client('s3') # 后续直接调用upload_file方法即可
内容的提问来源于stack exchange,提问作者AlMacOwl
相关产品推荐
相关产品推荐

