如何复用AWS STS AssumeRole的MFA TokenCode批量获取多账号会话?
单MFA验证码批量获取多AWS账号AssumeRole会话
问题背景
使用boto3遍历多个AWS账号,通过AssumeRole获取会话,对应的IAM策略要求MFA验证。现有代码会为每个账号单独执行AssumeRole并传入MFA码,但每次AssumeRole成功后,该MFA码就无法再次使用,必须等待30秒获取新码,效率极低。而AWS控制台仅在登录时要求MFA,切换角色无需重复验证,因此希望实现用单个MFA码完成所有账号的AssumeRole操作。
试错发现:同一个MFA码可重复用于失败的AssumeRole请求(如权限不足报错),但一旦某次AssumeRole成功,该码立即失效。
基础代码如下:
session = boto3.Session( aws_access_key_id=#####, aws_secret_access_key=##### ) sts_client = session.client('sts') assumed_role = sts_client.assume_role( RoleArn=f'arn:aws:iam::#####:role/#####', RoleSessionName=f'#####', SerialNumber='arn:aws:iam::#####:mfa/#####', TokenCode=mfa_code ) credentials = assumed_role['Credentials'] assumed_session = boto3.Session( aws_access_key_id=credentials['AccessKeyId'], aws_secret_access_key=credentials['SecretAccessKey'], aws_session_token=credentials['SessionToken'] )
解决方案
核心思路是先通过MFA获取已验证的临时基础会话凭证,之后用该凭证发起所有AssumeRole请求,无需重复传入MFA码,和AWS控制台的逻辑一致。
步骤1:获取带MFA验证的基础临时凭证
调用sts.get_session_token接口,传入MFA信息,获取已完成MFA验证的临时凭证。这个凭证的有效期最长为12小时,期间可用于多次AssumeRole操作。
步骤2:用已验证的凭证创建会话,批量执行AssumeRole
基于上述临时凭证创建boto3会话,后续所有AssumeRole请求都使用该会话的STS客户端,无需再提供MFA参数。
修改后的代码示例
# 1. 用长期密钥创建初始会话 initial_session = boto3.Session( aws_access_key_id=#####, aws_secret_access_key=##### ) # 2. 获取带MFA验证的临时基础凭证 sts_initial = initial_session.client('sts') mfa_verified_creds = sts_initial.get_session_token( SerialNumber='arn:aws:iam::#####:mfa/#####', TokenCode=mfa_code )['Credentials'] # 3. 创建已验证的基础会话 verified_session = boto3.Session( aws_access_key_id=mfa_verified_creds['AccessKeyId'], aws_secret_access_key=mfa_verified_creds['SecretAccessKey'], aws_session_token=mfa_verified_creds['SessionToken'] ) # 4. 遍历账号批量执行AssumeRole,无需再传MFA码 account_roles = [ {'role_arn': 'arn:aws:iam::account1:role/your-role', 'session_name': 'session-account1'}, {'role_arn': 'arn:aws:iam::account2:role/your-role', 'session_name': 'session-account2'}, # 更多账号角色... ] sts_verified = verified_session.client('sts') assumed_sessions = [] for role in account_roles: try: assumed_role = sts_verified.assume_role( RoleArn=role['role_arn'], RoleSessionName=role['session_name'] ) assumed_session = boto3.Session( aws_access_key_id=assumed_role['Credentials']['AccessKeyId'], aws_secret_access_key=assumed_role['Credentials']['SecretAccessKey'], aws_session_token=assumed_role['Credentials']['SessionToken'] ) assumed_sessions.append(assumed_session) print(f"成功获取账号{role['role_arn'].split(':')[4]}的会话") except Exception as e: print(f"获取账号{role['role_arn'].split(':')[4]}会话失败: {str(e)}")
原理说明
get_session_token返回的临时凭证已完成MFA验证,AWS会标记该会话的身份已通过MFA校验,后续基于该会话的AssumeRole请求无需再次验证MFA。- 原代码中每次
AssumeRole直接用长期密钥发起,必须每次传入MFA码,且成功后AWS会消耗该MFA码(防止重复使用),导致无法复用。
内容的提问来源于stack exchange,提问作者Bryant Eastham
相关产品推荐
相关产品推荐

