使用实例元数据服务访问实例元数据
您可以使用以下其中一种方法,从正在运行的实例中访问实例元数据:
-
实例元数据服务版本 2 (IMDSv2) – 一种面向会话的方法
有关示例,请参阅IMDSv2 的示例。
-
实例元数据服务版本 1 (IMDSv1) – 一种请求/响应方法
有关示例,请参阅IMDSv1 的示例。
默认情况下,您可以使用 IMDSv1 和/或 IMDSv2。
您可以在每个实例上配置实例元数据服务(IMDS),以确保本地代码或用户必须使用 IMDSv2。在指定必须使用 IMDSv2 时,IMDSv1 不再起作用。有关如何配置实例以使用 IMDSv2 的信息,请参阅 配置实例元数据服务选项。
PUT
或 GET
标头对于 IMDSv2 是唯一的。如果请求中存在这些标头,则该请求针对 IMDSv2。如果不存在标头,则假定该请求针对 IMDSv1。
有关 IMDSv2 的详细回顾,请参阅借助 EC2 实例元数据服务的增强功能,为开放式防火墙、反向代理和 SSRF 漏洞增加深度防御
实例元数据服务版本 2 的工作原理
IMDSv2 使用面向会话的请求。对于面向会话的请求,您创建一个会话令牌以定义会话持续时间,该时间最少为 1 秒,最多为 6 小时。在指定的持续时间内,您可以将相同的会话令牌用于后续请求。在指定的持续时间到期后,您必须创建新的会话令牌以用于将来的请求。
注意
本部分中的示例使用实例元数据服务(IMDS)的 IPv4 地址:169.254.169.254
。如果要通过 IPv6 地址检索 EC2 实例的实例元数据,请确保启用并改用 IPv6 地址:[fd00:ec2::254]
。IMDS 的 IPv6 地址与 IMDSv2 命令兼容。IPv6 地址只能在基于 AWS Nitro System 构建的实例上和支持 IPv6 的子网(仅限双堆栈或 IPv6)中访问。
以下示例使用 Shell 脚本和 IMDSv2 检索顶级实例元数据项。每个示例:
-
使用
PUT
请求创建持续 6 小时(21600 秒)的会话令牌 -
将会话令牌标头存储在名为
TOKEN
(Linux 实例)或token
(Windows 实例)的变量中 -
使用令牌请求顶级元数据项
您可以运行两个单独的命令,也可以将它们组合使用。
单独的命令
首先,使用以下命令生成令牌。
[ec2-user ~]$
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
然后,通过令牌使用以下命令生成顶级元数据项。
[ec2-user ~]$
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
组合命令
您可以存储令牌并组合命令。以下示例将上述两个命令组合在一起,并将会话令牌标头存储在名为 TOKEN 的变量中。
注意
如果创建令牌时发生错误,则不会生成有效令牌,而会在变量中存储一条错误消息,该命令将不起作用。
[ec2-user ~]$
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \ && curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
在创建令牌后,您可以重复使用令牌,直到令牌过期。在以下示例命令(获取用于启动实例的 AMI 的 ID)中,将重复使用上一示例中的令牌(存储在 $TOKEN
中)。
[ec2-user ~]$
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-id
PS C:\>
[string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
PS C:\>
Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/
在创建令牌后,您可以重复使用令牌,直到令牌过期。在以下示例命令(获取用于启动实例的 AMI 的 ID)中,将重复使用上一示例中的令牌(存储在 $token
中)。
PS C:\>
Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} ` -Method GET -uri http://169.254.169.254/latest/meta-data/ami-id
在使用 IMDSv2 请求实例元数据时,请求必须包含以下内容:
-
使用
PUT
请求启动到实例元数据服务的会话。PUT
请求返回一个令牌,该令牌必须包含在对实例元数据服务的后续GET
请求中。需要具有该令牌才能使用 IMDSv2 访问元数据。 -
将该令牌包含在对 IMDS 的所有
GET
请求中。如果将令牌使用设置为required
,没有有效令牌或令牌过期的请求将显示401 - Unauthorized
HTTP 错误代码。-
令牌是实例特定的密钥。令牌在其他 EC2 实例上无效,如果尝试在生成令牌的实例外部使用,令牌将会被拒绝。
-
PUT
请求必须包含一个标头,它以秒为单位指定令牌的生存时间 (TTL),最多为 6 小时(21600 秒)。令牌表示一个逻辑会话。TTL 指定令牌的有效时间长度,因而指定会话的持续时间。 -
在令牌过期后,要继续访问实例元数据,您必须使用另一
PUT
创建新会话。 -
您可以选择在每个请求中重复使用令牌或创建新的令牌。对于少量请求,每次需要访问 IMDS 时生成令牌并立即使用可能会更容易。但为了提高效率,您可以为令牌指定更长的持续时间并重复使用令牌,而不必在每次需要请求实例元数据时都编写
PUT
请求。对并发令牌数量没有实际限制,每个令牌表示自己的会话。不过,IMDSv2 仍然受到正常 IMDS 连接和节流限制的制约。有关更多信息,请参阅 查询限制。
-
允许在 IMDSv2 实例元数据请求中使用 HTTP GET
和 HEAD
方法。如果 PUT
请求包含 X-Forwarded-For 标头,则会被拒绝。
默认情况下,PUT
请求的响应在 IP 协议级别的响应跃点数限制(生存时间)为 1
。如果需要更大的跃点数限制,可使用 modify-instance-metadata-options AWS CLI 命令进行调整。例如,您可能需要使用更大的跃点数限制,以便与实例上运行的容器服务保持向后兼容。有关更多信息,请参阅 为现有实例修改实例元数据选项。
转换为使用 实例元数据服务版本 2
如果迁移到 IMDSv2,我们建议您使用以下工具和转换途径。
帮助转换为 IMDSv2 的工具
如果您的软件使用 IMDSv1,请使用以下工具帮助重新配置软件,以使用 IMDSv2。
- AWS 软件
-
最新版本的 AWS CLI 和 AWS SDK 均支持 IMDSv2。要使用 IMDSv2,请确保您的 EC2 实例具有最新版本的 CLI 和 SDK。有关更新 CLI 的信息,请参阅 AWS Command Line Interface 用户指南中的安装、更新和卸载 AWS CLI。
所有的 Amazon Linux 2 和 Amazon Linux 2023 软件包都支持 IMDSv2。在 Amazon Linux 2023 中,默认情况下禁用 IMDSv1。
有关支持 IMDSv2 的最低 AWS 开发工具包版本,请参阅 使用支持的 AWS 开发工具包。
- IMDS Packet Analyzer
-
IMDS Packet Analyzer 是一个开源工具,用于识别和记录您的实例启动阶段的 IMDSv1 调用。这可以帮助识别在 EC2 实例上调用 IMDSv1 的软件,让您能够准确地确定需要更新的内容,以使您的实例准备好仅使用 IMDSv2。您可以从命令行运行 IMDS Packet Analyzer,也可以将其作为服务安装。有关更多信息,请参阅 GitHub 上的 IMDS Packet Analyzer
。 - CloudWatch
-
IMDSv2 使用由令牌支持的会话,而 IMDSv1 不使用。
MetadataNoToken
CloudWatch 指标跟踪对使用 IMDSv1 的实例元数据服务(IMDS)的调用次数。通过查看该指标是否为零,您可以确定是否以及何时将所有软件升级为使用 IMDSv2。禁用 IMDSv1 后,您可以使用
MetadataNoTokenRejected
CloudWatch 指标来跟踪 IMDSv1 调用被尝试和拒绝的次数。通过跟踪该指标,您可以确定您的软件是否需要更新以使用 IMDSv2。有关更多信息,请参阅 实例指标。
- EC2 API 和 CLI 更新
-
对于新实例,您可以使用 RunInstances API 以启动要求使用 IMDSv2 的新实例。有关更多信息,请参阅 为新实例配置实例元数据选项。
对于现有实例,您可以使用 ModifyInstanceMetadataOptions API 以要求使用 IMDSv2。有关更多信息,请参阅 为现有实例修改实例元数据选项。
为了要求在 Auto Scaling 组启动的所有新实例上使用 IMDSv2,您的 Auto Scaling 组可以使用启动模板或启动配置。当您创建启动模板或创建启动配置时,必须配置
MetadataOptions
参数以要求使用 IMDSv2。自动扩缩组将使用新的启动模板或启动配置来启动新实例,但现有实例不受影响。对于自动扩缩组中的现有实例,您可以使用 ModifyInstanceMetadataOptions API 以要求在现有实例上使用 IMDSv2,或者终止实例,自动扩缩组将使用在新的启动模板或启动配置中定义的实例元数据选项设置启动新的替换实例。 - 使用默认配置 IMDSv2 的 AMI
-
启动实例时,您可以使用将
ImdsSupport
参数设置为v2.0
的 AMI 启动该实例,从而自动将其配置为默认使用 IMDSv2(将HttpTokens
参数设置为required
)。您可以在使用 register-image CLI 命令注册 AMI 时将ImdsSupport
参数设置为v2.0
,也可以使用 modify-image-attribute CLI 命令修改现有的 AMI。有关更多信息,请参阅 配置 AMI。 - IAM policy 和 SCP
-
您可以使用 IAM policy 或 AWS Organizations 服务控制策略(SCP)来控制用户,具体如下所示:
-
除非将实例配置为使用 IMDSv2,否则无法使用 RunInstances API 启动实例。
-
无法使用 ModifyInstanceMetadataOptions API 修改正在运行的实例以重新启用 IMDSv1。
IAM policy 或 SCP 必须包含以下 IAM 条件键:
-
ec2:MetadataHttpEndpoint
-
ec2:MetadataHttpPutResponseHopLimit
-
ec2:MetadataHttpTokens
如果 API 或 CLI 调用中的参数与包含该条件键的策略中指定的状态不一致,则 API 或 CLI 调用将失败并显示
UnauthorizedOperation
响应。此外,您还可以选择额外的保护层以强制从 IMDSv1 更改为 IMDSv2。在与通过 EC2 角色凭证调用的 API 相关的访问管理层上,您可以在 IAM policy 或 AWS Organizations 服务控制策略 (SCP) 中使用新的条件键。具体来说,通过在 IAM policy 中使用值为
ec2:RoleDelivery
的条件键2.0
,使用从 IMDSv1 获取的 EC2 角色凭证进行的 API 调用将会收到UnauthorizedOperation
响应。通过使用 SCP 所需的该条件,可以更广泛地实现相同的效果。这会确保通过 IMDSv1 提供的凭证不能实际用于调用 API,因为任何不符合指定条件的 API 调用将会收到UnauthorizedOperation
错误。有关示例 IAM policies,请参阅 使用实例元数据。有关 SCP 的更多信息,请参阅《AWS Organizations 用户指南》中的 服务控制策略。
-
要求 IMDSv2 的建议途径
在使用上述工具时,我们建议您按照以下途径转换为 IMDSv2。
步骤 1:在开始时
将在 EC2 实例上使用角色凭证的 SDK、CLI 和软件更新为与 IMDSv2 兼容的版本。有关更新 CLI 的信息,请参阅 AWS Command Line Interface 用户指南中的升级到最新版本的 AWS CLI。
然后,使用 IMDSv2 请求更改直接访问实例元数据的软件(换句话说,不使用开发工具包)。您可以使用 IMDS Packet Analyzer
第 2 步:跟踪转换进度
使用 CloudWatch 指标 MetadataNoToken
跟踪您的转换进度。此指标显示对实例上 IMDS 的 IMDSv1 调用次数。有关更多信息,请参阅 实例指标。
第 3 步:当 IMDSv1 的使用量为零时
当 CloudWatch 指标 MetadataNoToken
记录的 IMDSv1 使用量为零时,表明您的实例已准备好完全转换到使用 IMDSv2。在此阶段,您可以执行以下操作:
-
账户默认值
可将 IMDSv2 设置为必需的账户默认值。启动实例时,实例配置会自动设置为账户默认值。
要设置账户默认值,请执行以下操作:
-
Amazon EC2 控制台:对于 IMDS 默认设置,在 EC2 控制面板上的账户属性、数据保护和安全下,将实例元数据服务设置为已启用,并将元数据版本设置为仅 V2(需要令牌)。有关更多信息,请参阅 将 IMDSv2 设置为账户默认设置。
-
AWS CLI:使用 modify-instance-metadata-defaults CLI 命令并指定
--http-tokens required
和--http-put-response-hop-limit
。2
-
-
新实例
启动新实例时,您可以执行以下操作:
-
Amazon EC2 控制台:在启动实例向导中,将 Metadata accessible(可访问元数据)设置为 Enabled(已启用),将 Metadata version(元数据版本)设置为 V2 only (token required) [仅 V2(必须使用令牌)]。有关更多信息,请参阅 在启动时配置实例。
-
AWS CLI:使用 run-instances CLI 命令并指定需要使用 IMDSv2。
-
-
现有实例
对于现有实例,您可以执行以下操作:
-
Amazon EC2 控制台:在实例页面上选择实例,然后依次选择操作、实例设置、修改实例元数据选项,对于 IMDSv2,选择必需。有关更多信息,请参阅 要求使用 IMDSv2。
-
AWS CLI:使用 modify-instance-metadata-options CLI 命令指定仅使用 IMDSv2。
您可以在正在运行的实例上修改实例元数据选项,并且修改后无需重新启动实例。
-
步骤 4:检查实例是否切换为 IMDSv2
您可以检查是否有任何实例尚未配置为要求使用 IMDSv2,换言之,IMDSv2 仍配置为 optional
。如果仍有实例配置为 optional
,则可通过重复上述步骤 3 来修改实例元数据选项,以将 IMDSv2 配置为 required
。
筛选实例:
-
Amazon EC2 控制台:在实例页面,使用 IMDSv2 = 可选筛选条件来筛选实例。有关筛选的更多信息,请参阅 使用控制台筛选资源。您还可以查看 IMDSv2 对每个实例是必需的还是可选的:在首选项窗口中,打开 IMDSv2,以将 IMDSv2 列添加到实例表中。
-
AWS CLI:使用 describe-instances CLI 命令并按
metadata-options.http-tokens = optional
进行筛选,如下所示:aws ec2 describe-instances --filters "Name=metadata-options.http-tokens,Values=optional" --query "Reservations[*].Instances[*].[InstanceId]" --output text
步骤 5:当所有实例已切换为 IMDSv2
ec2:MetadataHttpTokens
、ec2:MetadataHttpPutResponseHopLimit
和 ec2:MetadataHttpEndpoint
IAM 条件键可用于控制 RunInstances 和 ModifyInstanceMetadataOptions API 及相应 CLI 的使用。如果创建了策略,并且 API 调用中的参数与使用条件键的策略中指定的状态不匹配,API 或 CLI 调用将失败并显示 UnauthorizedOperation
响应。有关示例 IAM policies,请参阅 使用实例元数据。
此外,禁用 IMDSv1 后,您可以使用 MetadataNoTokenRejected
CloudWatch 指标来跟踪 IMDSv1 调用被尝试和拒绝的次数。如果在禁用 IMDSv1 后,您的软件无法正常运行,并且 MetadataNoTokenRejected
指标记录了 IMDSv1 调用,则可能需要更新此软件才能使用 IMDSv2。
使用支持的 AWS 开发工具包
要使用 IMDSv2,EC2 实例必须使用支持 IMDSv2 的 AWS 开发工具包版本。所有 AWS 开发工具包的最新版本均支持使用 IMDSv2。
重要
我们建议您及时了解开发工具包版本,以了解其最新功能、安全更新和底层依赖项。不建议继续使用不受支持的开发工具包版本,但是否继续使用由您自行决定。有关更多信息,请参阅《AWS SDK 和工具参考指南》中的 AWS SDK 和工具维护策略。
以下是支持使用 IMDSv2 的最低版本:
-
AWS CLI
– 1.16.289 -
AWS Tools for Windows PowerShell
– 4.0.1.0 -
AWS SDK for .NET
– 3.3.634.1 -
AWS SDK for C++
– 1.7.229 -
AWS SDK for Go
– 1.25.38 -
AWS SDK for Go v2
– 0.19.0 -
AWS SDK for Java
– 1.11.678 -
AWS SDK for Java 2.x
– 2.10.21 -
适用于 Node.js 中 JavaScript 的 AWS 开发工具包
– 2.722.0 -
AWS SDK for PHP
– 3.147.7 -
适用于 Python (Botocore) 的 AWS SDK
– 1.13.25 -
AWS SDK for Python (Boto3)
– 1.12.6 -
AWS SDK for Ruby
– 3.79.0
IMDSv2 的示例
在您的 Amazon EC2 实例上运行以下示例,以检索 IMDSv2 的实例元数据。
在 Windows 实例上,您可以使用 Windows PowerShell,也可以安装 cURL 或 wget。如果您在 Windows 实例上安装第三方工具,请确保您仔细阅读随附的文档,因为调用和输出格式可能与此处所述的内容不同。
示例
获取实例元数据的可用版本
此示例可以获取实例元数据的可用版本。当有新的实例元数据类别发布时,每个版本都引用一个实例元数据构建。实例元数据构建版本与 Amazon EC2 API 版本不相关。如果您有依赖于以前版本中所存在的结构和信息的脚本,则您可使用早期版本。
获取顶级元数据项
此示例获得顶级元数据项目。有关响应中项目的更多信息,请参阅 实例元数据类别。
请注意,只有在允许您访问的情况下,标签才会包含在此输出中。有关更多信息,请参阅 允许访问实例元数据中的标签。
获取元数据项的值
这些示例获取在前面示例中获取的某些顶级元数据项的值。这些请求使用在前面的示例中使用命令创建的存储令牌。令牌不得过期。
获取可用的公有密钥列表
此示例获得可用公有密钥的列表。
显示可以使用公有密钥 0 的格式
此示例显示了可以使用公有密钥 0 的格式。
获取公有密钥 0(采用 OpenSSH 密钥格式)
此示例获得公有密钥 0 (以 OpenSSH 密钥格式)。
获取实例的子网 ID
此示例获取实例的子网 ID。
获取实例的实例标签
如果对实例元数据中的实例标签的访问权限已开启,则可以从实例元数据中获得实例标签。有关更多信息,请参阅 从实例元数据中检索标签。
IMDSv1 的示例
在您的 Amazon EC2 实例上运行以下示例,以检索 IMDSv1 的实例元数据。
在 Windows 实例上,您可以使用 Windows PowerShell,也可以安装 cURL 或 wget。如果您在 Windows 实例上安装第三方工具,请确保您仔细阅读随附的文档,因为调用和输出格式可能与此处所述的内容不同。
示例
获取实例元数据的可用版本
此示例可以获取实例元数据的可用版本。当有新的实例元数据类别发布时,每个版本都引用一个实例元数据构建。实例元数据构建版本与 Amazon EC2 API 版本不相关。如果您有依赖于以前版本中所存在的结构和信息的脚本,则您可使用早期版本。
获取顶级元数据项
此示例获得顶级元数据项目。有关响应中项目的更多信息,请参阅 实例元数据类别。
请注意,只有在允许您访问的情况下,标签才会包含在此输出中。有关更多信息,请参阅 允许访问实例元数据中的标签。
获取元数据项的值
这些示例获取在先前示例中获取的某些顶级元数据项的值。
获取可用的公有密钥列表
此示例获得可用公有密钥的列表。
显示可以使用公有密钥 0 的格式
此示例显示了可以使用公有密钥 0 的格式。
获取公有密钥 0(采用 OpenSSH 密钥格式)
此示例获得公有密钥 0 (以 OpenSSH 密钥格式)。
获取实例的子网 ID
此示例获取实例的子网 ID。
获取实例的实例标签
如果对实例元数据中的实例标签的访问权限已开启,则可以从实例元数据中获得实例标签。有关更多信息,请参阅 从实例元数据中检索标签。