跨账号Lambda问题:Account A的Lambda获取Account B的EC2实例无结果
问题描述:
我尝试用Account A中的Lambda函数获取Account B里的EC2实例,但遇到了问题:
- Lambda代码能正常运行,Assume Role操作成功返回了访问密钥和会话令牌
- Account B确实有运行中的EC2实例
- 调用
ec2.describe_instance_status()后返回{'InstanceStatuses': []},没有实例数据 - Account B的IAM角色已经附加了
AmazonEC2ReadOnlyAccess策略,信任关系配置了arn:aws:iam::ACCOUNT_A:role/role-name_ACCOUNT_A
相关代码:
import json import boto3 from collections import OrderedDict from pprint import pprint import time from time import sleep from datetime import date import datetime def lambda_handler(event, context): # Assume Role To connect to other Account sts_connection = boto3.client('sts') acct_b = sts_connection.assume_role( RoleArn="arn:aws:iam::ACCOUNT_B:role/role_name_account_B", RoleSessionName="cross_acct_lambda" ) ACCESS_KEY = acct_b['Credentials']['AccessKeyId'] SECRET_KEY = acct_b['Credentials']['SecretAccessKey'] SESSION_TOKEN = acct_b['Credentials']['SessionToken'] # create service client using the assumed role credentials, e.g. S3 ec2 = boto3.client( "ec2", aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY, aws_session_token=SESSION_TOKEN, ) status = ec2.describe_instance_status() pprint(status) return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') }
执行结果:
Response:
{"statusCode": 200, "body": "\"Hello from Lambda!\""}
函数日志:START RequestId: ZZZZZZZZZZZZZZZZZZ Version: $LATEST {'InstanceStatuses': []}
排查方案:
我来帮你一步步梳理可能的原因:
先明确
describe_instance_status的特性
这个API并不是返回所有EC2实例,它只返回处于运行中(running)状态且已经生成了状态检查数据的实例。如果你的实例是刚启动的,或者处于停止(stopped)/终止(terminated)状态,这个API会直接返回空列表。
建议先换成describe_instances()测试,这个API会返回所有状态的实例,能帮你快速确认是否真的有权限访问到实例:# 替换原来的status = ec2.describe_instance_status() instances = ec2.describe_instances() pprint(instances)检查区域是否匹配
你的Lambda函数默认运行的区域,和Account B中EC2实例所在的区域是不是同一个?boto3的EC2客户端如果没有指定region_name参数,会使用Lambda执行环境的默认区域。如果实例在别的区域,自然查不到任何数据。
可以在创建EC2客户端时明确指定区域,比如实例在us-east-1:ec2 = boto3.client( "ec2", region_name="us-east-1", # 替换为你的实例所在区域 aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY, aws_session_token=SESSION_TOKEN, )验证信任关系和权限的准确性
- 确认Account B中IAM角色的信任关系里,Account A的角色ARN完全正确:账号ID、角色名有没有拼写错误?比如是不是误写成了用户ARN而不是角色ARN?
- 虽然附加了
AmazonEC2ReadOnlyAccess,但可以临时在Lambda里加日志打印调用的区域,或者用AssumeRole返回的凭证在本地测试(比如用aws configure set临时配置这些凭证,然后运行aws ec2 describe-instances --region xxx),确认权限是否真的生效。
再次确认Account B的实例状态
登录Account B的EC2控制台,确认实例确实处于running状态,没有被停止或终止,而且系统状态和实例状态检查已经显示正常。
内容的提问来源于stack exchange,提问作者Rajiv Nakkana

