如何创建自定义平台角色
目录
1. 概述2. 核心概念3. 技术变更4. 选择方法5. 配置5.1 方法 A:FunctionResource5.2 方法 B:ClusterRole 聚合(独立自定义角色)5.3 方法 C:customRules5.4 字段参考5.5 验证配置是否实际生效检查 RoleTemplate 状态确认用户确实获得权限在写入aggregationRules 前检查聚合标签是否可用5.6 更新和删除6. 复制并精简(示例)6.1 精简系统 RoleTemplate YAML(方法 A)6.2 构建多范围审计员角色(方法 B)1. 概述
本文介绍自定义角色的核心概念,以及如何配置 RoleTemplate。构建可用自定义角色主要有两种方式——任选一种并完整执行:
- FunctionResource 方法(5.1):从产品内置的权限目录中选择权限。最简单的选项,无需编写 RBAC。
- ClusterRole 聚合方法(5.2):编写自己的原生
ClusterRole,并通过标签匹配将其引入 RoleTemplate。配置较为复杂,但不受任何产品模块迁移进度的影响,并且是平台的长期发展方向。
customRules(5.3)是第三种更底层的选项,用于一次性使用的原生 RBAC 规则。
不知道该选择哪一种? 请从方法 A(5.1)开始——这是最简单的方式,几乎可以满足所有需求。只有在明确需要使用自有 ClusterRole 构建角色,或需要构建跨多个集群的角色时,才选择方法 B(5.2)。
RoleTemplate 创建后,可通过 UserBinding 将其授予用户——控制台操作步骤请参阅管理角色。
2. 核心概念
- RoleTemplate:自定义角色模板。它定义角色语义和权限集,控制器会将其转换为 ClusterRole。
- FunctionResource:产品功能使用的 K8s 资源抽象;在 RoleTemplate 中通过
functionResourceRef引用。 - ClusterRole:RBAC 规则集。手动编写的 ClusterRole 可以通过标签聚合到 RoleTemplate(或内置系统角色)中。
- UserBinding:用户与角色/作用域之间的绑定;控制器会根据 UserBinding 生成 RoleBinding/ClusterRoleBinding,以完成最终授权。
functionResourceRef的值来自 FunctionResourcemetadata.name。- 显示名称通常位于
metadata.annotations中,可用于映射到 UI 模块。
3. 技术变更
自 ACP v4.3 起,功能权限正逐步从 FunctionResource 迁移到原生 K8s ClusterRole 管理,并通过 ClusterRole 标签聚合到系统角色中;基于 FunctionResource 的管理方式将在 v4.5 中弃用。创建角色不需要了解这些背景——请跳转到第 5 节查看具体步骤。
迁移仍在进行中:大多数产品模块尚未发布可用于聚合的 ClusterRole,因此 5.4 中提到的内置系统标签(aggregate-to-namespace-developer 等)目前不会匹配到任何内容。不要将 aggregationRules 指向其中一个标签并寄希望于它能生效——5.2 展示了可行的模式,5.5 介绍了验证方法。(你还可能会在 kubectl 输出中看到隐藏的 legacy-* RoleTemplate;这些是内置角色的兼容性桥接对象,可以忽略。)
4. 选择方法
这三种方法都可以生成可正常工作的 RoleTemplate;区别在于需要编写的内容以及它们能够表达的权限范围。
5. 配置
始终在自定义 RoleTemplate 上设置 rbac.cpaas.io/version: "v2" 和 auth.cpaas.io/roletemplate.frozen: "false"。 对于自定义角色,控制器会将缺失的 version 自动填充为 v1(该值会忽略 aggregationRules),并将缺失的 frozen 自动填充为 true(该值会阻止后续对 spec 的编辑更新 ClusterRole),且两者独立处理——因此只设置其中一个,另一个仍会保留旧版默认值。以下示例还设置了 auth.cpaas.io/roletemplate.official: "false"(可选,但在自定义角色上切勿将其设置为 "true"——这会将其切换为内置系统角色)和 auth.cpaas.io/roletemplate.level,后者决定角色的授予范围——请选择满足需求的最小范围:namespace(每个命名空间)、project(项目中的所有命名空间)、cluster(整个集群)或 platform(整个平台)。
5.1 方法 A:FunctionResource
当所需权限已经通过 FunctionResource 公开时,请使用此方法——目前几乎所有产品模块都属于这种情况。
步骤 1——查找所需的 FunctionResource
metadata.name 就是要填入 functionResourceRef 的值;显示名称注解会告诉你它映射到哪个 UI 功能。
步骤 2——编写 RoleTemplate
步骤 3——应用并验证,请参阅 5.5。
自定义角色中不允许使用 acp-namespace-resource-manage。
5.2 方法 B:ClusterRole 聚合(独立自定义角色)
与 FunctionResource 方法不同,aggregationRules 本身不定义权限——它只会从带有匹配标签的现有 ClusterRole 中引入 rules。要通过这种方式构建真正独立的自定义角色,需要自行提供两个部分:包含实际规则的 ClusterRole,以及将其连接到 RoleTemplate 的标签。
步骤 1——使用实际权限编写原生 ClusterRole,并为其添加自定义聚合标签和作用域标签。除非你明确希望将这些权限授予已经持有该内置角色的所有用户,否则不要重复使用内置系统角色标签(5.4);对于独立角色,请自行创建标签名称。
步骤 2——如果该角色还需要在工作负载集群中生效,且上面的 ClusterRole 只在 global 集群中创建,请添加 rbac.cpaas.io/sync.scope: "platform",以便平台将其复制到每个集群。如果没有此标签,ClusterRole 只会存在于创建它的位置,而下面的 RoleTemplate 在任何没有该 ClusterRole 的集群上都会解析为空权限。
步骤 3——创建 RoleTemplate,通过 aggregationRules 引用相同的标签:
要涵盖多个作用域(例如还包括 cluster 或 system-ns),请为每个作用域添加一个带有匹配作用域标签的 ClusterRole,并在 aggregationRules 下为每个作用域再添加一项——请参阅 6.2 中完整的多作用域示例。
步骤 4——应用并验证,请参阅 5.5。结果为空表示 ClusterRole 上的标签与 clusterRoleSelectors 中的标签实际上不匹配,或者 ClusterRole 尚未同步到你正在检查的集群(步骤 2)。
不要将 aggregationRules 指向你希望存在的系统/产品标签(例如 rbac.cpaas.io/aggregate-to-namespace-auditor)——大多数模块尚未发布自己的标签,因此解析结果为空,角色也会静默地不授予任何权限。如上所示,使用自有 ClusterRole 和自有标签始终有效。
5.3 方法 C:customRules
对于无需单独 ClusterRole 对象的一次性原生 RBAC 规则,可以直接将其内联到 RoleTemplate 中:
customRules 只会写入角色的基础 ClusterRole——无法将其定向到特定作用域,例如 cluster 或 system-ns(customRules 上不存在 scope 字段)。如果需要跨作用域规则,请使用方法 A 或方法 B。
5.4 字段参考
第一个表格介绍元数据以及每个自定义角色都需要的标签;第二个表格介绍权限字段,并按照所属方法(5.1–5.3)进行分组。
元数据和标签(每个自定义 RoleTemplate 都需要)
权限字段(根据所用方法选择相应字段集)
- 对于给定作用域,请使用直接规则(
spec.rules/spec.customRules)或spec.aggregationRules,不要同时使用两者——当它们在同一个生成的 ClusterRole 上发生重叠时,聚合规则优先,直接规则会被丢弃。 auth.cpaas.io/roletemplate.level(角色被授予的范围——platform/cluster/project/namespace)与spec.aggregationRules[].scope(每个聚合规则要写入的生成 ClusterRole)是不同的概念。控制器会强制执行以下约束:platform级和cluster级角色只能使用scope: cluster;project级和namespace级角色可以使用五种作用域中的任意一种(包括cluster)。违反此规则会使 RoleTemplate 进入Failed状态。
用于 matchLabels 的标签
对于独立自定义角色,请自行创建聚合标签——任何 rbac.cpaas.io/aggregate-to-<name> 字符串都可以(5.2)。将其与一个作用域标签配对,该标签控制规则的适用范围:
rbac.cpaas.io/aggregate-to-scope-cluster: "true"rbac.cpaas.io/aggregate-to-scope-project-ns: "true"rbac.cpaas.io/aggregate-to-scope-business-ns: "true"rbac.cpaas.io/aggregate-to-scope-system-ns: "true"rbac.cpaas.io/aggregate-to-scope-kube-public: "true"
若要向内置系统角色添加权限(高级操作——这会将权限授予所有已持有该角色的用户),请为您的 ClusterRole 添加 rbac.cpaas.io/aggregate-to-<built-in-role> 标签,例如 aggregate-to-namespace-developer 或 aggregate-to-platform-admin。
多集群分发(5.2 第 2 步):将 rbac.cpaas.io/sync.scope: "platform" 添加到您手动创建的 ClusterRole,以便将其从 global 集群复制到所有集群。它对 RoleTemplate 或 RoleTemplate 生成的 ClusterRole 没有影响。
5.5 验证配置是否实际生效
检查 RoleTemplate 状态
RoleTemplate 会报告其生成的内容以及是否已同步——请从这里开始:
status.phase 应为 Ready;status.clusterRoles 列出其生成的 ClusterRole;status.conditions 在发生故障时包含原因/消息。如果阶段不是 Ready、status.clusterRoles 为空,或其列出的 ClusterRole 的 rules(kubectl get clusterrole <name> -o yaml)为空,则该角色未授予您预期的权限。常见原因如下,按大致发生频率排序:
- RoleTemplate 缺少
rbac.cpaas.io/version: "v2",或已被自动冻结——请参阅第 5 节中关于必需标签的注意事项。这是aggregationRules看似不起作用的最常见原因。 functionResourceRef名称拼写错误——控制器会静默跳过未知引用,并生成一个没有错误但内容为空的 ClusterRole。- 您的
aggregationRules标签未匹配任何 ClusterRole,或者源 ClusterRole 尚未同步到此集群。
确认用户确实获得权限
生成 ClusterRole 不是最终目标——最终目标是让用户获得访问权限。通过 UserBinding 授予角色后(请参阅管理角色),使用模拟用户检查确认实际结果:
在写入 aggregationRules 前检查聚合标签是否可用
在 clusterRoleSelectors 中引用 rbac.cpaas.io/aggregate-to-* 标签之前,请确认它确实能解析为 ClusterRole:
- 无输出 → 没有 ClusterRole 携带此标签。如果您使用的是自己的自定义标签(5.2),请仔细检查该标签是否确实已应用于您的 ClusterRole,以及它是否已同步到此集群。如果您使用的是系统标签(5.4),并希望某个产品模块已发布该标签,则它很可能尚未发布——请参阅第 3 节。
- 输出显示
auth.cpaas.io/roletemplate的legacy-*值 → 此 ClusterRole 来自第 3 节所述的基于 FunctionResource 的兼容性桥接,而不是来自已实际迁移的模块。权限仍来源于 FunctionResource,并且预计此桥接将在 v4.5 中移除。
5.6 更新和删除
- 更新:编辑 RoleTemplate 的
spec。只有在auth.cpaas.io/roletemplate.frozen为"false"时,更改才会生效(请参阅第 5 节中的注意事项)。 - 删除:删除 RoleTemplate。控制器会在所有集群中垃圾回收其生成的 ClusterRole——您无需手动清理这些资源。(通过方法 B 手动创建的 ClusterRole 由您负责删除。)
6. 复制并精简(示例)
两个完整示例:精简内置模板(方法 A,6.1),以及使用您自己的 ClusterRole 构建多范围角色(方法 B,6.2)。对于 FunctionResource 角色,复制内置系统模板并精简,是避免遗漏模块权限的最快方法。
6.1 精简系统 RoleTemplate YAML(方法 A)
步骤:
- 保留必需的 FunctionResource。
- 将动词缩减为只读操作(get/list/watch)。
- 移除未使用的模块。
角色示例:没有 Secret 权限的开发人员审计员
- 在自定义角色中,不要配置 Namespace Resource Management(FunctionResource:
acp-namespace-resource-manage)。 - 移除 User Secret Dictionary(FunctionResource:
acp-user-secret)。 - 将所有动词设置为 get/list/watch。
YAML 示例:
6.2 构建多范围审计员角色(方法 B)
这是 6.1 的聚合方法版本:一个命名空间级只读角色,涵盖业务命名空间和项目命名空间,并使用您自己的 ClusterRole 和标签构建,遵循 5.2 中的模式。
ClusterRole — 每个要涵盖的范围对应一个 ClusterRole,所有 ClusterRole 使用相同的自定义标签,并分别具有自己的范围标签:
RoleTemplate — 每个范围配置一个 aggregationRules 条目,并重复使用相同的自定义标签:
如果需要,也可以用同样的方式添加 system-ns。另外请注意,如果 ClusterRole 仅在 global 集群中创建,但角色也必须在工作负载集群中生效,则需在每个 ClusterRole 上设置 rbac.cpaas.io/sync.scope: "platform"(5.2 第 2 步)。