策略目标与路线图¶
OpenStack 中的策略长期以来一直是运维人员关注和痛点所在。其实现方式复杂难懂,项目之间不一致,并且缺乏安全的默认设置。
本文档的目的是定义我们在 OpenStack 的策略实现中需要实现的总目标,统一策略术语,并描述实现这些目标以及解决 OpenStack 当前基于角色的访问控制 (RBAC) 实现中的安全漏洞所需的步骤。
问题描述¶
身份和访问管理系统负责根据身份允许或拒绝对服务的资源访问。实现此目的的一种方法是使用基于角色的访问控制 (RBAC)。RBAC 是一种安全模型,它允许通过可以分配给用户或身份的角色来访问资源。
OpenStack 服务在其操作的上下文中基于项目。对于我们的目的而言,可以将项目视为资源的逻辑容器。例如,实例由项目拥有,这意味着该实例应可以从该项目内部访问,但不能从外部访问。这有助于 OpenStack 在单个部署中模拟多个组织,同时保持一定程度的分离或多租户。副作用是这给 OpenStack 的访问控制模型引入了额外的复杂性。整个系统不仅需要了解身份、角色和分配,还需要正确考虑特定操作的范围。
因此,OpenStack 依赖于 RBAC 模型的一个派生版本,非正式地称为基于范围的 RBAC。
基于范围的 RBAC 模型建立在传统 RBAC 的所有假设之上,但在实现中添加了范围的概念。如果 OpenStack 中的所有操作都很好地与项目对齐,这将是 OpenStack 的理想模型。然而,事实并非如此。为了更有效地说明这一点,让我们使用一些示例。
示例一¶
假设我们想创建一个实例。我们已经确定实例应包含在项目中,因此将创建实例的请求的范围应用于我们希望拥有该实例的项目是有意义的(例如,Bob 想要在 Staging 项目中创建一个实例,因此他首先获取一个作用域为 Staging 项目的令牌,并将其与他的计算 API 请求一起发送以获取一个实例)。
这个例子清楚地展示了基于范围的 RBAC 如何与正确映射到项目范围的资源操作配合使用。
示例二¶
让我们看一个相反情况的例子。假设我们想将一个实例从一个计算主机迁移到另一个计算主机,以便进行一些维护。该主机可能负责属于不同项目的实例。您应该将范围限定为哪个项目,以便在不违反多租户关注点分离的情况下,可以对主机进行实例的实时迁移?
这是一个不适合项目结构的操作示例。相反,实时迁移更像是一种与特定项目无关的系统级操作。
总结¶
OpenStack 中的某些操作与项目范围的概念配合良好,而另一些则不然。有关此的更多阅读和上下文,请参阅 bug 968696,该 bug 强调了基于范围的 RBAC 对于 OpenStack 系统级操作和资源的问题。
现有实现的一个更具问题性的副作用是运维人员必须在违反最小权限原则时选择较小的两个邪恶。最小权限原则指出,用户应该只拥有执行其职责所需的权限,不多也不少。当前系统范围和项目范围操作或资源之间的差距迫使运维人员要么授予用户过多的权限,要么不给予用户足够的权限来有效地完成他们的工作。授予过多的权限违反了最小权限原则,但反之亦然,因为过多的限制不允许用户有效地完成他们的工作。
目标¶
以下目标通过减少复杂性、提高互操作性以及消除安全漏洞来提高 OpenStack 的采用率。
通过 admin 角色提供的管理权限应在整个 OpenStack 中得到一致对待。例如,将管理员角色授予项目中的用户不应导致修改端点,因为端点不是特定于项目资源。同样,将管理权限授予部署系统中的用户不应导致能够在特定项目中执行管理操作。
策略到操作的映射应该易于理解、自定义和维护。
在安装或升级时,应该默认提供各种合理的角色。这些角色应与每个项目提供的默认策略相对应。这需要跨项目沟通,以确保这些角色在项目边界内有意义。
以上列表允许运维人员更轻松地完成用例,例如
授予用户对项目的只读访问权限
按项目基础授予用户管理员权限
授予用户对特定项目的特定资源类型的访问权限
未来目标¶
以下目标在讨论中已被多次提出。目前,我们不排除解决这些目标的可能性,但正式将其视为在完成上一节中列出的目标后才解决的事情(例如,您必须先爬行才能行走,然后才能跑步)。
应该能够将资源的细粒度访问权限委派给另一个用户或系统。
应该能够构建自定义策略,这些策略可以考虑用户、资源和范围。这可能会导致策略针对特定资源接收不同的断言。例如,制定一项策略,规定特定用户只能在特定日期访问我的实例,并且只有在他们使用的 SAML 文档中提供特定断言时才能访问。
应该能够确定在考虑角色分配的情况下部署中可用的操作。这需要在不跨 OpenStack 服务复制信息或增加运维人员维护开销的情况下完成。
跨项目影响¶
策略和基于角色的访问控制 (RBAC) 传统上被认为是 OpenStack Identity 范围内的某个问题空间。虽然这种说法在逻辑上是合理的,但当前策略的实现是在整个 OpenStack 服务中强制执行的,这使得问题的所有权更难确定。Keystone 目前仅充当服务的信息点,而服务最终负责根据来自 Keystone 和项目的信息强制执行策略决策。
跨项目解决方案¶
如果对上述目标之一的拟议解决方案需要在项目之间进行协调,我们将使用 社区目标、标签或两者兼而有之。这些工具需要跨项目沟通、支持和承诺。
例如,一个社区目标可能是定义一组默认角色,另一个是在整个服务中一致地实现它们。一旦一个项目测试并实现了标准化的默认集,他们就可以将 assert:basic-rbac 作为项目标签断言。
当以前的解决方案被提出时,这些工具尚不可用。现在我们可以作为社区使用它们,它们非常适合解决复杂的分布式问题,例如一致的 RBAC 强制执行。
路线图¶
本路线图试图描述减轻上述问题所需的步骤,并描绘 OpenStack 中策略的长期愿景。以下每个部分都表示一个序列中的一个工作部分,从而产生所需的最终状态。
重新分类操作与范围¶
基于上一节中的示例操作,一个好的起点可能是重新评估每个操作以及理想的范围应该是什么。这项工作中的大部分可以被认为是为从身份系统消耗正确的范围做准备。理想情况下,在这种情况下,服务的责任应该是将对资源的执行的操作与身份系统提供的范围进行比较(例如,此请求中修改的实例是否属于令牌作用域的项目)。
工作项¶
需要完成以下工作项才能满足此项
在每个服务中将角色检查与范围检查分开。
将范围检查的逻辑隔离到一致的模式或可消耗的库中。
评估每个操作并关联适当的范围或范围。
沟通范围差异¶
下一步,可以与上一步并行进行,就是沟通正确的范围。在当前系统中,只有两个范围真正代表在 OpenStack 中。第一个是 unscoped,可以认为是对一个空操作集进行有效身份验证。第二个是 project-scoped,是对具有特定项目角色的用户的有效身份验证。这些是在 OpenStack 中最常用的范围。但是,身份系统支持另外两个范围。一个是 domain-scoped,是对具有域角色的用户的有效身份验证。另一个是 system-scope,是对具有部署系统角色的用户的有效身份验证,旨在用于访问系统特定资源。
消耗库¶
现在我们有了将角色分配到系统并对令牌进行作用域限定到该上下文的方法,我们需要确保消耗库正确处理这些更改。大多数消耗来自 Keystone 的令牌以强制执行策略的 OpenStack 项目都通过使用 oslo.context 来完成。令牌响应用于使用 oslo.context 构建上下文字典。项目使用上下文字典的属性来对授权范围进行断言。我们需要确保 oslo.context 正确处理新的范围。
进行这些更改后,Keystone 团队将处于一个很好的位置来帮助其他项目消耗这些更改。这可能包括帮助其他项目将其范围检查与角色检查分开,或对操作所需的不同范围进行分类。
工作项¶
为 oslo.context 和 oslo.policy 添加支持,以消耗系统范围的令牌并将该信息中继到生成的上下文中,供项目消耗。
结论¶
最终结果应该包括一种易于使用的机制来授予系统角色,一种清晰的接口来向服务指示范围,以及项目可以使用来评估范围的直接策略模式。
参考资料¶
以下是过去或当前规范的参考