- Using AWS Lambda functions with Docker containers - Fri, May 12 2023
- A Go AWS SDK example - Fri, Nov 11 2022
- Getting started with Jenkins - Tue, Aug 16 2022
Instance Metadata Service
Accessing metadata from a running EC2 instance is possible using either of the following methods:
- IMDSv1
- IMDSv2
IMDS stands for the Instance Metadata Service. The methods, as you would expect, differ slightly; IMDSv1 uses a request/response method, whereas IMDSv2 is session-oriented. The preferred method is IMDSv2, and AWS gently encourages you in this direction. The AWS SDK uses IMDSv2 calls by default, and you can use IAM condition keys in an IAM policy to enforce users to configure a new EC2 with IMDSv2 enabled. IMDSv1 is available for any legacy instances configured to use this service.
For the demo, you will launch an AWS Linux 2 AMI. As you go through the configuration screens for launching your EC2, stop and look at Step 3: Configure Instance Details:
Under Advanced Details, there are a couple of options to configure if you want to enable or disable metadata and the version. The version allows you to use both V1 and V2 or just V2, which requires a token. For the purposes of this setup, leave the Metadata token response hop limit as 1. We will add a small script to the User data section. AWS user data enables passing a command or script to your new instance at launch time. In this small example, we will update all installed packages to their latest versions. The main purpose here is to view the user data entry in metadata, which we will look at a bit later.
In the user data section, add:
#!/bin/bash yum update -y
You are not required to add sudo to the front of the command, as code run in user data is performed as root on launch. Skip through the rest of the options to launch your EC2.
Once your EC2 is up and running, select your server and click Connect.
On the first screen that appears, connect to instance: click Connect at the bottom of the screen to view your EC2 instance terminal from the browser.
Retrieving instance metadata
Instance metadata is only retrieved from the running instance and not by the console or the AWS CLI. To view instance metadata, you can only use the link-local address of 169.254.169.254 to access. Requests to the metadata via the URI are free, so there are no additional charges from AWS.
Using the curl tool on Linux or the PowerShell cmdlet Invoke-WebRequest on Windows, you will first create your token. A token is required, as IMDSv2 is a session-orientated request. The session token is used to define the session duration. This can be set from one second to six hours. During the specified time, you can use the same session token.
The request for the token must include a PUT request to initiate a session. The PUT request returns a token, which is required for subsequent GET requests. The token created is only valid for the existing EC2 instance.
The token you will create will be for the full duration of six hours. The header for the duration request is in seconds:
TOKEN=`curl --request PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
I've also echoed the value in the token variable, which you can see as a bunch of random characters.
Once you have created your token, you can then pass the token to the GET request. Adding /latest/meta-data/ to the end of the URI will view all categories (the --write-out option is used to allow a space after the returned value):
curl --write-out "\n" --request GET "http://169.254.169.254/latest/meta-data/ami-id" --header "X-aws-ec2-metadata-token: $TOKEN"
The screen should return the instance AMI ID to the screen.
Now that you have seen how to retrieve metadata, let's take a look at how to discover the available information.
Instance metadata categories
The instance metadata is divided into categories, such as host name, events, and security groups.
Make a request to http://169.254.169.254/latest/ without passing any additional data this time.
curl --write-out "\n" --request GET "http://169.254.169.254/latest/" --header "X-aws-ec2-metadata-token: $TOKEN"
Three headers are returned to the screen: dynamic, meta-data, and user-data. An HTTP header is an important part of the API request and response, as it represents the metadata associated with the API request and response.
Adding each data category to the end of the URI, after the latest, returns data within these categories. We can take a look at some of them, starting with user-data.
Add the word user-data to the end of the header http://169.254.169.254/latest/user-data. This is handy information to have, as you can see the data added to user-data when the instance was built:
curl --write-out "\n" --request GET "http://169.254.169.254/latest/user-data" --header "X-aws-ec2-metadata-token: $TOKEN"
Change the URI and replace user-data with meta-data, http://169.254.169.254/latest/meta-data. When it is run inside the curl command, a list is returned with over 20 options available to query. Under meta-data, you can easily obtain instance ID, region, and network information. I won't list them all; instead, I'll refer you to the AWS documentation, which provides the options and some details about each.
EC2 instances include dynamic data, the last one in the list we've come to. Dynamic data contains information about the instance identity documents. The types of information included in dynamic data are account ID, region, and certificates. To view this document, add the URI to your curl command again:
curl --write-out "\n" --request GET "http://169.254.169.254/latest/dynamic/instance-identity/document" --header "X-aws-ec2-metadata-token: $TOKEN"
With the document details, as we can see from the screen shot, we are provided a great amount of high-level information about our EC2.
Subscribe to 4sysops newsletter!
Conclusion
EC2 metadata is a useful, convenient way to obtain information about our EC2 instance from the running instance. Should we need to create a dynamic script to run on several EC2 instances, we know we can reference metadata and pass these details to the script. Being able to pass instance id, region, and such to an AWS CLI command without hard coding provides great flexibility. In addition, this information can be obtained without the need for access keys, so there is the added security of not having to store access keys in plain text on disk. Plus, you are able to set a duration for the length of time required to view metadata.
Is there a way to retrieve the metadata version number via CLI?