背景・目的
プライベートサブネット上の EC2(Amazon Linux 2)で、IMDSv2(HttpTokens: required)の状態で SSM Session Manager に接続できない事象が発生しました。
本記事では、この事象を再現し、原因を特定して解決するまでの流れをまとめます。
まとめ
| 項目 | 内容 |
|---|---|
| 事象 | 古い AMI の EC2 で IMDSv2 にすると Session Manager に接続できない |
| 原因 | AMI にプリインストールされた SSM Agent が IMDSv2 に非対応(2019年6月の AMI < IMDSv2 リリース 2019年11月) |
| 対策 | 最新の Amazon Linux 2 AMI を使用する(UserData での更新は鶏と卵の問題で不可) |
概要
IMDS とは
Instance Metadata Service(IMDS)は、EC2 インスタンスが自身のメタデータや IAM ロールの一時認証情報を取得するためのサービスです。169.254.169.254 にアクセスして利用します。
| IMDSv1 | IMDSv2 | |
|---|---|---|
| 方式 | GET リクエストのみ | PUT でトークン取得 → GET にトークン付与 |
| セキュリティ | SSRF 攻撃に脆弱 | トークンベースで SSRF 対策 |
| AWS 推奨 | 非推奨 | 推奨 |
SSM Agent と IMDS の関係
SSM Agent は IMDS から以下を取得します:
- インスタンス ID(自身の識別)
- IAM ロールの一時認証情報(AWS API 呼び出し用)
これらが取得できないと、SSM Agent は AWS Systems Manager に登録できず、Session Manager も Run Command も動作しません。
実践
事前準備
前回の記事で構築した検証環境(Ec2VpcInternalStack)に、古い固定 AMI(ami-XXXXXXXXXXXXX)のインスタンスを追加しました。
- VPC: インターネット疎通なし(IGW/NAT なし)
- VPC Endpoints: ssm, ssmmessages, ec2messages, s3
- EC2: Amazon Linux 2(固定 AMI), t3.micro, IMDSv2(required)
- IAM ロール: AmazonSSMManagedInstanceCore
Phase 1: 事象の確認
1-1. SSM 接続を試行
EC2 コンソールから Session Manager で接続を試みます。
- Ping status: オフライン
- Session Manager connection status: Not connected
- Agent version: —(表示なし)
→ SSM Agent が Systems Manager に登録できていない状態です。
1-2. IMDS 設定を確認
aws ec2 describe-instances --instance-ids i-XXXXXXXXXXXX \
--query "Reservations[0].Instances[0].MetadataOptions" \
--region ap-northeast-1
{
"HttpTokens": "required",
"HttpPutResponseHopLimit": 2,
"HttpEndpoint": "enabled"
}
IMDSv2(HttpTokens: required)になっています。
Phase 2: 切り分け
2-1. 最新 AMI のインスタンスとの比較
同じ VPC・同じ IAM ロール・同じ IMDSv2 設定で、最新 AMI(latestAmazonLinux2)のインスタンスは Session Manager で接続できています。
| 古い固定 AMI | 最新 AMI | |
|---|---|---|
| AMI | ami-XXXXXXXXXXXXX | 最新の Amazon Linux 2 |
| IMDSv2 | required | required |
| VPC / Endpoints | 同じ | 同じ |
| IAM ロール | 同じ | 同じ |
| SSM 接続 | ❌ オフライン | ✅ 接続可能 |
→ AMI の違い(= プリインストールされた SSM Agent のバージョン)が原因と推測。
2-2. IMDSv1 への変更を試みる
念のため IMDSv1 に戻して切り分けを試みます。
aws ec2 modify-instance-metadata-options \
--instance-id i-XXXXXXXXXXXX \
--http-tokens optional \
--region ap-northeast-1
An error occurred (UnsupportedOperation): You can't set httpTokens to 'optional'
because httpTokensEnforced is enabled for this account.
→ アカウントレベルで IMDSv2 が強制されているため、IMDSv1 に戻すことはできません。
Phase 3: 原因の調査
3-1. AMI の情報を確認
SSM で接続できないため、AMI のリリース日から SSM Agent のバージョンを推測します。
aws ec2 describe-images --image-ids ami-XXXXXXXXXXXXX \
--query "Images[0].{Name:Name,CreationDate:CreationDate,Description:Description}" \
--region ap-northeast-1
{
"Name": "amzn2-ami-hvm-2.0.20190618-x86_64-gp2",
"CreationDate": "2019-06-19T21:59:16.000Z",
"Description": "Amazon Linux 2 AMI 2.0.20190618 x86_64 HVM gp2"
}
2019年6月 の AMI です。
3-2. 原因の特定
IMDSv2 は 2019年11月 にリリースされました。この AMI は 2019年6月のため、プリインストールされた SSM Agent は IMDSv2 リリースより前のバージョンであり、IMDSv2 に対応していません。
| 古い固定 AMI | 最新 AMI | |
|---|---|---|
| AMI リリース日 | 2019年6月(IMDSv2 リリース前) | 最新(IMDSv2 対応済み) |
| IMDSv2 環境での動作 | ❌ 認証情報取得不可 | ✅ 正常動作 |
結論: AMI にプリインストールされた SSM Agent が IMDSv2 に非対応のため、トークンベースのメタデータ取得ができず、IAM ロールの認証情報を取得できず SSM に登録できない。
Phase 4: 対策の実施(SSM Agent の更新)
4-1. UserData で SSM Agent を更新する(失敗)
CDK を修正し、UserData で最新の SSM Agent をインストールするようにします。
yum install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm
systemctl enable amazon-ssm-agent
systemctl restart amazon-ssm-agent
- UserData は初回起動時のみ動作するため、既存の EC2 を terminate します
- CDK を再デプロイします
- → 接続できません
UserData 実行時に yum install が S3 からパッケージを取得するには IAM 認証情報が必要です。その認証情報は IMDS から取得しますが、古い AWS CLI(AMI にプリインストールされたもの)が IMDSv2 に対応していないため、認証情報が取れず S3 アクセスが失敗します。
鶏と卵の問題: SSM Agent を更新するために S3 にアクセスしたいが、S3 にアクセスするための認証情報を取得するには IMDSv2 対応が必要。
Phase 5: 動作確認
CDK の AMI を最新の Amazon Linux 2 に変更してデプロイします。
-
Session Manager で接続できることを確認します
-
SSM Agent のバージョンを確認します
sh-4.2$ amazon-ssm-agent --version
SSM Agent version: 3.3.4108.0
- IMDSv2 でメタデータが取得できることを確認します
sh-4.2$ TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
sh-4.2$ curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id
i-XXXXXXXXXXX
→ 最新 AMI であれば IMDSv2 環境でも SSM Agent が正常に動作し、Session Manager で接続できることを確認しました。
考察
なぜ古い AMI で問題が起きるのか
IMDSv2 はセキュリティ強化のためにトークンベースの認証を導入しました。しかし、IMDSv2 リリース前の SSM Agent は GET リクエストのみでメタデータを取得する設計のため、トークン取得(PUT リクエスト)ができず認証情報を取得できません。
UserData での更新が不可能な理由
通常、古いソフトウェアは UserData で更新できますが、今回は以下の循環依存が発生します:
SSM Agent を更新したい
→ S3 からパッケージを取得する必要がある
→ S3 アクセスには IAM 認証情報が必要
→ IAM 認証情報は IMDS から取得する
→ IMDS は IMDSv2(トークンベース)
→ 古い AWS CLI/yum は IMDSv2 に非対応
→ 認証情報が取れない → S3 アクセス失敗
教訓
- AMI は定期的に更新する: 古い AMI を固定で使い続けると、アカウントレベルのセキュリティ強化(IMDSv2 強制等)に追従できなくなる
-
AMI ID のハードコードを避ける: SSM Parameter Store の最新 AMI パスや CDK の
latestAmazonLinux2()を使うことで、常に最新の AMI を参照できる - IMDSv2 強制前にテストする: アカウントレベルで IMDSv2 を強制する前に、既存インスタンスの SSM Agent バージョンを確認すべき

