【小ネタ】EC2 IMDSv2でインスタンスIDを取得する

# これは何？
IMDSv2強制している（IMDSv1を許可しない）EC2で、内部からインスタンスIDを取得する方法です。
業務でEC2内部に入って作業をした時に、証跡でインスタンスIDも一緒に残したい場面があり、備忘としてメモしました。


# 最初に結論
curlのHTTPリクエストヘッダにセッショントークンを含めることで、取得可能です。
```zsh
# インスタンスID取得
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" \
    -v http://169.254.169.254/latest/meta-data/instance-id/

# メタデータ全体取得
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  -v http://169.254.169.254/latest/meta-data/

```


# 少し詳しく

## IMDSv2強制していない場合
```zsh
# IMDSv1が許可されているので、これで取得できる
$ curl 169.254.169.254/latest/meta-data/instance-id/

# メタデータ全体取得
$ curl http://169.254.169.254/latest/meta-data/
```

## IMDSv2強制の場合
### 失敗例
```zsh
# IMDSv1が許可されていないので、これを打ってもはじかれて何も出力されない
$ curl 169.254.169.254/latest/meta-data/instance-id/
```

### 正しい例
```zsh
# IMDSv2経由でインスタンスID取得
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" \
    -v http://169.254.169.254/latest/meta-data/instance-id/

## 出力例（一部マスク）
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    56  100    56    0     0  16979      0 --:--:-- --:--:-- --:--:-- 18666
*   Trying 169.254.169.254:80...
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> GET /latest/meta-data/instance-id/ HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/8.0.1
> Accept: */*
> X-aws-ec2-metadata-token: xxxxxxx
>
< HTTP/1.1 200 OK
< X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 21600
< Content-Type: text/plain
< Accept-Ranges: none
< Last-Modified: Tue, 27 Feb 2024 12:06:18 GMT
< Content-Length: 19
< Date: Tue, 27 Feb 2024 13:06:06 GMT
< Server: EC2ws
< Connection: close
<
* Closing connection 0
i-0410xxxxxxxxxx # インスタンスID


# メタデータ全体取得
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  -v http://169.254.169.254/latest/meta-data/

## 出力例（一部マスク）
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    56  100    56    0     0  34610      0 --:--:-- --:--:-- --:--:-- 56000
*   Trying 169.254.169.254:80...
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> GET /latest/meta-data/ HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/8.0.1
> Accept: */*
> X-aws-ec2-metadata-token: xxxxxx
>
< HTTP/1.1 200 OK
< X-Aws-Ec2-Metadata-Token-Ttl-Seconds: 21600
< Content-Type: text/plain
< Accept-Ranges: none
< Last-Modified: Tue, 27 Feb 2024 12:06:18 GMT
< Content-Length: 325
< Date: Tue, 27 Feb 2024 13:02:56 GMT
< Server: EC2ws
< Connection: close
<
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
* Closing connection 0

```


# 参考
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html