I Tried Identifying Instances That Don't Require IMDSv2 Using the EC2 ImdsV1Enabled Metric

I Tried Identifying Instances That Don't Require IMDSv2 Using the EC2 ImdsV1Enabled Metric

I tested whether the CloudWatch metric ImdsV1Enabled for Amazon EC2 can identify instances not requiring IMDSv2. One get-metric-data SEARCH query returned values for 3 instances; after switching to required, 0 appeared within 4m59s in all 3 trials.
2026.11.16

This page has been translated by machine translation. View original

Introduction

On November 5, 2026, the CloudWatch metric ImdsV1Enabled was added for EC2.

https://aws.amazon.com/about-aws/whats-new/2026/11/ec2-imdsv1enabled-cloudwatch-metric/

This metric lets you check in CloudWatch which instances have IMDSv1 enabled. The value is 1 for instances whose metadata option is optional, and 0 for instances where it is required (documentation).

I verified whether this metric can identify instances that do not require IMDSv2, and how long it takes for 0 to become visible after changing an instance to required.

Instances and Configuration Changes

In ap-northeast-1, I launched new t4g.nano instances, the smallest spec, from an Amazon Linux 2023 (arm64) AMI. The first three instances launched were configured as: optional with basic monitoring, optional with detailed monitoring, and required with basic monitoring.

The launch-time settings were as follows.

  • optional: --metadata-options HttpTokens=optional
  • required: --metadata-options HttpTokens=required
  • Basic monitoring: --monitoring Enabled=false
  • Detailed monitoring: --monitoring Enabled=true

To measure how long it takes for a configuration change to be reflected in the metric, I added two more optional, basic-monitoring instances, for a total of five instances in the test. I call these two the first additional instance and the second additional instance. To change from optional to required, I used modify-instance-metadata-options.

aws ec2 modify-instance-metadata-options \
  --instance-id <インスタンスID> \
  --http-tokens required

How to Identify Them

Using a SEARCH expression with get-metric-data, you can retrieve the series for each InstanceId in a single query. I saved the query as queries.json.

queries.json
[
  {
    "Id": "q1",
    "Expression": "SEARCH('{AWS/EC2,InstanceId} MetricName=\"ImdsV1Enabled\"', 'Maximum', 60)",
    "ReturnData": true
  }
]
aws cloudwatch get-metric-data \
  --metric-data-queries file://queries.json \
  --start-time <開始時刻> --end-time <終了時刻> \
  --query 'MetricDataResults[?length(Values)>`0`].[Label,Timestamps,Values]'

In the account I tested, series for other instances that had data within the past two weeks were also included in the results with empty Values. Therefore, I used --query to keep only the series that have values. The retrieval range was from 15 minutes before the retrieval time up to the retrieval time.

The table below shows the Label and Values from the results retrieved about 2 minutes after launching the three instances. The Label is an instance ID, which I have replaced here with notation that distinguishes the three instances. Each series had one value.

Label Values
<optional/basic> 1.0
<optional/detailed> 1.0
<required/basic> 0.0

Values are returned in descending order of timestamp, so the first one is the latest data point. Immediately after changing to required, the first value may still be the pre-change 1, and it changes to 0 once a post-change data point appears. If the retrieval range includes data points from both before and after the change, 1 and 0 appear together in a single series.

Results

I measured three times how long it takes for 0 to become visible after changing an optional instance to required. For retrieval, I used get-metric-data specifying the InstanceId (Maximum, Period 60). The time of each change is shown as the elapsed time since the preceding 5-minute mark (such as 12:35 UTC). Because retrieval was repeated at regular intervals, the times in the table are the elapsed time from the change until the retrieval at which 0 became visible, and 0 may actually have appeared earlier. For that reason, all of them are marked "within."

Target Time of change Time until 0 became visible
optional/basic, optional/detailed (changed simultaneously) 2 minutes 14 seconds after 12:35 (the 12:35 data point was already visible) Within 3 minutes 33 seconds (visible in the same retrieval for both instances)
optional/basic (first additional instance) 3 seconds after 12:50 (the 12:50 data point was not yet visible) Within 21 seconds
optional/basic (second additional instance) 44 seconds after 13:00 (right after the 13:00 data point was visible as 1) Within 4 minutes 59 seconds

The slowest was the third run, where I made the change right after the 13:00 data point became visible as 1.

Even when Period was set to 60 seconds, the timestamps in the response were at 5-minute intervals. For the two instances changed simultaneously, one with basic monitoring and one with detailed monitoring, no speedup from detailed monitoring was observed.

Conclusion

With support for the ImdsV1Enabled metric, I was able to identify instances that do not require IMDSv2 with a single SEARCH query via get-metric-data. I confirmed that a change to required is reflected within 5 minutes.

It can be used as an efficient way to find instances that do not require IMDSv2 and therefore need remediation. It is considered especially effective in an AWS Organizations environment where metrics centralization is in place.

https://dev.classmethod.jp/articles/cloudwatch-metrics-centralization-cross-account/

Also, even in an environment that has been remediated, unless IMDSv2 is enforced at the account level, there remains a possibility that instances that do not require IMDSv2 will be launched. If you want to detect them faster than with AWS Config rules, please consider using alarms based on ImdsV1Enabled.

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/configuring-IMDS-new-instances.html

Share this article

AWSのお困り事はクラスメソッドへ