Cómo obtener el Instance ID desde dentro de tu EC2 usando IMDSv2

Estás escribiendo un script de arranque en una instancia EC2 y necesitas conocer el Instance ID desde dentro del propio servidor — sin hardcodearlo, sin llamar a la API de AWS desde fuera. El servicio de metadatos de instancia (IMDS) resuelve exactamente esto, pero la versión que uses marca una diferencia real en términos de seguridad operacional.

TL;DR — IMDSv1 vs IMDSv2 para obtener el Instance ID

AspectoIMDSv1IMDSv2
AutenticaciónNinguna — petición directa GETToken de sesión obligatorio (TTL configurable)
Protección SSRFNoSí — el token requiere cabecera PUT explícita
Complejidad de usoUna sola llamadaDos llamadas (obtener token + consultar metadato)
Recomendación AWSDeprecado operacionalmenteRecomendado y configurable como obligatorio
Endpointhttp://169.254.169.254/latest/meta-data/Mismo endpoint, cabecera de sesión requerida

Cómo funciona el Instance Metadata Service (IMDS)

El IMDS es un endpoint HTTP local disponible en todas las instancias EC2 en la dirección de enlace local 169.254.169.254. No requiere credenciales de AWS ni acceso a internet — el tráfico nunca sale del hipervisor. Desde cualquier proceso corriendo en la instancia, puedes consultar metadatos como el Instance ID, la región, el tipo de instancia, o las credenciales temporales del rol IAM asociado.

La diferencia estructural entre V1 y V2 está en el modelo de sesión. IMDSv1 acepta peticiones GET directas sin ningún tipo de autenticación previa. IMDSv2 exige primero una petición PUT a un endpoint especial para obtener un token de sesión con TTL, y luego ese token debe incluirse como cabecera en cada consulta posterior. Este diseño de dos pasos es lo que rompe los ataques SSRF más comunes.

Piénsalo como la diferencia entre una puerta sin cerradura y una con cerradura de doble vuelta: IMDSv1 es la puerta abierta — cualquier proceso en la red que pueda hacer un GET a esa IP, incluyendo código ejecutado por una vulnerabilidad SSRF en tu aplicación, obtiene los metadatos sin fricción. IMDSv2 requiere que el atacante también pueda emitir un PUT con cabeceras personalizadas, lo que la mayoría de las vulnerabilidades SSRF simples no pueden hacer.
sequenceDiagram participant Script as Script en EC2 participant IMDS as IMDS (169.254.169.254) Note over Script,IMDS: IMDSv1 — Sin autenticación Script->>IMDS: GET /latest/meta-data/instance-id IMDS-->>Script: i-1234567890abcdef0 Note over Script,IMDS: IMDSv2 — Con token de sesión Script->>IMDS: PUT /latest/api/token
(TTL: 21600s) IMDS-->>Script: TOKEN=AQAEAxxxxxxx... Script->>IMDS: GET /latest/meta-data/instance-id
(Header: X-aws-ec2-metadata-token: TOKEN) IMDS-->>Script: i-1234567890abcdef0
  1. Petición PUT al endpoint de token: El cliente envía una petición PUT indicando el TTL deseado para la sesión. Este paso no existe en IMDSv1.
  2. IMDS devuelve un token de sesión: El token es una cadena opaca válida durante el TTL especificado (entre 1 y 21600 segundos).
  3. Consulta con token: Cada petición GET al endpoint de metadatos debe incluir el token en la cabecera X-aws-ec2-metadata-token.
  4. IMDS responde con el metadato: Si el token es válido, el servicio devuelve el valor solicitado — en este caso, el Instance ID.

Por qué IMDSv1 es un riesgo real, no solo teórico

El vector de ataque clásico es SSRF (Server-Side Request Forgery). Si tu aplicación web tiene una vulnerabilidad que permite a un atacante hacer que el servidor realice peticiones HTTP arbitrarias, y la instancia usa IMDSv1, el atacante puede recuperar las credenciales temporales del rol IAM con una sola petición a http://169.254.169.254/latest/meta-data/iam/security-credentials/<nombre-del-rol>. Con esas credenciales, tiene acceso a todos los recursos que el rol permita.

IMDSv2 no elimina SSRF, pero sí eleva el coste del ataque. La petición PUT inicial requiere enviar la cabecera X-aws-ec2-metadata-token-ttl-seconds, y muchos proxies y frameworks de aplicación que son vulnerables a SSRF no permiten cabeceras personalizadas en peticiones redirigidas. Es una defensa en profundidad, no una solución absoluta.

Ese detalle — que IMDSv2 no bloquea SSRF sino que rompe la cadena de explotación — es lo que a veces se malinterpreta en los análisis de seguridad.

Cómo obtener el Instance ID con IMDSv2 desde un script

El flujo completo requiere dos llamadas. Primero obtienes el token de sesión, luego lo usas para consultar el metadato. Aquí el proceso paso a paso con ejemplos listos para producción.

Paso 1 — Obtener el token de sesión IMDSv2

Solicita un token con un TTL razonable para tu caso de uso. Para scripts de arranque que se ejecutan una sola vez, 21600 segundos (6 horas) es más que suficiente. Para procesos de larga duración, considera renovar el token periódicamente.

TOKEN=$(curl -s -X PUT \
  'http://169.254.169.254/latest/api/token' \
  -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600')

Paso 2 — Consultar el Instance ID usando el token

Con el token almacenado en la variable, realiza la consulta al endpoint de metadatos incluyendo el token como cabecera.

INSTANCE_ID=$(curl -s \
  'http://169.254.169.254/latest/meta-data/instance-id' \
  -H "X-aws-ec2-metadata-token: $TOKEN")

echo "Instance ID: $INSTANCE_ID"

Script completo y robusto para uso en producción

Este script combina ambos pasos, añade validación básica y es seguro para incluir en user data o en scripts de configuración de sistemas.

🔽 Ver script completo de obtención de Instance ID con IMDSv2
#!/bin/bash
set -euo pipefail

# Obtener token IMDSv2 con TTL de 6 horas
IMDS_TOKEN=$(curl -s \
  --connect-timeout 2 \
  --max-time 5 \
  -X PUT \
  'http://169.254.169.254/latest/api/token' \
  -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600')

if [ -z "$IMDS_TOKEN" ]; then
  echo 'ERROR: No se pudo obtener el token IMDSv2. Verifica que IMDS esté habilitado.' >&2
  exit 1
fi

# Consultar el Instance ID
INSTANCE_ID=$(curl -s \
  --connect-timeout 2 \
  --max-time 5 \
  'http://169.254.169.254/latest/meta-data/instance-id' \
  -H "X-aws-ec2-metadata-token: $IMDS_TOKEN")

if [ -z "$INSTANCE_ID" ]; then
  echo 'ERROR: No se pudo obtener el Instance ID desde IMDS.' >&2
  exit 1
fi

echo "Instance ID: $INSTANCE_ID"

Obtener otros metadatos útiles con el mismo token

El token obtenido es válido para cualquier consulta al IMDS durante su TTL. Puedes reutilizarlo para obtener región, tipo de instancia, zona de disponibilidad, o el nombre del rol IAM asociado.

# Reutilizar el mismo token para otros metadatos
AZ=$(curl -s \
  'http://169.254.169.254/latest/meta-data/placement/availability-zone' \
  -H "X-aws-ec2-metadata-token: $IMDS_TOKEN")

INSTANCE_TYPE=$(curl -s \
  'http://169.254.169.254/latest/meta-data/instance-type' \
  -H "X-aws-ec2-metadata-token: $IMDS_TOKEN")

echo "AZ: $AZ"
echo "Tipo: $INSTANCE_TYPE"

Cómo forzar IMDSv2 en tus instancias EC2

Obtener el Instance ID con IMDSv2 desde tu script es solo la mitad del trabajo. Si la instancia todavía permite IMDSv1, cualquier otro proceso en el servidor puede seguir usándolo. La configuración correcta es deshabilitar IMDSv2 opcional y hacerlo obligatorio a nivel de instancia.

Verificar el estado actual de IMDS en una instancia

Antes de cambiar nada, comprueba si la instancia ya tiene IMDSv2 como requerido o si todavía permite V1. Este comando es el punto de partida diagnóstico — si no lo ejecutas primero, puedes estar asumiendo un estado de seguridad que no existe.

aws ec2 describe-instances \
  --instance-ids i-1234567890abcdef0 \
  --query 'Reservations[*].Instances[*].MetadataOptions' \
  --output table \
  --region us-east-1

Busca el campo HttpTokens en la salida. Si el valor es optional, IMDSv1 sigue activo. Si es required, solo IMDSv2 funciona.

Forzar IMDSv2 en una instancia existente

Puedes cambiar el comportamiento sin reiniciar la instancia. El cambio es efectivo de inmediato.

aws ec2 modify-instance-metadata-options \
  --instance-id i-1234567890abcdef0 \
  --http-tokens required \
  --http-endpoint enabled \
  --region us-east-1

Configurar IMDSv2 como obligatorio en el lanzamiento (Launch Template)

Para nuevas instancias, la forma correcta es definirlo en el Launch Template. Así no dependes de recordar aplicarlo manualmente después del lanzamiento.

🔽 Ver configuración de Launch Template con IMDSv2 obligatorio
aws ec2 create-launch-template \
  --launch-template-name mi-plantilla-segura \
  --version-description 'IMDSv2 obligatorio' \
  --launch-template-data '{
    "MetadataOptions": {
      "HttpTokens": "required",
      "HttpEndpoint": "enabled",
      "HttpPutResponseHopLimit": 1
    }
  }' \
  --region us-east-1

El parámetro HttpPutResponseHopLimit con valor 1 es relevante para entornos con contenedores: limita cuántos saltos de red puede atravesar la respuesta del token. Con valor 1, solo el proceso directamente en la instancia puede obtener el token — los contenedores anidados no pueden, a menos que explícitamente se aumente este valor.

Diagnóstico: cuando el script falla al obtener el token

Hay un patrón de fallo que aparece con cierta frecuencia en migraciones: el script funcionaba perfectamente con IMDSv1, se migra a IMDSv2, y de repente falla en instancias específicas. La causa casi siempre no está en el script.

El síntoma observable: curl devuelve una cadena vacía o un error 400 al intentar obtener el token. El diagnóstico inicial suele apuntar a permisos de red o al Security Group — pero el IMDS usa la dirección de enlace local 169.254.169.254, que no está sujeta a Security Groups ni a NACLs de subred.

La causa real en la mayoría de estos casos: el endpoint IMDS estaba deshabilitado (HttpEndpoint: disabled) en esa instancia específica, o la instancia fue lanzada con una AMI que tenía configuraciones heredadas. El comando describe-instances con el filtro MetadataOptions mostrado arriba lo confirma en segundos.

flowchart TD A[Script falla al obtener token] --> B{curl devuelve vacío o 400?} B -->|Sí| C[Verificar HttpEndpoint] C --> D{HttpEndpoint = disabled?} D -->|Sí| E[Habilitar con modify-instance-metadata-options] D -->|No| F[Verificar HttpTokens] F --> G{HttpTokens = required
y script usa IMDSv1?} G -->|Sí| H[Migrar script a IMDSv2] G -->|No| I[Verificar HopLimit] I --> J{Script en contenedor
y HopLimit = 1?} J -->|Sí| K[Aumentar HopLimit o mover lógica a host] J -->|No| L[Revisar logs del sistema y conectividad]
  1. Token vacío: La primera señal — si el PUT no devuelve nada, el problema está antes de la consulta de metadatos.
  2. Verificar HttpEndpoint: Si el endpoint está deshabilitado, ninguna versión de IMDS funciona. Habilítalo con modify-instance-metadata-options.
  3. Verificar HttpTokens: Si está en required y tu script usa IMDSv1, fallará silenciosamente devolviendo 401.
  4. Verificar HopLimit en contenedores: Si el script corre dentro de un contenedor y el HopLimit es 1, el token no llegará al contenedor.

Verificar con AWS CLI que IMDSv2 está activo en toda la cuenta

Para auditar todas las instancias de una región y detectar las que todavía permiten IMDSv1, este comando filtra directamente por el estado del campo HttpTokens.

aws ec2 describe-instances \
  --query 'Reservations[*].Instances[?MetadataOptions.HttpTokens==`optional`].[InstanceId,MetadataOptions.HttpTokens]' \
  --output table \
  --region us-east-1

Cualquier instancia que aparezca en esta salida todavía acepta peticiones IMDSv1 sin token. En entornos con múltiples cuentas, considera usar AWS Config con la regla gestionada ec2-imdsv2-check para detectar incumplimientos de forma continua.

Cómo obtener el Instance ID con IMDSv2 — Resumen y próximos pasos

Recuperar el Instance ID desde dentro de una instancia EC2 es una operación cotidiana, pero hacerlo con IMDSv2 en lugar de IMDSv1 elimina una superficie de ataque concreta sin añadir complejidad operacional significativa. El patrón de dos pasos — token primero, consulta después — se convierte en rutina rápidamente.

Los pasos inmediatos recomendados:

  • Audita tus instancias actuales con describe-instances filtrando por HttpTokens: optional.
  • Actualiza tus Launch Templates para incluir HttpTokens: required en todas las nuevas instancias.
  • Migra los scripts existentes al patrón de dos pasos de IMDSv2 mostrado en este artículo.
  • Considera habilitar la regla de AWS Config ec2-imdsv2-check para detección continua.

Documentación oficial de referencia: Configuring the Instance Metadata Service — AWS EC2 User Guide.

Glosario de términos clave

TérminoDefinición
IMDS (Instance Metadata Service)Endpoint HTTP local en 169.254.169.254 que expone metadatos de la instancia EC2 sin requerir credenciales de AWS.
IMDSv2Versión 2 del IMDS que requiere un token de sesión obtenido mediante PUT antes de poder consultar metadatos.
SSRF (Server-Side Request Forgery)Vulnerabilidad que permite a un atacante hacer que el servidor realice peticiones HTTP a destinos arbitrarios, incluyendo el endpoint IMDS.
HttpTokensParámetro de configuración de la instancia que controla si IMDSv2 es opcional (optional) u obligatorio (required).
HttpPutResponseHopLimitNúmero máximo de saltos de red que puede atravesar la respuesta del token IMDSv2. Relevante para entornos con contenedores.

Comentarios