如何创建自定义 Platform 角色
目录
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:自定义角色模板。它定义角色语义和权限集合,并由 controller 转换为 ClusterRole。
- FunctionResource:产品功能所使用的 K8s 资源抽象;在 RoleTemplate 中通过
functionResourceRef引用。 - ClusterRole:RBAC 规则集合。手写的 ClusterRole 可以通过标签聚合到 RoleTemplate(或内置系统角色)中。
- UserBinding:用户与角色/作用域之间的绑定;controller 会基于 UserBinding 生成 RoleBinding/ClusterRoleBinding,完成最终授权。
functionResourceRef的值来自 FunctionResource 的metadata.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,controller 会自动补成 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
如果你只需要一条一次性的原生 RBAC 规则,又不值得单独创建一个 ClusterRole 对象,就直接将其内联到 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)是不同的概念。controller 只对它们施加一条约束:platform和cluster级角色只能使用scope: cluster;project和namespace级角色可以使用五种 scope 中的任意一种(包括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 会在失败时提供原因/消息。如果 phase 不是 Ready、status.clusterRoles 为空,或者其列出的 ClusterRole 的 rules 为空(kubectl get clusterrole <name> -o yaml),说明该角色并没有授予你期望的权限。常见原因,按出现频率大致排序如下:
- RoleTemplate 缺少
rbac.cpaas.io/version: "v2",或者被自动冻结了——参见第 5 节中关于必需标签的说明。这是aggregationRules看起来“毫无作用”的最常见原因。 functionResourceRef名称拼写错误——controller 会静默跳过未知引用,并生成一个没有错误但规则为空的 ClusterRole。- 你的
aggregationRules标签没有匹配到任何 ClusterRole,或者源 ClusterRole 尚未同步到当前集群。
确认用户是否真正获得了权限
生成 ClusterRole 不是最终目标——用户真正拥有访问权限才是。通过 UserBinding 授权角色后(参见 管理角色),使用 impersonation 检查确认实际结果:
在编写 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。controller 会回收它在所有集群中生成的 ClusterRole——无需手动清理。(对于方法 B 中你手动编写的 ClusterRole,则由你自行删除。)
6. 复制与裁剪(示例)
下面给出两个完整示例:裁剪一个内置模板(方法 A,6.1),以及基于你自己的 ClusterRole 构建一个多作用域角色(方法 B,6.2)。对于 FunctionResource 角色,复制一个内置系统模板并进行裁剪,是避免遗漏模块权限的最快方式。
6.1 裁剪系统 RoleTemplate YAML(方法 A)
步骤:
- 保留所需的 FunctionResource。
- 将 verbs 缩减为只读(get/list/watch)。
- 移除未使用的模块。
角色示例:不包含 secret 权限的开发人员审计员
- 在自定义角色中,不要配置 Namespace Resource Management(FunctionResource:
acp-namespace-resource-manage)。 - 移除 User Secret Dictionary(FunctionResource:
acp-user-secret)。 - 将所有 verbs 设置为 get/list/watch。
示例 YAML:
6.2 构建多作用域审计员角色(方法 B)
这是 6.1 的聚合方法对应实现:一个跨 business 和 project 命名空间的命名空间级只读角色,基于你自己的 ClusterRole 和你自己的标签构建——遵循 5.2 中的模式。
ClusterRole — 每个需要覆盖的作用域一个,全部使用相同的自定义标签,并各自带有自己的作用域标签:
RoleTemplate — 每个作用域对应一条 aggregationRules,复用同一个自定义标签:
如果你还需要 system-ns,可以用同样的方式添加,并且如果这些 ClusterRole 只创建在 global 集群中但角色还必须在业务集群中生效,请记得在每个 ClusterRole 上添加 rbac.cpaas.io/sync.scope: "platform"(5.2 步骤 2)。