24
24
log = logging .getLogger (__name__ )
25
25
Config = get_config ()
26
26
27
+ # Documentation for configuring instance metadata can be found here:
28
+ # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
29
+ TOKEN_ENDPOINT = "http://169.254.169.254/latest/api/token"
30
+ TOKEN_REQUEST_HEADER_KEY = "X-aws-ec2-metadata-token-ttl-seconds"
31
+ TOKEN_REQUEST_HEADER_VALUE = "21600"
27
32
DEFAULT_EC2_METADATA_ENDPOINT = (
28
33
"http://169.254.169.254/latest/dynamic/instance-identity/document"
29
34
)
35
+ METADATA_REQUEST_HEADER_KEY = "X-aws-ec2-metadata-token"
30
36
31
37
32
- async def fetch ( # type: ignore
33
- session : aiohttp .ClientSession , url : str
38
+ async def fetchJSON (
39
+ session : aiohttp .ClientSession , method : str , url : str , headers : Dict [ str , str ],
34
40
) -> Dict [str , Any ]:
35
- async with session .get ( url , timeout = 2 ) as response :
41
+ async with session .request ( method , url , timeout = 2 , headers = headers ) as response :
36
42
# content_type=None prevents validation of the HTTP Content-Type header
37
43
# The EC2 metadata endpoint uses text/plain instead of application/json
38
44
# https://github.com/aio-libs/aiohttp/blob/7f777333a4ec0043ddf2e8d67146a626089773d9/aiohttp/web_request.py#L582-L585
39
45
return cast (Dict [str , Any ], await response .json (content_type = None ))
40
46
41
47
48
+ async def fetchString (
49
+ session : aiohttp .ClientSession , method : str , url : str , headers : Dict [str , str ]
50
+ ) -> str :
51
+ async with session .request (method , url , timeout = 2 , headers = headers ) as response :
52
+ return await response .text ()
53
+
54
+
42
55
class EC2Environment (Environment ):
43
56
def __init__ (self ) -> None :
44
57
self .sink : Optional [AgentSink ] = None
@@ -48,10 +61,22 @@ async def probe(self) -> bool:
48
61
metadata_endpoint = (
49
62
Config .ec2_metadata_endpoint or DEFAULT_EC2_METADATA_ENDPOINT
50
63
)
64
+ token_header = {TOKEN_REQUEST_HEADER_KEY : TOKEN_REQUEST_HEADER_VALUE }
65
+ log .info ("Fetching token for EC2 metadata request from: %s" , TOKEN_ENDPOINT )
66
+ try :
67
+ token = await fetchString (session , "PUT" , TOKEN_ENDPOINT , token_header )
68
+ log .debug ("Received token for request to EC2 metadata endpoint." )
69
+ except Exception :
70
+ log .info (
71
+ "Failed to fetch token for EC2 metadata request from %s" , TOKEN_ENDPOINT
72
+ )
73
+ return False
74
+
51
75
log .info ("Fetching EC2 metadata from: %s" , metadata_endpoint )
52
76
try :
53
- response_json = await fetch (session , metadata_endpoint )
54
- log .debug ("Received response from EC2 metdata endpoint." )
77
+ metadata_request_header = {METADATA_REQUEST_HEADER_KEY : token }
78
+ response_json = await fetchJSON (session , "GET" , metadata_endpoint , metadata_request_header )
79
+ log .debug ("Received response from EC2 metadata endpoint." )
55
80
self .metadata = response_json
56
81
return True
57
82
except Exception :
0 commit comments