如何在AWS的STS连接与S3连接中刷新令牌?解决boto3跨账号复制对象时的ExpiredToken错误
解决STS凭证过期导致长时间S3复制失败的问题
嘿,我完全懂你遇到的麻烦——STS临时凭证默认只有1小时有效期,这种耗时数小时的复制操作肯定会碰上图中的ExpiredToken错误。RefreshableCredentials正是为这种场景设计的,它能自动在凭证快过期时重新获取新凭证,让你的S3操作全程都用有效凭证。
先简单说下RefreshableCredentials的核心逻辑
它本质是一个自动刷新的凭证管理器:你只需要告诉它怎么获取新凭证,以及凭证的过期时间,它就会在凭证即将失效时(默认提前几分钟)自动调用你的刷新函数,更新凭证信息。这样你的S3客户端就不用手动处理凭证过期的问题了。
完整代码示例(修改后的版本)
下面是调整后的代码,直接替换你原来的逻辑即可:
import boto3 from botocore.credentials import RefreshableCredentials from botocore.session import Session def get_refreshable_sts_credentials(): """获取STS临时凭证,返回符合RefreshableCredentials要求的格式""" sts_client = boto3.client('sts') assumed_role_response = sts_client.assume_role( RoleArn="arn:aws:iam::目标账号ID:role/你的角色名称", # 替换成实际的Role ARN RoleSessionName="cross_acct_s3_copy_session", # 如果你的角色允许,可以设置最长12小时的会话有效期(默认1小时) # DurationSeconds=43200 ) credentials = assumed_role_response['Credentials'] # 必须返回这四个字段:access_key, secret_key, token, expiry_time(ISO格式) return { "access_key": credentials['AccessKeyId'], "secret_key": credentials['SecretAccessKey'], "token": credentials['SessionToken'], "expiry_time": credentials['Expiration'].isoformat() } def main(): # 创建可自动刷新的凭证对象 refreshable_creds = RefreshableCredentials.create_from_metadata( metadata=get_refreshable_sts_credentials(), # 初始凭证 refresh_using=get_refreshable_sts_credentials, # 刷新时调用的函数 method="sts-assume-role" # 凭证获取方式标识(可自定义) ) # 创建botocore会话并绑定刷新凭证 botocore_session = Session() botocore_session._credentials = refreshable_creds # 基于botocore会话创建boto3会话,后续所有客户端都会自动用刷新后的凭证 boto3_session = boto3.Session(botocore_session=botocore_session) # 获取S3客户端,这个客户端会自动处理凭证刷新 s3_client = boto3_session.client('s3') # 执行你的长时间复制操作,比如批量复制对象 # 示例:复制单个对象 # s3_client.copy_object( # Bucket="目标账号的S3桶名", # CopySource={"Bucket": "源账号的S3桶名", "Key": "源对象键"}, # Key="目标对象键" # )
关键注意事项
- 角色权限配置:确保你的STS角色不仅允许被当前账号assume,还拥有源S3桶的读取权限和目标S3桶的写入权限。另外,如果想延长会话有效期(最长12小时),需要在IAM角色的设置里调整
MaxSessionDuration参数。 - 凭证格式要求:
get_refreshable_sts_credentials返回的字典必须包含指定的四个键,尤其是expiry_time需要是ISO格式的字符串,这样凭证管理器才能准确判断刷新时机。 - 客户端复用:所有需要使用跨账号凭证的服务客户端(比如S3、EC2等)都要从同一个boto3会话创建,这样它们都会共享自动刷新的凭证。
内容的提问来源于stack exchange,提问作者Nakano
相关产品推荐
相关产品推荐

