この記事では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のみが利用可能