この記事ではTerraformを使用してEC2インスタンスでIMDSv2を必須にする方法について説明します。
IMDSv2とは
IMDSv2(Instance Metadata Service version 2)はAWS EC2インスタンスにおいてメタデータとユーザーデータを取得するためのサービスです。 IMDSv2はメタデータの取得にPUTやトークンを指定したGETヘッダーを使用します。
≫ IMDSv2の使用 - Amazon Elastic Compute Cloud
SecurityHub の IMDSに関する指摘
AWS SecurityHubを導入するとEC2インスタンスに対してIMDSv1の使用に関する指摘します。
≫ [EC2.8]Amazon EC2 instances should use Instance Metadata Service Version 2 (IMDSv2)
この指摘に対応するにはEC2インスタンスのメタデータの取得をIMDSv2必須とする必要があります。
EC2インスタンスにIMDSv2を適用する方法
TerraformでEC2インスタンスにIMDSv2を適用するにはaws_instanceリソースに設定を指定します。
以下のようにmetadata_options
ブロックを追加します。
resource "aws_instance" "host" {
# ...
metadata_options {
http_tokens = "required"
}
}
上記コードではTerraformでEC2インスタンスを作成するために使用されるaws_instance
のリソースブロックにmetadata_options
設定を追加しています。
metadata_options
ブロックのhttp_tokens
を「required
」に設定するとメタデータ取得時にトークンが必須になります。
http_tokens
のデフォルト値はoptional
で、IMDSv1によるメタデータの参照(トークン無しによる参照)が可能となります。
IMDSv2適用時に curl でメタデータを参照する方法
http_tokensをrequiredにするとトークンの取得が必須となります。
例えば以下のコマンドでメタデータに参照するとIMDSv1では取得できますが、IMDSv2ではエラー(401 Unauthorized) となります。
$ curl http://169.254.169.254/latest/meta-data/ami-id
ami-0ddb05e945a674cf5
$ curl http://169.254.169.254/latest/meta-data/ami-id
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>401 - Unauthorized</title>
</head>
<body>
<h1>401 - Unauthorized</h1>
</body>
</html>
IMDSv2適用時にメタデータを参照するには、まずcurlでトークンを取得する必要があります。以下はコマンド例です。
TOKEN=$(curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 600" "http://169.254.169.254/latest/api/token")
X-aws-ec2-metadata-token-ttl-seconds
ヘッダーで要求するトークンの有効期限(秒)を指定します。
上記コマンドではTOKEN変数に代入してあるのでechoで取得したトークンを確認できます。
$ echo $TOKEN
(略)
メタデータを参照するにはX-aws-ec2-metadata-token
ヘッダーに取得したトークンを指定します。
以下はコマンド例です。
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-id
ami-0ddb05e945a674cf5
トークンの期限が切れると401エラーになります。
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-id
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>401 - Unauthorized</title>
</head>
<body>
<h1>401 - Unauthorized</h1>
</body>
</html>
利用できる IMDS のバージョンを確認する方法
AWS CLIを使ってEC2インスタンスのIMDSのバージョンを確認できます。
$ aws ec2 describe-instances --instance-ids <インスタンスID> \
--query "Reservations[].Instances[].MetadataOptions.HttpTokens" --output text
optional
$ aws ec2 describe-instances --instance-ids <インスタンスID> \
--query "Reservations[].Instances[].MetadataOptions.HttpTokens" --output text
required
このコマンドの出力は以下のいずれかになります。
- optional:IMDSv1とIMDSv2の両方が利用可能
- required:IMDSv2のみが利用可能