使用 IMDSv2
您可以使用以下其中一种方法,从正在运行的实例中访问实例元数据:
-
实例元数据服务版本 1 (IMDSv1) – 一种请求/响应方法
-
实例元数据服务版本 2 (IMDSv2) – 一种面向会话的方法
默认情况下,您可以使用 IMDSv1 和/或 IMDSv2。实例元数据服务根据以下条件区分 IMDSv1 和 IMDSv2 请求:对于任何给定请求,PUT
或 GET
标头(对于 IMDSv2 是唯一的)在该请求中是否存在。有关更多信息,请参阅借助 EC2 实例元数据服务的增强功能,为开放式防火墙、反向代理和 SSRF 漏洞增加深度防御
您可以在每个实例上配置实例元数据服务,以确保本地代码或用户必须使用 IMDSv2。在指定必须使用 IMDSv2 时,IMDSv1 不再起作用。有关更多信息,请参阅配置实例元数据选项。
要检索实例元数据,请参阅检索实例元数据。
此部分中的示例使用实例元数据服务的 IPv4 地址:169.254.169.254
。如果要通过 IPv6 地址检索 EC2 实例的实例元数据,请确保启用并改用 IPv6 地址:fd00:ec2::254
。实例元数据服务的 IPv6 地址与 IMDSv2 命令兼容。IPv6 地址仅可在 基于 Nitro 系统构建的实例 上访问。
实例元数据服务版本 2 的工作原理
IMDSv2 使用面向会话的请求。对于面向会话的请求,您创建一个会话令牌以定义会话持续时间,该时间最少为 1 秒,最多为 6 小时。在指定的持续时间内,您可以将相同的会话令牌用于后续请求。在指定的持续时间到期后,您必须创建新的会话令牌以用于将来的请求。
以下示例使用 PowerShell Shell 脚本和 IMDSv2 检索顶级实例元数据项。示例:
-
使用
PUT
请求创建持续 6 小时(21600 秒)的会话令牌 -
将会话令牌标头存储在名为
token
的变量中 -
使用令牌请求顶级元数据项
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 访问元数据。 -
将该令牌包含在对实例元数据服务的所有
GET
请求中。如果将令牌使用设置为required
,没有有效令牌或令牌过期的请求将显示401 - Unauthorized
HTTP 错误代码。有关更改令牌使用要求的信息,请参阅 Amazon CLI Command Reference 中的 modify-instance-metadata-options。-
令牌是实例特定的密钥。令牌在其他 EC2 实例上无效,如果尝试在生成令牌的实例外部使用,令牌将会被拒绝。
-
PUT
请求必须包含一个标头,它以秒为单位指定令牌的生存时间 (TTL),最多为 6 小时(21600 秒)。令牌表示一个逻辑会话。TTL 指定令牌的有效时间长度,因而指定会话的持续时间。 -
在令牌过期后,要继续访问实例元数据,您必须使用另一
PUT
创建新会话。 -
您可以选择在每个请求中重复使用令牌或创建新的令牌。对于少量请求,在每次需要访问实例元数据服务时生成并立即使用令牌可能更方便。但为了提高效率,您可以为令牌指定更长的持续时间并重复使用令牌,而不必在每次需要请求实例元数据时都编写
PUT
请求。对并发令牌数量没有实际限制,每个令牌表示自己的会话。不过,IMDSv2 仍然受到正常实例元数据服务连接和限制的制约。有关更多信息,请参阅查询限制。
-
允许在 IMDSv2 实例元数据请求中使用 HTTP GET
和 HEAD
方法。如果 PUT
请求包含 X-Forwarded-For 标头,则会被拒绝。
默认情况下,PUT
请求的响应在 IP 协议级别的响应跃点数限制(生存时间)为 1
。如果需要增大跃点数限制,您可以使用 modify-instance-metadata-options
命令进行调整。例如,您可能需要使用更大的跃点数限制,以便与实例上运行的容器服务保持向后兼容。有关更多信息,请参阅 Amazon CLI Command Reference 中的 modify-instance-metadata-options。
转换为使用 实例元数据服务版本 2
如果迁移到 IMDSv2,我们建议您使用以下工具和转换途径。
帮助转换为 IMDSv2 的工具
如果您的软件使用 IMDSv1,请使用以下工具帮助重新配置软件,以使用 IMDSv2。
- Amazon 软件
-
最新版本的 Amazon CLI 和 Amazon SDK 均支持 IMDSv2。要使用 IMDSv2,请确保您的 EC2 实例具有最新版本的 CLI 和 SDK。有关更新 CLI 的信息,请参阅 Amazon Command Line Interface 用户指南中的安装、更新和卸载 Amazon CLI。
所有的 Amazon Linux 2 软件包都支持 IMDSv2。
有关支持 IMDSv2 的最低 Amazon 开发工具包版本,请参阅 使用支持的 Amazon 开发工具包。
- CloudWatch
-
IMDSv2 使用由令牌支持的会话,而 IMDSv1 不使用。
MetadataNoToken
CloudWatch 指标跟踪对使用 IMDSv1 的实例元数据服务的调用次数。通过查看该指标是否为零,您可以确定是否以及何时将所有软件升级为使用 IMDSv2。有关更多信息,请参阅实例指标。 - EC2 API 和 CLI 更新
-
对于现有实例,您可以使用 modify-instance-metadata-options CLI 命令(或 ModifyInstanceMetadataOptions API)以要求使用 IMDSv2。对于新实例,您可以使用 run-instances CLI 命令(或 RunInstances API)和
metadata-options
参数以启动要求使用 IMDSv2 的新实例。为了要求在 Auto Scaling 组启动的所有新实例上使用 IMDSv2,您的 Auto Scaling 组可以使用启动模板或启动配置。当您创建启动模板或创建启动配置时,必须配置
MetadataOptions
参数以要求使用 IMDSv2。在您配置启动模板或启动配置后,Auto Scaling 组会使用新的启动模板或启动配置启动新实例,但现有实例不受影响。使用 modify-instance-metadata-options CLI 命令(或 ModifyInstanceMetadataOptions API)以要求在现有实例上使用 IMDSv2,或者终止这些实例,这时 Auto Scaling 组会使用在启动模板或启动配置中定义的实例元数据选项设置启动新的替换实例。
- 使用默认配置 IMDSv2 的 AMI
-
启动实例时,您可以使用将
ImdsSupport
参数设置为v2.0
的 AMI 启动该实例,从而自动将其配置为默认使用 IMDSv2(将HttpTokens
参数设置为required
)。可以在使用 register-image CLI 命令注册 AMI 时将ImdsSupport
参数设置为v2.0
。有关更多信息,请参阅配置 AMI。 - IAM policy 和 SCP
-
您可以使用 IAM policy 或 Amazon 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 或 Amazon Organizations 服务控制策略 (SCP) 中使用新的条件键。具体来说,通过在 IAM policy 中使用值为
ec2:RoleDelivery
的条件键2.0
,使用从 IMDSv1 获取的 EC2 角色凭证进行的 API 调用将会收到UnauthorizedOperation
响应。通过使用 SCP 所需的该条件,可以更广泛地实现相同的效果。这会确保通过 IMDSv1 提供的凭证不能实际用于调用 API,因为任何不符合指定条件的 API 调用将会收到UnauthorizedOperation
错误。有关示例 IAM policies,请参阅 使用实例元数据。有关 SCP 的更多信息,请参阅《Amazon Organizations 用户指南》中的 服务控制策略。
-
要求 IMDSv2 访问的建议途径
在使用上述工具时,我们建议您按照以下途径转换为 IMDSv2:
步骤 1:在开始时
将在 EC2 实例上使用角色凭证的 SDK、CLI 和软件更新为与 IMDSv2 兼容的版本。有关更新 CLI 的信息,请参阅 Amazon Command Line Interface 用户指南中的升级到最新版本的 Amazon CLI。
然后,使用 IMDSv2 请求更改直接访问实例元数据的软件(换句话说,不使用开发工具包)。
第 2 步:跟踪转换进度
使用 CloudWatch 指标 MetadataNoToken
跟踪您的转换进度。此指标显示对在实例上使用 IMDSv1 的实例元数据服务的调用次数。有关更多信息,请参阅实例指标。
第 3 步:当 IMDSv1 的使用量为零时
当 CloudWatch 指标 MetadataNoToken
记录的 IMDSv1 使用量为零时,表明您的实例已准备好完全转换到使用 IMDSv2。在此阶段,您可以执行以下操作:
-
新实例
启动新实例时,您可以执行以下操作:
-
Amazon EC2 控制台:在启动实例向导中,将 Metadata accessible(可访问元数据)设置为 Enabled(已启用),将 Metadata version(元数据版本)设置为 V2 only (token required) [仅 V2(必须使用令牌)]。有关更多信息,请参阅在启动时配置实例。
-
Amazon CLI:使用 run-instances CLI 命令指定仅使用 IMDSv2。
-
-
现有实例
您可以通过 modify-instance-metadata-options CLI 命令要求必须使用 IMDSv2。您可以在正在运行的实例上进行这些更改,而无需重新启动实例。
更新现有实例的实例元数据选项的操作只能通过 API 或 Amazon CLI 执行。Amazon EC2 控制台当前不支持此操作。有关更多信息,请参阅配置实例元数据选项。
步骤 4:将所有实例转换为 IMDSv2 时
可以使用 ec2:MetadataHttpTokens
、ec2:MetadataHttpPutResponseHopLimit
和 ec2:MetadataHttpEndpoint
IAM 条件键来控制对 RunInstances 和 ModifyInstanceMetadataOptions API 以及相应 CLI 的使用。如果创建了策略,并且 API 调用中的参数与使用条件键的策略中指定的状态不匹配,API 或 CLI 调用将失败并显示 UnauthorizedOperation
响应。有关示例 IAM policies,请参阅 使用实例元数据。
使用支持的 Amazon 开发工具包
要使用 IMDSv2,EC2 实例必须使用支持 IMDSv2 的 Amazon 开发工具包版本。所有 Amazon 开发工具包的最新版本均支持使用 IMDSv2。
我们建议您及时了解开发工具包版本,以了解其最新功能、安全更新和底层依赖项。不建议继续使用不受支持的开发工具包版本,但是否继续使用由您自行决定。有关更多信息,请参阅《Amazon SDK 和工具参考指南》中的 Amazon SDK 和工具维护策略。
以下是支持使用 IMDSv2 的最低版本:
-
Amazon CLI
– 1.13.23 -
Amazon SDK for .NET
– 3.3.634.1 -
Amazon SDK for C++
– 1.7.229 -
Amazon SDK for Go
– 1.25.38 -
Amazon SDK for Go v2
– 0.19.0 -
Amazon SDK for Java
– 1.11.678 -
Amazon SDK for Java 2.x
– 2.10.21 -
适用于 Node.js 中 JavaScript 的 Amazon 开发工具包
– 2.722.0 -
Amazon SDK for PHP
– 3.147.7 -
Amazon SDK for Python (Boto)
– 1.13.23 -
Amazon SDK for Python (Boto3)
– 1.12.6 -
Amazon SDK for Ruby
– 3.79.0