如何识别AWS中的禁用区域?

时间:2019-05-17 08:55:52

标签: python amazon-web-services boto

AWS会定期添加新区域。默认情况下,每个AWS账户中都会启用“旧”区域,而默认情况下,1禁用新区域。

我正在尝试使用以下Python(伪)代码扫描所有可用区域中的特定资源:

regions = boto3_session.get_available_regions('rds')
for region in regions:
    boto_rds_client = boto3_session.client('rds', region_name=region)
    r_paginator = boto_rds_client.get_paginator('describe_db_instances')
    for rdses in r_paginator.paginate():
        for rds in rdses['DBInstances']:
            do_stuff(rds)

但是,当访问“新”区域时,此操作失败,并显示了一个神秘的An error occurred (InvalidClientTokenId) when calling the DescribeDBInstances operation: The security token included in the request is invalid

其他服务因其他错误而失败:例如Lambda失败,An error occurred (UnrecognizedClientException) when calling the ListFunctions operation: The security token included in the request is invalid

如何识别区域是否启用?似乎没有API调用可以执行此操作...

2 个答案:

答案 0 :(得分:1)

我发现该API的一种极端情况是可以(滥用)来标识启用的区域:ec2:DescribeRegions API调用(可能还有其他未曾尝试过)在禁用区域中表现出略有不同的故障模式:

  • 呼叫成功,您就会知道该区域已启用

  • 呼叫失败,并显示UnauthorizedOperation错误。这表明您没有IAM权限,但是该区域已启用

  • 呼叫失败,AuthFailure。这表明该区域已禁用

以下代码成功过滤了我的测试用例中的区域:

def get_enabled_regions(boto3_session: boto3.Session, service: str) -> typing.Set[str]:
    regions = boto3_session.get_available_regions(service)
    enabled_regions = set()
    for region in regions:
        ec2_client = boto3_session.client('ec2', region_name=region)
        try:
            ec2_client.describe_regions()
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "AuthFailure":
                print(f"region {region} seems disabled, skipping")
                continue  # Account is disabled
            elif e.response['Error']['Code'] == "UnauthorizedOperation":
                print(f"region {region} seems enabled (but not sure)")
                pass  # Access denied is good: we have access to the region, just not to the ec2:DescribeRegions call
            else:
                raise
        enabled_regions.add(region)
    return enabled_regions

答案 1 :(得分:0)

我在这个问题上做了更多的工作,发现了一种较少依赖边缘情况的方式:使用sts:GetCallerIdentity调用。

ec2:DescribeRegions相比,它具有多个优点,因为该API始终处于启用状态(不受IAM限制)。您可以为某个区域禁用STS,但是即使这样,GetCallerIdentity仍然可以工作(仅禁用1临时证书的颁发)。

def get_enabled_regions(boto3_session: boto3.Session, service: str) -> typing.Set[str]:
    regions = boto3_session.get_available_regions(service)
    enabled_regions = set()
    for region in regions:
        sts_client = boto3_session.client('sts', region_name=region)
        try:
            sts_client.get_caller_identity()
            enabled_regions.add(region)
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "InvalidClientTokenId":
                # error code received when region is disabled
                print(f"region {region} is disabled")
                pass
            else:
                raise
    return enabled_regions
相关问题