代码中的策略¶
https://blueprints.launchpad.net/oslo?searchtext=policy-in-code
长期以来,一直希望将合理的策略默认值嵌入到代码中,并允许策略文件覆盖它们。这将允许部署者仅配置他们想要覆盖的策略,从而减少这些文件的数量和复杂性。它还将允许生成一个示例策略文件,其中包含所有策略的详尽列表。
问题描述¶
这里涉及两个问题
给定一个部署的策略文件,确定它与项目期望的默认值之间的差异并不容易。这是因为没有一个权威的地方可以找到所有策略及其默认值。一些项目提供示例文件,但它们并不总是详尽的。而且,在进行大量修改后,很难将生产策略文件与示例文件进行比较。
给定一个经过身份验证的请求上下文,无法确定哪些策略将通过。这是因为策略检查在代码中是临时的,没有一个中心化的注册表来记录所有可能的检查。而且,策略文件可能没有列出所有策略,因为有些策略可能依赖于默认规则的回退。
提议的变更¶
提议是,代码中应检查的任何策略都可以使用 Enforcer 类进行注册,类似于配置注册的方式。将添加一种新的策略执行方法,如果被检查的策略先前未注册,则会报错。从文件加载策略和策略检查的当前方法不受影响。
注册需要两部分数据
规则名称,例如“compute:get”或“os_compute_api:servers:index”
规则,例如“rule:admin_or_owner”或“role:admin”
注册可以选择性地接受第三部分数据
描述字符串。这可以帮助管理员了解每个策略的信息。
需要规则名称以便后续查找。规则对于设置默认值和生成示例文件是必要的。描述可以作为注释添加到策略示例文件中。
通过将 PolicyOpt 类传递给 Enforcer.register_rule 或 PolicyOpt 列表传递给 Enforcer.register_rules 来完成注册。
例如,基于 Nova 可能会如何使用它
-- nova/policy/create.py
from oslo_policy import policy
from nova import policy as nova_policy
server_policies = [
policy.PolicyOpt(rulename='os_compute_api:servers:create',
rule='rule:admin_or_owner',
description='Checked on POST /servers'),
policy.PolicyOpt(rulename='os_compute_api:servers:create:forced_host',
rule='rule:admin_or_owner',
description='Controls whether the forced_host '
'scheduler hint is allowed.'),
policy.PolicyOpt(rulename='os_compute_api:servers:create:attach_volume',
rule='rule:admin_or_owner',
description='Checks if a volume can be attached '
'during instance create.'),
policy.PolicyOpt(rulename='os_compute_api:servers:create:attach_network',
rule='rule:admin_or_owner',
description='Checks if a network can be attached '
'during instance create.'),
]
policy_engine = nova_policy.get_policy()
# registration will error if a duplicate policy is defined
policy_engine.register_rules(server_policies)
-- nova/api/openstack/compute/servers.py
from nova import policy
policy_engine = policy.get_policy()
def create(self, context):
...
policy_engine.authorize('os_compute_api:servers:create', target, creds)
try:
# This would error because the policy is not registered
policy_engine.authorize(
'os_compute_api:servers:create_not_registered', target, creds)
except:
pass
if volume_to_attach:
policy_engine.authorize(
'os_compute_api:servers:create:attach_volume', target, creds)
对 oslo.policy 的提议更改是,Enforcer 类将获得两种新方法:“register_rule”和“register_rules”。这些方法将处理和存储注册的策略。将修改“load_rules”方法,以将从策略文件中加载的规则与注册的默认值合并。从文件中加载的规则将覆盖注册的默认值。
将更新“authorize”方法,以便尝试检查不存在的规则将导致错误。换句话说,默认规则失去了其特殊状态,并且不是未定义规则的回退。它仍然会作为其他规则使用的参考。
将添加一个 PolicyOpt 类,该类定义要注册的策略。它最初将包含 rulenames、rules 和 descriptions。
要更改的文件
oslo_policy/policy.py
备选方案¶
与其修改 oslo_policy/policy.py 中的 Enforcer 类,不如可以添加一个新的 Policy 类,该类处理注册并包含一个新的“authorize”方法。Policy 类将主要处理策略的注册和存储,并将代理给 Enforcer 以从文件中加载策略并处理实际的执行。随着时间的推移,将从文件中加载策略移出 Enforcer 类并放入 Policy 类可能是有意义的。
Impact on Existing APIs¶
将向 Enforcer 类添加一个新的“register”方法。
安全影响¶
此更改不会产生安全影响。策略的执行方式没有改变,只是策略的加载位置发生了改变。
性能影响¶
从代码注册策略将在注册时产生轻微的性能影响,但这与注册配置选项应该没有区别
Configuration Impact¶
此更改不会直接影响配置。此更改将允许注册了策略的项目无需策略文件即可使用这些默认值。这将允许部署者减少或删除他们的策略文件,如果他们正在运行接近默认值。
开发人员影响¶
在注册策略规则之前使用它们不是必需的,但会受到鼓励。因此,开发人员需要养成在注册后使用该注册的习惯,类似于添加新的配置选项。
Testing Impact¶
单元测试应该足够了。这增加了一种可以被其他项目使用的功能,但它不直接依赖于任何东西。
实现¶
负责人¶
- 主要负责人
alaski
- 其他贡献者
无
里程碑¶
- 完成目标里程碑
newton-1
工作项¶
将 PolicyOpt 类添加到 oslo_policy/policy.py
向 Enforcer 添加“register_rule”方法以进行规则注册
向 Enforcer 添加“register_rules”方法以进行规则注册
更新 Enforcer.load_rules() 以将注册的规则与从文件中加载的规则合并
向 Enforcer 添加“authorize”方法,该方法类似于“enforce”,但如果被检查的策略未注册,则会报错。
孵化¶
N/A
采用¶
Nova 想要使用此功能。
库¶
N/A
预计 API 稳定¶
N/A
文档影响¶
注册策略规则的能力将在面向开发者的文档中记录。任何面向部署者的更改将由使用项目负责记录,因为他们切换到使用策略注册。
依赖项¶
无
参考资料¶
Nova 的此功能规范:https://review.openstack.org/#/c/290155/
注意
本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode