如何用Boto3和Python创建AWS MFA授权会话并跨账号获取EC2实例
Based on your scenario with three linked AWS accounts (main for IAM management, acc1/acc2 for EC2), here's a step-by-step implementation to meet your requirements:
Prerequisites
- Boto3 installed (
pip install boto3) - MFA enabled for your main account IAM user
- Cross-account roles created in
aws_acc_1andaws_acc_2that trust your main account (with a condition requiring MFA) - Your main account user has permission to assume these cross-account roles
Step 1: Configure AWS Credentials & Config Files
First, set up your .aws/credentials and .aws/config files to streamline profile management:
.aws/credentials
Store your main account's IAM user credentials here:
[aws_acc_main] aws_access_key_id = YOUR_MAIN_ACCOUNT_ACCESS_KEY aws_secret_access_key = YOUR_MAIN_ACCOUNT_SECRET_KEY
.aws/config
Define profiles for each sub-account, linking to the cross-account role and MFA device:
[profile aws_acc_1] role_arn = arn:aws:iam::YOUR_ACC1_ACCOUNT_ID:role/CrossAccountEC2ReadOnlyRole source_profile = aws_acc_main mfa_serial = arn:aws:iam::YOUR_MAIN_ACCOUNT_ID:mfa/YourMainUserMFA region = us-east-1 # Replace with your target region [profile aws_acc_2] role_arn = arn:aws:iam::YOUR_ACC2_ACCOUNT_ID:role/CrossAccountEC2ReadOnlyRole source_profile = aws_acc_main mfa_serial = arn:aws:iam::YOUR_MAIN_ACCOUNT_ID:mfa/YourMainUserMFA region = us-west-2 # Replace with your target region
Note: The cross-account roles should have a trust policy requiring MFA, and attach the AmazonEC2ReadOnlyAccess managed policy (or a custom policy with ec2:DescribeInstances permission).
Step 2: Create MFA-Authorized Session (test1.py)
This script handles MFA authentication and returns a Boto3 session using the assumed cross-account role:
import boto3 from botocore.exceptions import ClientError def get_assumed_role_session(account_profile: str, mfa_token: str): """Create a Boto3 session using an MFA-authenticated cross-account role""" try: # Initialize base session from the profile base_session = boto3.Session(profile_name=account_profile) sts_client = base_session.client('sts') # Extract role ARN and MFA serial from profile config profile_config = base_session._session.get_scoped_config() role_arn = profile_config['role_arn'] mfa_serial = profile_config['mfa_serial'] # Assume the role with MFA validation sts_response = sts_client.assume_role( RoleArn=role_arn, RoleSessionName=f"MFA-Session-{account_profile}", SerialNumber=mfa_serial, TokenCode=mfa_token ) # Create session with temporary credentials assumed_session = boto3.Session( aws_access_key_id=sts_response['Credentials']['AccessKeyId'], aws_secret_access_key=sts_response['Credentials']['SecretAccessKey'], aws_session_token=sts_response['Credentials']['SessionToken'], region_name=profile_config.get('region', 'us-east-1') ) return assumed_session except ClientError as e: print(f"Error assuming role: {e.response['Error']['Message']}") raise
Step 3: Fetch EC2 Instances from Sub-Accounts (test2.py)
Use the authenticated session to retrieve and display EC2 instances from both sub-accounts:
from test1 import get_assumed_role_session def list_ec2_instances(assumed_session): """List all EC2 instances in the assumed session's region""" ec2_client = assumed_session.client('ec2') try: response = ec2_client.describe_instances() for reservation in response['Reservations']: for instance in reservation['Instances']: print(f"Instance ID: {instance['InstanceId']}") print(f" State: {instance['State']['Name']}") print(f" Instance Type: {instance['InstanceType']}") print(f" Launch Time: {instance['LaunchTime']}\n") except ClientError as e: print(f"Error fetching EC2 instances: {e.response['Error']['Message']}") raise if __name__ == "__main__": # Get MFA token from user input mfa_token = input("Enter your MFA token (6 digits): ").strip() # Fetch instances from aws_acc_1 print("=== EC2 Instances in aws_acc_1 ===") acc1_session = get_assumed_role_session('aws_acc_1', mfa_token) list_ec2_instances(acc1_session) # Fetch instances from aws_acc_2 print("\n=== EC2 Instances in aws_acc_2 ===") acc2_session = get_assumed_role_session('aws_acc_2', mfa_token) list_ec2_instances(acc2_session)
Key Notes
- Temporary credentials from
assume_roleare valid for up to 12 hours (adjust with theDurationSecondsparameter if needed) - Add error handling for edge cases (invalid MFA token, missing permissions, etc.)
- The main account only needs IAM permissions to assume cross-account roles—no other service access is required
内容的提问来源于stack exchange,提问作者wafers

