Parsing Meta-Data on an EC2 Instance

Quite often you'll need the ability to run scripts on an EC2 instance based on information that can be easily accessible from the EC2's meta-data (http://169.254.169.254/latest/meta-data)

For example, maybe you want the instance id. This can be found via:


> curl -s http://169.254.169.254/latest/meta-data/instance-id

This would return the instance id with something like:


i-06c3bxxxxxxxxx

However other items like availability zones are buried in latest/dynamic/instance-identity/document


curl -s http://169.254.169.254/latest/dynamic/instance-identity/document

This returns a json object like:

{
"accountId" : "xxxxxxxxxxx",
"architecture" : "x86_64",
"availabilityZone" : "us-east-1a",
"billingProducts" : null,
"devpayProductCodes" : null,
"marketplaceProductCodes" : null,
"imageId" : "ami-xxxxxxxxx",
"instanceId" : "i-06c3bxxxxxxxxx",
"instanceType" : "t3.large",
"kernelId" : null,
"pendingTime" : "2021-03-18T00:27:16Z",
"privateIp" : "10.10.1.50",
"ramdiskId" : null,
"region" : "us-east-1",
"version" : "2017-09-30"
}

As you can see, this also includes the instance-id but if we want any data out of it we'll need to parse it.  Luckily you have all sorts of options.  You can use bash scripts with commands like awk but I find those fairly messy and hard to read.  My preference is either python or for this use case, I pref jq.

Let's take a look at both.

Python Example

We'll start off with a python example.  Most Linux AMI's have python already installed.  AWS uses python scripts for a lot of it's initial loading, so in general, we shouldn't need to install it. 


# get the full document
document="$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document)"
# print it out so we can see it
echo $document

# now get the region, az and instance from the document
region=`echo $document | python -c "import json,sys; print json.loads(sys.stdin.read())['region']"`
az=`echo $document | python -c "import json,sys; print json.loads(sys.stdin.read())['availabilityZone']"`
instance_id=`echo $document | python -c "import json,sys; print json.loads(sys.stdin.read())['instanceId']"`

# print them out to verify them
echo $region
echo $az
echo $instance_id

jq Example

 

jq isn't typically installed by default but with a little yum install you can quickly add it.


# requirements install jq
yum install jq -y

# get the region
region=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region)
# get the instance
instance_id=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .instance_id)

Use Cases

There are several use cases for getting these variables, such as add the information to logs or making updates to the EC2 instance itself. 

For example if you wanted to use an EC2 instance as a NAT instance or a VPN instance, you need to disable the Source to Destination check.  This can be accomplished via the AWS console but it can also been done from the AWS cli from within the EC2 instance itself.  To run the command the EC2 role associated with the instance will need the proper rights to modify the instance.  You will also need the instance-id and the region which we can get from the script above.  And then you can use the following command to disable the source to destination checks.


# requirements... make sure the ec2 instance has the appropriate permissions on the box
> aws ec2 modify-instance-attribute --instance-id=${instance_id} --no-source-dest-check --region=${region}