Retrieve instance metadata
Because your instance metadata is available from your running instance, you do not need to use the Amazon EC2 console or the AWS CLI. This can be helpful when you're writing scripts to run from your instance. For example, you can access the local IP address of your instance from instance metadata to manage a connection to an external application.
Instance metadata is divided into categories. For a description of each instance metadata category, see Instance metadata categories.
To view all categories of instance metadata from within a running instance, get the data from the following IPv4 or IPv6 URIs. These IP addresses are link-local addresses and are valid only from the instance. For more information, see Link-local addresses.
IPv4
http://169.254.169.254/latest/meta-data/
IPv6
http://[fd00:ec2::254]/latest/meta-data/
Pricing
You are not billed for HTTP requests used to retrieve instance metadata and user data.
Considerations
To avoid problems with instance metadata retrieval, consider the following.
- Command format
-
The command format is different, depending on whether you use IMDSv1 or IMDSv2. By default, you can use both versions of the IMDS. To require the use of IMDSv2, see Use IMDSv2.
- (IMDSv2) If IMDSv2 is required, IMDSv1 does not work
-
To check whether IMDSv2 is required, select the instance to view its details. The value for IMDSv2 is either Required (you must use IMDSv2) or Optional (you can use either IMDSv2 or IMDSv1).
- (IMDSv2) Use /latest/api/token to retrieve the token
-
Issuing
PUT
requests to any version-specific path, for example/2021-03-23/api/token
, results in the metadata service returning 403 Forbidden errors. This behavior is intended. - IPv6 support
-
To retrieve instance metadata using IPv6 address, ensure that you enable and use
[fd00:ec2::254]
instead of the IPv4 address. The instance must be built on the AWS Nitro System and launched in a subnet that supports IPv6. - (Windows) Create custom AMIs using Windows Sysprep
-
To ensure that IMDS works when you launch an instance from a custom Windows AMI, the AMI must be a standardized image created with Windows Sysprep. Otherwise, the IMDS won't work. Form more information, see Create an AMI with Windows Sysprep.
- In a container environment, set the hop limit to 2
-
The AWS SDKs use IMDSv2 calls by default. If the IMDSv2 call receives no response, the SDK retries the call and, if still unsuccessful, uses IMDSv1. This can result in a delay, especially in a container environment. In a container environment, if the hop limit is 1, the IMDSv2 response does not return because going to the container is considered an additional network hop. To avoid the process of falling back to IMDSv1 and the resultant delay, in a container environment we recommend that you set the hop limit to 2. For more information, see Configure the instance metadata options.
- Metadata version
-
To avoid having to update your code every time Amazon EC2 releases a new instance metadata build, we recommend that you use
latest
in the path, and not the version number.
Responses and error messages
All instance metadata is returned as text (HTTP content type
text/plain
).
A request for a specific metadata resource returns the appropriate value, or a
404 - Not Found
HTTP error code if the resource is not available.
A request for a general metadata resource (the URI ends with a /) returns a list
of available resources, or a 404 - Not Found
HTTP error code if there
is no such resource. The list items are on separate lines, terminated by line feeds
(ASCII 10).
For requests made using Instance Metadata Service Version 2, the following HTTP error codes can be returned:
-
400 - Missing or Invalid Parameters
– ThePUT
request is not valid. -
401 - Unauthorized
– TheGET
request uses an invalid token. The recommended action is to generate a new token. -
403 - Forbidden
– The request is not allowed or the IMDS is turned off.
Examples for IMDSv2
Run the following examples on your Amazon EC2 instance to retrieve the instance metadata for IMDSv2.
On Windows instances, you can use Windows PowerShell or you can install cURL or wget. If you install a third-party tool on a Windows instance, ensure that you read the accompanying documentation carefully, as the calls and the output might be different from what is described here.
Examples
- Get the available versions of the instance metadata
- Get the top-level metadata items
- Get the values for metadata items
- Get the list of available public keys
- Show the formats in which public key 0 is available
- Get public key 0 (in the OpenSSH key format)
- Get the subnet ID for an instance
- Get the instance tags for an instance
Get the available versions of the instance metadata
This example gets the available versions of the instance metadata. Each version refers to an instance metadata build when new instance metadata categories were released. The instance metadata build versions do not correlate with the Amazon EC2 API versions. The earlier versions are available to you in case you have scripts that rely on the structure and information present in a previous version.
Get the top-level metadata items
This example gets the top-level metadata items. For more information about the items in the response, see Instance metadata categories.
Note that tags are included in this output only if you've allowed access. For more information, see Allow access to tags in instance metadata.
Get the values for metadata items
These examples get the values of some of the top-level metadata items that were obtained in the preceding example. These requests use the stored token that was created using the command in the previous example. The token must not be expired.
Get the list of available public keys
This example gets the list of available public keys.
Show the formats in which public key 0 is available
This example shows the formats in which public key 0 is available.
Get public key 0 (in the OpenSSH key format)
This example gets public key 0 (in the OpenSSH key format).
Get the subnet ID for an instance
This example gets the subnet ID for an instance.
Get the instance tags for an instance
These examples access the tags for an instance. You must allow access to tags before you can use these examples.
Examples for IMDSv1
Run the following examples on your Amazon EC2 instance to retrieve the instance metadata for IMDSv1.
On Windows instances, you can use Windows PowerShell or you can install cURL or wget. If you install a third-party tool on a Windows instance, ensure that you read the accompanying documentation carefully, as the calls and the output might be different from what is described here.
Examples
- Get the available versions of the instance metadata
- Get the top-level metadata items
- Get the values for metadata items
- Get the list of available public keys
- Show the formats in which public key 0 is available
- Get public key 0 (in the OpenSSH key format)
- Get the subnet ID for an instance
- Get the instance tags for an instance
Get the available versions of the instance metadata
This example gets the available versions of the instance metadata. Each version refers to an instance metadata build when new instance metadata categories were released. The instance metadata build versions do not correlate with the Amazon EC2 API versions. The earlier versions are available to you in case you have scripts that rely on the structure and information present in a previous version.
Get the top-level metadata items
This example gets the top-level metadata items. For more information about the items in the response, see Instance metadata categories.
Note that tags are included in this output only if you've allowed access. For more information, see Allow access to tags in instance metadata.
Get the values for metadata items
These examples get the values of some of the top-level metadata items that were obtained in the previous example.
Get the list of available public keys
This example gets the list of available public keys.
Show the formats in which public key 0 is available
This example shows the formats in which public key 0 is available.
Get public key 0 (in the OpenSSH key format)
This example gets public key 0 (in the OpenSSH key format).
Get the subnet ID for an instance
This example gets the subnet ID for an instance.
Get the instance tags for an instance
These examples access the tags for an instance. You must allow access to tags before you can use these examples.
Query throttling
We throttle queries to the IMDS on a per-instance basis, and we place limits on the number of simultaneous connections from an instance to the IMDS.
If you're using the IMDS to retrieve AWS security credentials, avoid querying for credentials during every transaction or concurrently from a high number of threads or processes, as this might lead to throttling. Instead, we recommend that you cache the credentials until they start approaching their expiry time. For more information about IAM role and security credentials associated with the role, see Retrieve security credentials from instance metadata.
If you are throttled while accessing the IMDS, retry your query with an exponential backoff strategy.
Limit IMDS access
You can consider using local firewall rules to disable access from some or all processes to the IMDS.
For instances built
on the AWS Nitro System, the IMDS can be reached from your own
network when a network appliance within your VPC, such as a virtual router,
forwards packets to the IMDS address, and the default source/destination check on the instance is disabled. To prevent a
source from outside your VPC reaching the IMDS, we recommend that you modify the
configuration of the network appliance to drop packets with the destination IPv4
address of the IMDS 169.254.169.254
and, if you enabled the IPv6
endpoint, the IPv6 address of the IMDS [fd00:ec2::254]
.
Using iptables to limit access
The following example uses Linux iptables and its owner
module to prevent the Apache webserver (based on its default installation
user ID of apache
) from accessing 169.254.169.254. It uses a
deny rule to reject all instance
metadata requests (whether IMDSv1 or IMDSv2) from any
process running as that user.
$
sudo iptables --append OUTPUT --proto tcp --destination 169.254.169.254 --match owner --uid-owner apache --jump REJECT
Or, you can consider only allowing access to particular users or groups, by using allow rules. Allow rules might be easier to manage from a security perspective, because they require you to make a decision about what software needs access to instance metadata. If you use allow rules, it's less likely you will accidentally allow software to access the metadata service (that you did not intend to have access) if you later change the software or configuration on an instance. You can also combine group usage with allow rules, so that you can add and remove users from a permitted group without needing to change the firewall rule.
The following example prevents access to the IMDS by all
processes, except for processes running in the user account
trustworthy-user
.
$
sudo iptables --append OUTPUT --proto tcp --destination 169.254.169.254 --match owner ! --uid-owner
trustworthy-user
--jump REJECT
Note
-
To use local firewall rules, you need to adapt the preceding example commands to suit your needs.
-
By default, iptables rules are not persistent across system reboots. They can be made to be persistent by using OS features, not described here.
-
The iptables
owner
module only matches group membership if the group is the primary group of a given local user. Other groups are not matched.
Using PF or IPFW to limit access
If you are using FreeBSD or OpenBSD, you can also consider using PF or IPFW. The following examples limit access to the IMDS to just the root user.
PF
$
block out inet proto tcp from any to 169.254.169.254
$
pass out inet proto tcp from any to 169.254.169.254 user root
IPFW
$
allow tcp from any to 169.254.169.254 uid root
$
deny tcp from any to 169.254.169.254
Note
The order of the PF and IPFW commands matter. PF defaults to last matching rule and IPFW defaults to first matching rule.
Using Windows firewall to limit access
The following PowerShell example uses the built-in Windows firewall to
prevent the Internet Information Server webserver (based on its default
installation user ID of NT AUTHORITY\IUSR
) from accessing
169.254.169.254. It uses a deny rule to
reject all instance metadata requests (whether IMDSv1 or
IMDSv2) from any process running as that user.
PS C:\>
$blockPrincipal = New-Object -TypeName System.Security.Principal.NTAccount ("NT AUTHORITY\IUSR")
PS C:\>
$BlockPrincipalSID = $blockPrincipal.Translate([System.Security.Principal.SecurityIdentifier]).Value
PS C:\>
$BlockPrincipalSDDL = "D:(A;;CC;;;$BlockPrincipalSID)"
PS C:\>
New-NetFirewallRule -DisplayName "Block metadata service from IIS" -Action block -Direction out ` -Protocol TCP -RemoteAddress 169.254.169.254 -LocalUser $BlockPrincipalSDDL
Or, you can consider only allowing access to particular users or groups, by using allow rules. Allow rules might be easier to manage from a security perspective, because they require you to make a decision about what software needs access to instance metadata. If you use allow rules, it's less likely you will accidentally allow software to access the metadata service (that you did not intend to have access) if you later change the software or configuration on an instance. You can also combine group usage with allow rules, so that you can add and remove users from a permitted group without needing to change the firewall rule.
The following example prevents access to instance metadata by all
processes running as an OS group specified in the variable
blockPrincipal
(in this example, the Windows group
Everyone
), except for processes specified in
exceptionPrincipal
(in this example, a group called
trustworthy-users
). You must specify both deny and allow
principals because Windows Firewall, unlike the ! --uid-owner
trustworthy-user
rule in Linux iptables, does not provide a
shortcut mechanism to allow only a particular principal (user or group) by
denying all the others.
PS C:\>
$blockPrincipal = New-Object -TypeName System.Security.Principal.NTAccount ("Everyone")
PS C:\>
$BlockPrincipalSID = $blockPrincipal.Translate([System.Security.Principal.SecurityIdentifier]).Value
PS C:\>
$exceptionPrincipal = New-Object -TypeName System.Security.Principal.NTAccount ("trustworthy-users")
PS C:\>
$ExceptionPrincipalSID = $exceptionPrincipal.Translate([System.Security.Principal.SecurityIdentifier]).Value
PS C:\>
$PrincipalSDDL = "O:LSD:(D;;CC;;;$ExceptionPrincipalSID)(A;;CC;;;$BlockPrincipalSID)"
PS C:\>
New-NetFirewallRule -DisplayName "Block metadata service for $($blockPrincipal.Value), exception: $($exceptionPrincipal.Value)" -Action block -Direction out ` -Protocol TCP -RemoteAddress 169.254.169.254 -LocalUser $PrincipalSDDL
Note
To use local firewall rules, you need to adapt the preceding example commands to suit your needs.
Using netsh rules to limit access
You can consider blocking all software using netsh
rules, but
those are much less flexible.
C:\>
netsh advfirewall firewall add rule name="Block metadata service altogether" dir=out protocol=TCP remoteip=169.254.169.254 action=block
Note
-
To use local firewall rules, you need to adapt the preceding example commands to suit your needs.
-
netsh
rules must be set from an elevated command prompt, and can’t be set to deny or allow particular principals.