99EC2_HOST_NAME_URI = DEFAULT_EC2_METADATA_URI + "local-hostname"
1010EC2_HOST_INSTANCE_TYPE_URI = DEFAULT_EC2_METADATA_URI + "instance-type"
1111
12+ # Used for IMDSv2 to retrieve API token that will be used to call the EC2 METADATA service.
13+ # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
14+ # Bandit marks the following line as risky because it contains the word "token",
15+ # thought it doesn't contain any secret; ignoring with # nosec
16+ # https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html
17+ EC2_API_TOKEN_URI = "http://169.254.169.254/latest/api/token" # nosec
18+ EC2_METADATA_TOKEN_HEADER_KEY = 'X-aws-ec2-metadata-token' # nosec
19+ EC2_METADATA_TOKEN_TTL_HEADER_KEY = 'X-aws-ec2-metadata-token-ttl-seconds' # nosec
20+ EC2_METADATA_TOKEN_TTL_HEADER_VALUE = '21600' # nosec
21+
1222logger = logging .getLogger (__name__ )
1323
24+
1425class AWSEC2Instance (FleetInfo ):
1526 """
1627 This class will get and parse the EC2 metadata if available.
@@ -26,29 +37,47 @@ def get_fleet_instance_id(self):
2637 return self .host_name
2738
2839 @classmethod
29- def __look_up_host_name (cls ):
30- # The id of the fleet element. Eg. host name in ec2.
31- return http_get (url = EC2_HOST_NAME_URI ).read ().decode ()
40+ def __look_up_host_name (cls , token ):
41+ """
42+ The id of the fleet element. Eg. host name in ec2.
43+ """
44+ return cls .__look_up_with_IMDSv2 (EC2_HOST_NAME_URI , token )
45+
46+ @classmethod
47+ def __look_up_instance_type (cls , token ):
48+ """
49+ The type of the instance. Eg. m5.2xlarge
50+ """
51+ return cls .__look_up_with_IMDSv2 (EC2_HOST_INSTANCE_TYPE_URI , token )
3252
3353 @classmethod
34- def __look_up_instance_type (cls ):
35- return http_get (url = EC2_HOST_INSTANCE_TYPE_URI ).read ().decode ()
54+ def __look_up_with_IMDSv2 (cls , url , token ):
55+ return http_get (url = url ,
56+ headers = {EC2_METADATA_TOKEN_HEADER_KEY : token }) \
57+ .read ().decode ()
58+
59+ @classmethod
60+ def __look_up_ec2_api_token (cls ):
61+ return http_get (url = EC2_API_TOKEN_URI ,
62+ headers = {EC2_METADATA_TOKEN_TTL_HEADER_KEY : EC2_METADATA_TOKEN_TTL_HEADER_VALUE }) \
63+ .read ().decode ()
3664
3765 @classmethod
3866 def look_up_metadata (cls ):
3967 try :
68+ token = cls .__look_up_ec2_api_token ()
4069 return cls (
41- host_name = cls .__look_up_host_name (),
42- host_type = cls .__look_up_instance_type ()
70+ host_name = cls .__look_up_host_name (token ),
71+ host_type = cls .__look_up_instance_type (token )
4372 )
4473 except Exception :
4574 log_exception (logger , "Unable to get Ec2 instance metadata, this is normal when running in a different "
4675 "environment (e.g. Fargate), profiler will still work" )
4776 return None
48-
77+
4978 def serialize_to_map (self ):
5079 return {
51- "computeType" : "aws_ec2_instance" ,
52- "hostName" : self .host_name ,
80+ "computeType" : "aws_ec2_instance" ,
81+ "hostName" : self .host_name ,
5382 "hostType" : self .host_type
5483 }
0 commit comments