aws/internal/providers/imds

IMDSv2 (Instance Metadata Service version 2) flow.

  1. PUT <endpoint>/latest/api/token with an X-aws-ec2-metadata-token- ttl-seconds header → session token in body.
  2. GET <endpoint>/latest/meta-data/iam/security-credentials/ with the token in X-aws-ec2-metadata-token → role name in body.
  3. GET <endpoint>/latest/meta-data/iam/security-credentials/<role> with the same token → JSON body with AccessKeyId, SecretAccessKey, Token, Expiration.

The PUT in step 1 is what makes this “v2”: it requires a session token that an SSRF attacker bouncing requests off the instance can’t easily obtain. v1 is intentionally not implemented.

Errors are classified so the chain can do the right thing:

Types

pub type Error {
  NotOnInstance(reason: String)
  Failed(reason: String)
}

Constructors

  • NotOnInstance(reason: String)

    Step 1 failed (connect refused, 401, 404, timeout). The standard signal that we’re not running on EC2 / Lambda. Chain should keep going.

  • Failed(reason: String)

    Anything past step 1 — the instance answered the token PUT but the downstream calls failed. Worth surfacing to the user.

Decoded credentials, kept as a flat record so this module doesn’t depend on aws/credentials. The caller wraps these into the canonical credentials.Credentials value.

pub type ImdsCredentials {
  ImdsCredentials(
    access_key_id: String,
    secret_access_key: String,
    session_token: String,
    expires_at: Int,
  )
}

Constructors

  • ImdsCredentials(
      access_key_id: String,
      secret_access_key: String,
      session_token: String,
      expires_at: Int,
    )
pub type Options {
  Options(endpoint: String, token_ttl_seconds: Int)
}

Constructors

  • Options(endpoint: String, token_ttl_seconds: Int)

Values

pub fn default_options() -> Options
pub fn fetch(
  send: fn(request.Request(BitArray)) -> Result(
    response.Response(BitArray),
    http_send.HttpError,
  ),
  options: Options,
) -> Result(ImdsCredentials, Error)

Run the full IMDSv2 flow. Returns decoded credentials or a categorised error. The send callback is the only side-effect surface — tests pass a stub here.

Search Document