Skip to content

Commit 32028db

Browse files
pb8oJonathanWoollett-Light
authored andcommitted
Use IMDSv2
IMDSv1 has problems and nowadays IMDSv2 is preferred. Signed-off-by: Pablo Barbáchano <pablob@amazon.com>
1 parent 1bc49b3 commit 32028db

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

tests/framework/utils_cpuid.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from enum import Enum, auto
88

99
from framework.utils import run_cmd
10+
from framework.utils_imdsv2 import imdsv2_get
1011
import host_tools.network as net_tools
1112

1213
ARM_CPU_DICT = {"0xd0c": "ARM_NEOVERSE_N1"}
@@ -46,10 +47,8 @@ def get_cpu_model_name():
4647

4748

4849
def get_instance_type():
49-
"""Get the instance type through IMDS."""
50-
imds_cmd = "curl http://169.254.169.254/latest/meta-data/instance-type"
51-
_, stdout, _ = run_cmd(imds_cmd)
52-
return stdout
50+
"""Get the instance type through IMDSv2"""
51+
return imdsv2_get("/meta-data/instance-type")
5352

5453

5554
def check_guest_cpuid_output(

tests/framework/utils_imdsv2.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""A simple IMDSv2 client
5+
6+
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
7+
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html
8+
9+
Important! For this client to work in a container scenario, make sure your
10+
instances are set with an adequate hop limit (2 for example). See
11+
`ec2:MetadataHttpPutResponseHopLimit`
12+
"""
13+
14+
15+
import time
16+
17+
import requests
18+
19+
IMDSV2_HDR_TOKEN_TTL = "X-aws-ec2-metadata-token-ttl-seconds"
20+
IMDSV2_HDR_TOKEN = "X-aws-ec2-metadata-token"
21+
22+
23+
class IMDSv2Client:
24+
"""
25+
A simple IMDSv2 client.
26+
27+
>>> IMDSv2Client().get("/meta-data/instance-type")
28+
"""
29+
30+
def __init__(self, endpoint="http://169.254.169.254", version="latest"):
31+
self.endpoint = endpoint
32+
self.version = version
33+
self.ttl = 21600
34+
self.token_expiry_time = 0
35+
self.token = None
36+
37+
def get_token(self):
38+
"""Get a token from IMDSv2"""
39+
if self.token_expiry_time < time.time():
40+
headers = {IMDSV2_HDR_TOKEN_TTL: str(self.ttl)}
41+
# To get a token, docs say to always use latest
42+
url = f"{self.endpoint}/latest/api/token"
43+
res = requests.put(url, headers=headers)
44+
self.token = res.content
45+
self.token_expiry_time = time.time() + self.ttl
46+
return self.token
47+
48+
def get(self, path):
49+
"""
50+
Get a metadata path from IMDSv2
51+
52+
>>> IMDSv2Client().get("/meta-data/instance-type")
53+
"""
54+
headers = {IMDSV2_HDR_TOKEN: self.get_token()}
55+
url = f"{self.endpoint}/{self.version}{path}"
56+
res = requests.get(url, headers=headers)
57+
if res.status_code != 200:
58+
raise Exception(f"IMDSv2 returned {res.status_code} for {url}")
59+
return res.text
60+
61+
62+
IMDS_V2 = IMDSv2Client()
63+
imdsv2_get = IMDS_V2.get

0 commit comments

Comments
 (0)