ニクニクドットミー

カッコいいおっさんを目指すエンジニアの厳かなブログ

インスタンスメタデータからタグ情報が取得できるようになったので試してみた

2022/1/6に以下の記事が公開されました。
aws.amazon.com

この記事よるとインスタンスメタデータからインスタンスに設定されているタグ情報が取得できるようになったとあります。いままではdescribe-tagsdescribe-instancesなどAPIを呼び出してタグ名を取得する必要がありました。
メタデータにタグ情報が付与されることでAPIを呼び出す必要がなくなり、APIコール数を抑えることが出来ます。

実際にメタデータからタグ名を取得できるか検証をしてみました。

環境 バージョン
OS Amazon Linux 2 AMI (HVM) - Kernel 5.10, SSD Volume Type - ami-0218d08a1f9dac831
awscli aws-cli/1.22.31 Python/3.8.2 Darwin/20.6.0 botocore/1.23.31

メタデータからタグ情報を取得するためには、2つの設定方法があります。一つは新規インスタンス作成時にオプションを有効にする。もう一つは既存インスタンスに対してオプションを有効にするAPIを実行をするです。

今回はオプションを無効にした状態でインスタンスを作成し、後からオプションを有効にするパターンで検証をしました。既存のインスタンスに対して後からオプションを有効にするパターンの方が業務で発生しやすいと考えたからです。

新規インスタンスを起動する際には以下のように--metadata-options "InstanceMetadataTags=enabled"を渡すことになります。

aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type c3.large \
    ...
    --metadata-options "InstanceMetadataTags=enabled"

既存インスタンスに対してメタデータオプションを変更するAPIを実行します。

aws ec2 modify-instance-metadata-options --instance-id i-xxxxxxxxxxxx \
    --instance-metadata-tags enabled

{
    "InstanceId": "i-xxxxxxxxxxxx",
    "InstanceMetadataOptions": {
        "State": "pending",
        "HttpTokens": "optional",
        "HttpPutResponseHopLimit": 1,
        "HttpEndpoint": "enabled",
        "HttpProtocolIpv6": "disabled",
        "InstanceMetadataTags": "enabled"
    }
}

"InstanceMetadataTags": "enabled"となり、有効になりました。

この状態で対象のインスタンスにログインしてメタデータを取得します。

[ssm-user@i-xxxxxxxxxxxx ~]$ curl http://169.254.169.254/latest/meta-data/tags/instance
Environment
Name
[ssm-user@i-xxxxxxxxxxxx ~]$ curl http://169.254.169.254/latest/meta-data/tags/instance/Environment
dev
[ssm-user@i-xxxxxxxxxxxx ~]$ curl http://169.254.169.254/latest/meta-data/tags/instance/Name
test-metadata-tag

タグ情報が取得することが出来ました。

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS

aws-cli/2.2.1にはmodify-instance-metadata-options--instance-metadata-tagsがまだ来てないようでした。

IMDSv2を試してみる

インスタンスメタデータにはv1とv2が存在します。v2ではトークンをAPIのリクエストに付与する必要があります。いつもv1を利用していたのでv2を試してみます。
さきほど作成したインスタンスはv1とv2を共存させていたので、どちらのバージョンのメタデータも利用可能でした。v2はセキュリティ面が向上しているので、普段からv2を利用するのが良いでしょう。
例)

HTTP GETおよびHEADメソッドはIMDSv2インスタンスメタデータリクエストで許可されています。 PUT リクエストは、X-Forwarded-For ヘッダーが含まれている場合、拒否されます。

参考情報

IMDSv1からv2に移行させます。

aws ec2 modify-instance-metadata-options --instance-id i-xxxxxxxxxxxx \
   --http-tokens required
{
    "InstanceId": "i-xxxxxxxxxxxx",
    "InstanceMetadataOptions": {
        "State": "pending",
        "HttpTokens": "required",
        "HttpPutResponseHopLimit": 1,
        "HttpEndpoint": "enabled",
        "HttpProtocolIpv6": "disabled",
        "InstanceMetadataTags": "enabled"
    }
}

"HttpTokens": "required"となり、トークンが必須となりました。この状態でv1形式でメタデータを取得してみます。

curl http://169.254.169.254/latest/meta-data/tags/instance/Name
<?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>

ステータスコード401が返却されました。次にv2形式で実行します。

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
curl http://169.254.169.254/latest/meta-data/tags/instance -H "X-aws-ec2-metadata-token: $TOKEN"
Environment
Name

タグ情報が取得できました。

EC2などで定期実行するスクリプトを書いた時にインスタンスのタグ情報を参照する機会が多くありました。その度にAPIを呼び出していましたが、メタデータに付与されることでAPIのコール数を減らすことが出来ます。
IMDSv1ばかり利用しておりv2を試せてなかったのですが、セキュリティ面でメリットがあることが理解できたので、今後はv2を利用したいと思います。

See you next time:)