理解 Tacker 策略¶
Tacker 支持 RBAC 策略系统来控制 API 的访问权限。Tacker RBAC 策略规则具有默认值,可以通过 policy.yaml 文件由操作员覆盖。
我们努力使策略默认值尽可能接近操作员的要求。在 Tacker 11.0.0 (OpenStack 2024.1 caracal) 版本中,进一步的工作旨在解决一些已识别的问题
没有只读角色。由于几个 API 倾向于为读写操作共享单个策略规则,因此它们没有提供必要的只读访问角色的粒度。为了解决这个问题,我们应该在策略中拥有 reader 角色。
该
admin_or_owner规则没有按预期工作。它的 check_str"is_admin:True or project_id:%(project_id)s",意味着它仅检查 owner 的 project_id 而不检查任何角色。这意味着 admin_or_owner` 规则将允许项目中具有任何角色的用户。例如,项目中具有role:foo的用户将表现为项目资源的 owner。为了解决这个问题,我们还应该在admin_or_owner规则中检查member角色。
Keystone 默认提供 admin、member 和 reader 角色。请参阅 keystone 文档 以获取有关这些新默认值的更多信息。此外,keystone 支持一个新的“scope”(范围)概念,这使得更容易保护部署级别资源免受项目级别资源的影响。请参阅 keystone 授权范围文档 以了解 scope 概念。
在 Tacker 11.0.0 (OpenStack 2024.1 caracal) 中,Tacker 策略实现了 keystone 提供的新的默认角色(admin、member 和 reader)。使用 keystone 的通用角色可以减少在项目或部署中实现类似但不同的角色的可能性(例如,名为 observer、reader 或 auditor 的角色)。借助新的默认值,更容易理解跨项目谁可以做什么,减少差异,并提高互操作性。除了新的默认值之外,Tacker 策略还定义了 scope_type,该类型被硬编码为 project,以便如果系统范围的 token 尝试访问 Tacker API,它们可以获得更好的错误消息。
以下部分解释了 Tacker 中的这些新默认值如何解决上述两个问题,并以安全可靠的方式为最终用户扩展更多功能。
范围¶
OpenStack Keystone 支持 token 中的不同 scope。Token scope 代表授权层级。Policy scope_types 代表访问 API 所需的授权层级。
注意
每个策略的 scope_type 被硬编码为 project scope,并且无法通过策略文件覆盖。
Tacker 策略通过为所有策略定义 scope_type 为 project scope 来实现 scope 概念。这意味着如果用户尝试使用 system scope 的 token 访问 Tacker API,他们将收到 403 权限被拒绝错误。
例如,考虑 POST /vnflcm/v1/vnf_instances API。
# Creates a new VNF instance resource
# POST /vnflcm/v1/vnf_instances
# Intended scope(s): project
#"os_nfv_orchestration_api:vnf_instances:create": "rule:project_member_or_admin"
策略 scope 默认情况下被禁用,以允许操作员以优雅的方式从旧的策略执行系统中迁移。可以通过在 tacker.conf 的 controller 节点上将 oslo_policy.enforce_scope 选项配置为 True 来启用它。
注意
[oslo_policy] enforce_scope=True
角色¶
您可以参考 keystone 角色文档 以了解 Keystone 中所有可用的默认值。
Tacker 策略为每个策略定义新的默认值。
reader
这为资源提供只读访问权限。Tacker 策略默认设置为以下规则
policy.RuleDefault(
name="admin_api",
check_str="role:admin",
description="Default rule for administrative APIs."
)
policy.RuleDefault(
name="project_reader",
check_str="role:reader and project_id:%(project_id)s",
description="Default rule for Project level read only APIs."
)
在策略规则中使用(具有 admin + reader 访问权限):(因为我们希望保持旧的 admin 行为相同,我们需要为 reader API 提供 admin 角色的访问权限。)
policy.DocumentedRuleDefault(
name='os_nfv_orchestration_api:vnf_instances:show',
check_str='role:admin or (' + 'role:reader and project_id:%(project_id)s)',
description="Query an Individual VNF instance.",
operations=[
{
'method': 'GET',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}'
}
],
scope_types=['project'],
)
OR
policy.DocumentedRuleDefault(
name='os_nfv_orchestration_api:vnf_instances:show',
check_str='rule: admin or rule:project_reader',
description="Query an Individual VNF instance.",
operations=[
{
'method': 'GET',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}'
}
],
scope_types=['project'],
)
member(成员)
project-member 表示项目中具有 member 角色的用户。它旨在由在项目中消耗资源并需要高于 reader 角色但低于 admin 角色的权限的最终用户使用。它继承了 project-reader 的所有权限。
project-member persona 在策略检查字符串中
policy.RuleDefault(
name="admin_api",
check_str="role:admin",
description="Default rule for administrative APIs."
)
policy.RuleDefault(
name="project_member",
check_str="role:member and project_id:%(project_id)s",
description="Default rule for Project level non admin APIs."
)
在策略规则中使用(具有 admin + member 访问权限):(因为我们希望保持旧的 admin 行为,admin 角色可以访问项目级别的 member API。)
policy.DocumentedRuleDefault(
name='os_nfv_orchestration_api:vnf_instances:create',
check_str='role:admin or (' + 'role:member and project_id:%(project_id)s)',
description="Creates vnf instance.",
operations=[
{
'method': 'POST',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}'
}
],
scope_types=['project'],
)
OR
policy.DocumentedRuleDefault(
name='os_nfv_orchestration_api:vnf_instances:create',
check_str='rule: admin or rule:project_member',
description="Query an Individual VNF instance.",
operations=[
{
'method': 'POST',
'path': '/vnflcm/v1/vnf_instances/{vnfInstanceId}'
}
],
scope_types=['project'],
)
check_str 中的 ‘project_id:%(project_id)s’ 对于限制请求项目的访问至关重要。
admin(管理员)
此角色用于执行 admin 级别的写入操作。Tacker 策略默认设置为以下规则
policy.DocumentedRuleDefault(
name='Polciy name',
check_str='role:admin',
scope_types=['project']
)
Tacker 支持的 scope & 角色¶
Tacker 支持以下 scope 和角色的组合,角色可以在 policy.yaml 文件中覆盖,但 scope 无法覆盖。
ADMIN:
admin角色在projectscope 上。这是执行 admin 级别操作的管理员。PROJECT_MEMBER:
member角色在projectscope 上。这用于在项目中执行资源 owner 级别的操作。例如:创建 vnf 实例。PROJECT_READER:
reader角色在projectscope 上。这用于在项目中执行只读操作。例如:获取 vnf 实例。PROJECT_MEMBER_OR_ADMIN:
admin或member角色在projectscope 上。这些策略规则默认设置为大多数 owner 级别 API,并与 member 角色 legacy admin 兼容,可以继续访问这些 API。PROJECT_READER_OR_ADMIN:
admin或reader角色在projectscope 上。这些策略规则默认设置为大多数只读 API,以便 legacy admin 可以继续访问这些 API。
向后兼容性¶
通过默认支持旧默认值,与 Tacker 11.0.0 (OpenStack 2024.1 Caracal) 之前的版本向后兼容。这意味着旧的默认值和使用它们的部署将保持原样。但是,我们鼓励每个部署切换到新的策略。新的默认值将在 Tacker 12.0.0 (OpenStack 2024.2 Dalmatian) 版本中默认启用,但我们将从 Tacker 15.0.0 (OpenStack 2026.1) 版本开始删除旧的默认值。
迁移计划¶
为了实现平滑迁移,Tacker 提供了两个标志来完全切换到新的策略。您无需覆盖策略文件即可采用新的策略默认值。
以下是迁移的分步指南
创建 scope 令牌
您需要通过以下 CLI 创建项目 scope 的令牌
如果尚未完成,请创建 Keystone 中的新默认角色
如果您在 Keystone 中没有新的默认值,则可以创建并重新运行 Keystone Bootstrap。
启用 Scope 检查
oslo_policy.enforce_scope标志用于启用scope_type功能。请求中使用的 token 的 scope 始终与策略的scope_type进行比较。如果 scope 不匹配,可能会发生两种情况。如果oslo_policy.enforce_scope为 True,则请求将被拒绝。如果oslo_policy.enforce_scope为 False,将记录警告,但请求将被接受(假设策略的其余部分通过)。此标志的默认值为 False。启用新的默认值
oslo_policy.enforce_new_defaults标志切换策略到仅新的默认值。此标志控制在评估策略时是否使用旧的弃用默认值。如果为 True,则不会评估旧的弃用默认值。这意味着如果任何现有的 token 允许使用旧的默认值,但新的默认值不允许,则将被拒绝。此标志的默认值为 False。注意
在您启用此标志之前,您需要告知用户他们需要使用的不同角色才能继续使用 Tacker API。
注意
We recommend to enable the both scope as well new defaults together
otherwise you may experience some late failures with unclear error
messages. For example, if you enable new defaults and disable scope
check then it will allow system users to access the APIs but fail
later due to the project check which can be difficult to debug.
下表显示了旧规则如何映射到新规则
旧规则 |
新规则 |
操作 |
scope_type |
|---|---|---|---|
RULE_ADMIN_API |
-> ADMIN |
全局资源写入 & 读取 |
[project] |
RULE_ADMIN_OR_OWNER |
-> ADMIN |
项目 admin 级别操作 |
[project] |
-> PROJECT_MEMBER_OR_ADMIN |
项目资源写入 |
[project] |
|
-> PROJECT_READER_OR_ADMIN |
项目资源读取 |
[project] |
我们预计所有部署将在 Tacker 13.0.0 (OpenStack 2025.1) 版本之前迁移到新的策略,以便我们可以在未来的版本中删除对旧策略的支持。