You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用boto3通过资源ID(非ARN)获取AWS资源标签?

仅通过AWS资源ID获取标签的解决方案(无需为每个服务单独创建客户端)

我通过boto3调用CostExplorer的get_cost_and_usage_with_resources方法收集成本统计数据,该方法会返回资源的ID/ARN、使用量及成本信息。现在需要将这些数据与资源标签关联,但Resource Groups Tagging API的get_resources方法仅接受ARN列表,不支持直接传入资源ID(比如EC2卷ID:vol-0053852a4f079axxx),又不想为每个AWS服务单独创建boto3客户端,该如何处理?

尝试过的代码及报错

我直接用资源ID调用get_resources方法,代码如下:

import boto3

tag_client = boto3.client('resourcegroupstaggingapi')

def get_resource_tags(resource_arn):
    response = tag_client.get_resources(
        ResourceARNList=[resource_arn]
    )
    print(response)

get_resource_tags("vol-0e6abc422806b0xxx")

得到报错:

botocore.errorfactory.InvalidParameterException: An error occurred (InvalidParameterException) when calling the GetResources operation: vol-0e6abc422806b0xxx is not a valid AmazonResourceName (ARN)

解决方案:通过资源ID构造ARN后调用Tagging API

AWS资源的ARN有固定格式,只要能从资源ID前缀识别出资源类型,就能拼接出对应的ARN,再用Tagging API获取标签。

1. 核心思路

  • 从资源ID前缀判断资源类型(比如vol-对应EBS卷,i-对应EC2实例)
  • 结合当前AWS账号ID、资源所在区域,构造符合格式的ARN
  • 将构造好的ARN传入get_resources方法获取标签

2. 实现代码

import boto3

def get_account_id():
    """获取当前AWS账号ID"""
    sts_client = boto3.client('sts')
    return sts_client.get_caller_identity()['Account']

def get_default_region():
    """获取当前boto3会话的默认区域"""
    session = boto3.Session()
    return session.region_name

def construct_arn(resource_id, resource_region=None):
    """根据资源ID构造ARN,支持指定资源所在区域"""
    account_id = get_account_id()
    region = resource_region or get_default_region()

    # 根据ID前缀匹配资源类型,可扩展更多资源类型
    if resource_id.startswith('vol-'):
        return f"arn:aws:ec2:{region}:{account_id}:volume/{resource_id}"
    elif resource_id.startswith('i-'):
        return f"arn:aws:ec2:{region}:{account_id}:instance/{resource_id}"
    elif resource_id.startswith('sg-'):
        return f"arn:aws:ec2:{region}:{account_id}:security-group/{resource_id}"
    elif resource_id.startswith('s3://'):
        # S3桶的ARN格式特殊,移除前缀后直接拼接
        bucket_name = resource_id.replace('s3://', '')
        return f"arn:aws:s3:::{bucket_name}"
    elif resource_id.startswith('rds-'):
        return f"arn:aws:rds:{region}:{account_id}:db:{resource_id}"
    elif resource_id.startswith('lambda-'):
        return f"arn:aws:lambda:{region}:{account_id}:function:{resource_id}"
    else:
        raise ValueError(f"无法识别资源ID {resource_id} 的类型,请扩展资源类型判断逻辑")

def get_resource_tags(resource_id, resource_region=None):
    """通过资源ID获取标签"""
    tag_client = boto3.client('resourcegroupstaggingapi')
    try:
        arn = construct_arn(resource_id, resource_region)
        response = tag_client.get_resources(ResourceARNList=[arn])
        
        # 提取标签字典
        if response['ResourceTagMappingList']:
            return {tag['Key']: tag['Value'] for tag in response['ResourceTagMappingList'][0]['Tags']}
        return {}
    except Exception as e:
        print(f"获取资源 {resource_id} 标签失败: {str(e)}")
        return {}

# 测试:传入EBS卷ID
print(get_resource_tags("vol-0e6abc422806b0xxx"))

3. 注意事项

  • 区域问题:如果资源不在当前默认区域,需要从CostExplorer的响应中获取资源所在区域(get_cost_and_usage_with_resources返回结果通常包含Region字段),传入construct_arn的resource_region参数。
  • 特殊资源格式:S3桶、CloudFront分发等资源的ARN格式有差异,需要单独处理,可根据需求扩展construct_arn中的判断逻辑。
  • 权限:确保当前IAM角色/用户拥有sts:GetCallerIdentity(获取账号ID)和tag:GetResources(获取标签)的权限。

内容的提问来源于stack exchange,提问作者Anton Serozhechkin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:23:13