The region in which an EC2 instance is located is exposed via EC2 Instance Metadata.
Part of instance metadata is Instance Identity Documents. Specifically, the instance-identity/document
endpoint is a dynamic data category that contains instance attributes such as the instanceId, privateIp, instanceType. And most relevantly the instance's region.
We can query the instance identity document via the 169.254.169.254 link-local address. (This only works on EC2 instances):
[ec2-user ~]$ curl http://169.254.169.254/latest/dynamic/instance-identity/document
{
"devpayProductCodes" : null,
"marketplaceProductCodes" : null,
"accountId" : "123456789012",
"imageId" : "ami-0d5d9d301c853a04a",
"availabilityZone" : "us-east-2c",
"ramdiskId" : null,
"kernelId" : null,
"privateIp" : "10.10.130.176",
"version" : "2017-09-30",
"region" : "us-east-2",
"pendingTime" : "2019-10-14T14:06:42Z",
"architecture" : "x86_64",
"billingProducts" : null,
"instanceId" : "i-050a5175c97088b9b",
"instanceType" : "t3.micro"
}
The response's JSON payload includes a region
key which can be extracted. We can use the Python requests
library to query the endpoint and then use requests
's built-in .json
method to deserialize the data for filtering. (The requests library is the de-facto standard for making HTTP requests in Python: requests - PyPI)
If requests
isn't currently on the local system, it can be installed via pip:
pip install requests
A simple function to get an EC2 instance's region:
import requests
def get_instance_region():
instance_identity_url = "http://169.254.169.254/latest/dynamic/instance-identity/document"
session = requests.Session()
r = requests.get(instance_identity_url)
response_json = r.json()
region = response_json.get("region")
return(region)
The region alone is filtered utilizing this function:
>>> region = get_instance_region()
>>> print(region)
us-east-2
We can also add some exception handling and an explicitly defined timeout to the function to handle situations where the metadata service isn't availabe, possibly because the local system isn't an EC2 instance. The final version of the function:
import requests
import sys
from requests.packages.urllib3 import Retry
def get_instance_region():
instance_identity_url = "http://169.254.169.254/latest/dynamic/instance-identity/document"
session = requests.Session()
retries = Retry(total=3, backoff_factor=0.3)
metadata_adapter = requests.adapters.HTTPAdapter(max_retries=retries)
session.mount("http://169.254.169.254/", metadata_adapter)
try:
r = requests.get(instance_identity_url, timeout=(2, 5))
except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError) as err:
print("Connection to AWS EC2 Metadata timed out: " + str(err.__class__.__name__))
print("Is this an EC2 instance? Is the AWS metadata endpoint blocked? (http://169.254.169.254/)")
sys.exit(1)
response_json = r.json()
region = response_json.get("region")
return(region)