为什么 EC2 元数据中有时会缺少安全凭证

Why would security credentials sometimes be missing from EC2 metadata

我正在使用 boto 库,版本信息:

boto==2.38.0
botocore==0.81.0

我在 EC2 实例上使用 boto.utils.get_instance_metadata() 它的元数据,以便使用我与该实例关联的安全凭证。有时凭据在 meta_data['iam']['security-credentials']['ROLE_NAME'] 下,但有时 'security-credentials' 只是指向一个空字典。

除了 boto3 之外还有 suggestions/explanations 吗?

刚刚弄明白了,这是因为 boto.utils.get_instance_metadata() return 是 <class 'boto.utils.LazyLoadMetadata'> 的一个实例,而不是真正的 dict。它的内部 dict 结构也是 LazyLoadMetadata 的成员 对于可以延迟获取的数据,此 class 提供的迭代器似乎只有 return items/values 具有已经被显式访问。因为与实例关联的凭据是临时的,所以延迟获取它们是有道理的。

示例:

>>> import boto.utils
>>> meta_data = boto.utils.get_instance_metadata()
>>> creds = meta_data.get('iam', {}).get('security-credentials', {})
>>> debug_vals = list(creds.iteritems())
>>> debug_vals
[('ROLE_NAME', None)]
>>>
>>> creds  # printing the object evaluates/loads the entire 'tree'
{'ROLE_NAME': {u'Code': u'Success', u'LastUpdated': u'2015-10-20T15:19:27Z', u'AccessKeyId': u'AQW...', u'SecretAccessKey': u'LmA...', u'Token': u'AQ...', u'Expiration': u'2015-10-20T21:36:17Z', u'Type': u'AWS-HMAC'}}
>>> 
>>> 
>>> debug_vals  # old instance was already populated, so it won't change
[('ROLE_NAME', None)]
>>>
>>> debug_vals2 = list(creds.iteritems())  # a new call to iteritems gets the fully loaded tree
>>> debug_vals2
[('ROLE_NAME', {u'Code': u'Success', u'LastUpdated': u'2015-10-20T15:19:27Z', u'AccessKeyId': u'AQW...', u'SecretAccessKey': u'LmA...', u'Token': u'AQ...', u'Expiration': u'2015-10-20T21:36:17Z', u'Type': u'AWS-HMAC'}}]
# THE END

因此,如果您直接访问它们,您将找到预期的值。如果你对它们进行迭代,你可能会得到惊喜。