A little more than a month ago, the new AWS region in Hong Kong, ap-east-1, became available. This is the first region that you have to enable before you can use it and that can lead to some unexpected problems, if you have a piece of code that gets a list of regions from somewhere else.
After seeing a possible solution on StackOverflow, we did some research and came up with this piece of (python) code to check if a certain region is enabled or not (except if you’re using one of the China regions).
from botocore.exceptions import ClientError
default_sts = boto3.client('sts')
# Older version of boto3 may need endpoint_url too.
regional_sts = boto3.client('sts', region_name=region)
except ClientError as e:
# Default should always work, do not catch its errors
If you have a known working region, and are sure that you have the right IAM permissions, you can also use
default_ec2 = boto3.client('ec2')
enabled_regions = set(r['RegionName'] for r in ec2.describe_regions()['Regions'])
return region in enabled_regions
But if you only need to check one region, and/or do not want to rely on ec2 (and IAM), the sts calls may be safer.
The reason that we’re using
sts.get_caller_identity in the first example, is that it behaves a bit differently than other api calls. We suspected this might be a good fit, because it’s an api that you can use even if you don’t have any other permissions. To confirm it would be able to detect a disabled region, we ran some tests and looked at the Exceptions that were thrown. We considered the following situations:
- A region can be enabled or disabled using the account:EnableRegion and account:DisableRegion actions.
- A region can also be restricted with an IAM Policy.
- Not all services are available in all regions. Even some STS actions can be turned off on a regional basis
For our use case we want to be able to detect the first situation, independent of the other setting. So we tested all combinations and put that in the following graph.
One thing to keep in mind is that we tested this with the GovCloud, China and ap-northeast-1 regions not linked to our account. If you do have access to those, we recommend confirming that the behaviour does not change.
As you can see,
get-caller-identity works in every enabled region, even if the STS endpoint is disabled, or an IAM policy denies the action and it fails with the same error in every region (except China) if the region is disabled.
If you use another API you can’t distinguish between an enabled and disabled region if the service is not available in that region (which may or may not be a problem, depending on your use case). You also need to put some extra logic to make the distinction between an action that was denied and a region that’s completely disabled. Furthermore, even the exceptions thrown when the region is not available differ between regions, and can even differ between APIs.
Of course we are always looking for a better solution, and hope that there will be either an api to check the status of a region or a consitent exception for this kind of errors.
Until that happens, the code and graph above, should help figure out when something fails because it tries to access a disabled region.