如何使用联合账户上传文件至带公开策略的S3存储桶
解决联合账户上传文件到S3存储桶的问题
核心问题梳理
- 当前S3桶策略仅开放了公共读取权限(
s3:GetObject),完全未配置上传相关权限,这是无法上传的直接原因。 - 联合账户确实无法获取长期Access Key/Secret Key,必须依赖临时凭证或环境自动授权的方式操作。
具体解决方案
方案1:调整S3桶策略(允许公开上传,注意安全风险)
若你的业务场景允许公开上传文件,可修改桶策略添加s3:PutObject权限,修改后的策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPublicRead", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<my-bucket-name>/*" }, { "Sid": "AllowPublicUpload", "Effect": "Allow", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::<my-bucket-name>/*" } ] }
注意:公开上传会允许任何人往桶内传文件,可能带来存储成本浪费、垃圾文件堆积甚至安全风险,非必要不建议采用此方案。
方案2:给联合账户关联的IAM角色添加S3上传权限(推荐)
联合账户通常通过IAM角色授权,只需给当前使用的角色添加上传权限即可:
- 找到你联合账户对应的IAM角色(即登录后实际使用的角色)
- 给该角色附加如下权限策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject" ], "Resource": "arn:aws:s3:::<my-bucket-name>/*" } ] }
- 修改boto3代码,删除手动指定密钥的部分,boto3会自动从环境中获取联合账户的临时凭证:
import boto3 # 无需手动创建带密钥的session,直接获取S3资源 s3 = boto3.resource('s3') txt_data = b'This is the content of the file uploaded from python boto3 asdfasdf' object = s3.Object('<bucket_name>', 'file_uploaded_by_boto3.txt') result = object.put(Body=txt_data)
此方式安全性最高,仅你的联合账户角色拥有上传权限,不会公开开放桶的写入能力。
方案3:使用预签名URL上传
若无法修改IAM角色或桶策略,可让拥有该桶权限的用户生成预签名URL,你通过此URL直接上传:
- 有权限的用户运行以下代码生成预签名URL:
import boto3 s3 = boto3.client('s3') url = s3.generate_presigned_url( 'put_object', Params={'Bucket': '<my-bucket-name>', 'Key': 'file_uploaded_by_boto3.txt'}, ExpiresIn=3600 # URL有效期1小时,可按需调整 )
- 你拿到URL后,用requests库直接上传:
import requests txt_data = b'This is the content of the file uploaded from python boto3 asdfasdf' response = requests.put(url, data=txt_data) print(response.status_code) # 返回200即为上传成功
内容的提问来源于stack exchange,提问作者EverythingZen
相关产品推荐
相关产品推荐

