无 IPA 到 conductor 通信

https://storyboard.openstack.org/#!/story/1526486

本规范旨在使 agent->ironic 通信变为可选,而是使用轮询机制使所有通信都变为进入 agent 的入站通信。

问题描述

作为启动过程的一部分,IPA 必须调用 ironic API 来查询其节点 ID,并在完成启动过程时通知 ironic。

这意味着目标节点必须能够访问 ironic API 的网络,这意味着理论上,恶意方可以从实例攻击控制平面。如果相同的控制平面持有 Keystone、Neutron 或其他此类服务,攻击者现在可以进行 DoS 攻击或破坏这些服务。这赋予了他们对基础设施的重大控制权。

部署者可以通过为宿主机使用两个网络来缓解此安全漏洞

  • 一个配置网络,它可以访问 ironic API,但无法与其他数据中心节点通信。

  • 一个租户网络,它可以与外部世界和其他宿主机通信,但无法联系 ironic API。

然而,这对于利用第 3 层网络拓扑的中型到大型部署者来说无法扩展。在 L3 网络中,子网被限制在单个机架内。这意味着为了利用两个网络来镜像宿主机,需要为每个机架配置第二个子网。

更糟糕的是,具有不同基本安全策略的不同网络意味着必须强制执行这些不同的策略。因此,对于需要访问 ironic API 的每个配置网络,都必须配置和强制执行防火墙中的访问控制。

在数百或数千个机架的情况下,这无法扩展。

一个(潜在)安全问题的示例

  • Bob 使用 ironic 启动一个宿主机,该宿主机可以公开路由到互联网。Mallory 找到并破坏了该宿主机。然后她从该宿主机攻击 ironic API。一旦她破坏了 ironic API,她就开始使用受损的磁盘镜像启动数据中心中的其他宿主机。如果 Bob 使用 ironic 来管理数据中心中的每个宿主机,那么 Mallory 现在已经有效地控制了整个数据中心。

为了修复此问题,我们需要减少控制平面的攻击面,方法是消除数据平面能够向 API 宿主机发送流量的需求。为此,我们需要能够告诉 agent 不要调用 ironic,并让 ironic 轮询 agent。

如果部署者运行 DHCPD 并从控制平面提供 PXE/iPXE,那么目标节点和控制平面之间仍然存在逻辑网络访问。但是,这可以通过在专用中间宿主机上运行这些服务来轻松修复,这些宿主机没有访问控制平面其余部分的网络访问权限。

在这种情况下,网络流是

+-----------+     +-----------+     +-------------+
|           |     |           +---> |             |
| Conductor +---> | iPXE host |     | Target node |
|           |     |           | <---+             |
+-----------+     +-----------+     +-------------+
|                                     ^
+-------------------------------------+

配置过程的一个简单示例是

  1. Conductor 接收到启动节点的调用。

  2. Conductor 创建启动数据,不带 ipa-api-url 参数。

  3. Conductor 发送 OOB 调用以打开目标节点电源。

  4. 目标节点启动,使用 DHCP 获取 IP。

  5. 目标节点运行 PXE/iPXE,从 ipxe 宿主机拉取数据。

  6. 目标节点启动并运行 IPA。

  7. Conductor 轮询 IPA 直到其处于活动状态。

  8. Conductor 调用 IPA 的 get_hardware_info 命令以获取有关节点硬件的信息。这用于验证 MAC 地址,以确保这是我们期望的节点。

  9. Conductor 调用 IPA 的 node_info 命令,以向其提供它需要执行其工作的数据,包括查找 API 返回的配置数据。

  10. Conductor 调用目标节点上的 IPA 命令,引导其完成配置过程。

  11. Conductor 以可配置的间隔轮询实例以检查状态、收集信息等。

  12. 目标完成。Conductor 重启目标节点。

  13. Conductor 清理启动数据。

  14. 完成。

一个将此作为安全问题修复的示例

  • Bob 使用 ironic 启动一个宿主机,该宿主机可以公开路由到互联网。Mallory 找到并破坏了该宿主机。她尝试攻击 ironic API。连接超时。她放弃并攻击 iPXE 宿主机。她成功并破坏了 iPXE 宿主机。然后她尝试攻击 ironic API。连接失败。Mallory 失望了,放弃了她的犯罪生活。

在这种情况下,即使 Mallory 破坏了目标节点,目标节点和控制平面之间也没有内在的网络访问。因此,她攻击配置基础设施的唯一途径是 DoS 攻击,或者影响正在启动过程中的宿主机。但她无法攻击队列、conductor、api、db 等。她无法控制基础设施,她的攻击受到了限制。

提议的变更

我们将向 [agent] 类别添加两个选项

  • poll_only:BoolOpt 以启用被动模式。默认值为 False。

  • poll_interval:IntOpt,轮询间隔(秒)。默认值为当前的 [api]/ramdisk_heartbeat_timeout 设置。

以及 [api] 类别中的一个选项

  • disable_agent_api:BoolOpt,禁用 agent 查找和心跳 API。默认值为 False。

如果启用了 poll_only,我们不会将 ipa-api-url 内核命令行参数传递给 IPA,这将禁用节点查找和心跳机制。

如果启用了 poll_only,conductor 将使用定期任务以 ‘poll_interval’ 中定义的间隔查询每个 agent,而不是在收到心跳后查询 agent。此定期任务仅查询处于 IPA 通常会心跳状态的节点:(DEPLOY*, RESCUE*, CLEAN*)。

我们假设部署者应禁止目标节点与 ironic API 之间的通信。但是,如果启用了 disable_agent_api 时收到 API 调用,则 Ironic 应返回 403。

对于此模式,我们还需要删除将 ipa-api-url 作为内核参数传递给 agent。

我们还将向 IPA 添加一个 node_info 命令,如下所述,conductor 将使用它将“查找数据”传递给节点。

最后,我们将向 IPA 添加一个 get_hardware_info 命令,它将返回我们可以用来确保节点是预期节点的硬件信息。

注意事项

  • 本规范依赖于 ironic 可以查找 Neutron 中的节点 IP 的假设。未使用 Neutron 的部署不支持 poll_only=True。未来可能会添加此功能。

  • ironic-inspector 不在此功能的范围内,因为它不使用 Neutron。

  • 可能存在按节点而不是全局设置 poll_only 的用例。但是,这超出了本规范的范围。

备选方案

无。

数据模型影响

状态机影响

REST API 影响

agent 使用的查找和心跳 API 现在将在设置 disable_agent_api 为 True 时返回 403。

客户端 (CLI) 影响

“ironic” CLI

“openstack baremetal” CLI

RPC API 影响

驱动程序 API 影响

部署驱动程序需要确保可以由定期任务触发任何到达某些 agent 的内容。

Nova 驱动程序影响

Ramdisk 影响

ironic-python-agent 大部分已经支持此功能,因为它可以在没有 API URL 的情况下正常运行。

某些步骤可能还需要查找端点返回的其他数据。我们将添加一个新的同步命令 node_info,它将把此数据作为单个 node_info 参数获取并将其存储在内存中以供以后使用。Ironic 会在首次注意到 IPA 处于活动状态时调用此命令。

为了验证节点是预期的节点,我们将添加另一个同步命令 get_hardware_info。它将首先返回 MAC 地址,但以后可以扩展为包括序列号等。

安全影响

此更改将防止恶意行为者使用 IPA 作为针对 ironic API 的攻击媒介。

请注意,agent API 上的 TLS 对于完全保护 IPA 和 Ironic 之间的交互仍然很重要;但是,这超出了本规范的范围。

其他最终用户影响

可扩展性影响

Conductor 轮询目标节点以获取状态可能会在管理数千个节点时出现扩展问题。但是,轮询将在线程池中完成,因此应该影响有限。

性能影响

以大型并行方式进行轮询将给 conductor 节点带来额外的 CPU 负载。部署者可能需要扩展其 conductor 节点以处理额外的负载。

其他部署者影响

添加的配置选项摘要

[agent] * poll_only (type=BoolOpt, default=False) * poll_interval (type=IntOpt, default=<[api]/ramdisk_heartbeat_timeout>)

[api] * disable_agent_api (type=BoolOpt, default=False)

我们应该记录需要在哪里设置这些选项(API 与 conductor 宿主机)。

开发人员影响

实现

负责人

主要负责人

jroll

其他贡献者

penick

工作项

  • 当 ironic 没有传递 ipa-api-url 内核命令行参数时,启用 IPA 跳过查找过程。

  • 创建 IPA 命令 get_hardware_info

  • 创建 IPA 命令 node_info

  • 将新选项添加到 ironic。

  • 启用 Ironic 使用轮询来执行 agent 操作/状态,而不是使用心跳作为触发器。

  • 在轮询模式下,Ironic 在 IPA 启动后调用 node_info 命令。

  • 在轮询模式下禁用 agent 中的心跳。

  • 测试定期任务的规模和性能影响。

  • 大量的文档,尤其是在管理指南中。在参考架构指南中也可能值得一篇大段的文章。

依赖项

无。

测试

我们应该配置现有的一个 tempest 作业来使用此功能。

升级和向后兼容性

部署者必须在升级 Ironic 并启用此功能之前,更新其镜像中的 IPA 以支持被动模式。如果他们不这样做,所有镜像尝试都将失败。

文档影响

需要将此功能记录为部署选项。

需要更新 ironic-inspector 文档,以记录 inspector 不适用于 poll_only=True。

应更新管理文档,以说明需要实施防火墙规则才能实际关闭目标节点与 ironic API 之间的网络访问。

参考资料