UPDATE: AWS added a way to see the regional status to the ec2 api. “aws ec2 describe-regions” now returns the “OptInStatus”. See https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-regions.html
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).
import boto3 from botocore.exceptions import ClientError default_sts = boto3.client('sts') def region_is_available(region): # Older version of boto3 may need endpoint_url too. regional_sts = boto3.client('sts', region_name=region) try: regional_sts.get_caller_identity() return True except ClientError as e: # Default should always work, do not catch its errors default_sts.get_caller_identity() return False
If you have a known working region, and are sure that you have the right IAM permissions, you can also use
import boto3 default_ec2 = boto3.client('ec2') enabled_regions = set(r['RegionName'] for r in ec2.describe_regions()['Regions']) def region_is_available(region): 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.
Paul C
Hi,
Looks like this workaround appears to have broken since upgrading botocore to anything higher than version 1.13.1 when your using Assume Role not Access/Secret keys
Ben Bridts
Hi Paul,
AWS added a native way to see the regional status to the ec2 api. “aws ec2 describe-regions” returns the “OptInStatus”.
See https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-regions.html
Kind regards,
Ben