API 权限控制
插件中的 APIs 无论是自定义模型自动生成的 APIs 或者是通过 @Controller
自定义的 APIs 都只有超级管理员能够访问,如果想将这些 APIs 授权给其他用户访问,
则需要定义一些角色模板的资源以便可以在用户界面上将其分配给其他角色使用。
角色模板定义
定义角色模板需要遵循一定的规范:
- 文件位置和标记:角色模板定义文件存放于
src/main/resources/extensions
,文件名 可以任意,它的 kind 为 Role 且必须具有标签halo.run/role-template: "true"
来标识其为模板。 - 角色类型:通常,我们为同一种资源定义两种角色模板:只读权限和管理权限,分别对应
view
和manage
,如果需要更细粒度的控制,可以定义更多的角色模板。 - 角色名称:角色名称必须以插件名作为前缀,以避免与其他插件冲突,例如
my-plugin-role-view-persons
。 - 角色依赖:如果一个角色需要依赖于另一个角色,可以通过
rbac.authorization.halo.run/dependencies
作为 key 的metadata.annotations
来声明依赖关系。 - UI 权限:如果需要在前端界面上控制某个角色的权限,可以通过
rbac.authorization.halo.run/ui-permissions
作为 key 的metadata.annotations
来声明。 - 角色模板分组:如果需要将多个角色模板归为一组显示,可以通过
rbac.authorization.halo.run/module
作为 key 的metadata.annotations
来声明分组名称。 - 角色显示名称:如果需要在前端界面上显示角色的友好名称,可以通过
rbac.authorization.halo.run/display-name
作为 key 的metadata.annotations
来声明显示名称。 - 隐藏角色模板:如果不想在前端界面上显示某个角色模板,可以通过
halo.run/hidden: "true"
的metadata.labels
来隐藏角色模板。
角色模板定义的基本框架如下:
apiVersion: v1alpha1
kind: Role
metadata:
name: role-template-name
labels:
halo.run/role-template: "true"
rules:
- apiGroups: []
resources: []
resourceNames: []
verbs: []
- nonResourceURLs: []
verbs: []
在遵循上述规范的基础上,最重要的是定义 rules
字段,它是一个数组,用于定义角色模板的权限规则,规则分为两种类型:资源型和非资源型。
资源型规则
资源型规则用于定义对资源的操作权限,API 符合以下特征:
- 以
/api
开头,且以/api/<version>/<resource>[/<resourceName>/<subresource>]
规则组成 APIs,最少路径层级为 3 即/api/<version>/<resource>
,最多路径层级为 5 即包含<resourceName>
和<subresource>
,例如/api/v1/posts
。 - 以
/apis/<group>/<version>/<resource>[/<resourceName>/<subresource>]
规则组成的 APIs,最少路径层级为 4 即/apis/<group>/<version>/<resource>
,最多路径层级为 6 即包含<resourceName>
和<subresource>
,例如/apis/my-plugin.halo.run/v1alpha1/persons
。
[]
包裹的部分表示可选,/api
前缀被 Halo 保留,不允许插件定义以 /api
开头的资源型 APIs,所以插件的资源型 APIs 都是以 /apis
开头的。
通常可以通过 apiGroups
、resources
、resourceNames
、verbs
来组合定义。
例如对于资源型 API GET /apis/my-plugin.halo.run/v1alpha1/persons
,可以定义如下规则:
rules:
- apiGroups: [ "my-plugin.halo.run" ]
resources: [ "my-plugin/persons" ]
verbs: [ "list" ]
而对于资源型 API GET /apis/my-plugin.halo.run/v1alpha1/persons/zhangsan
,可以定义如下规则:
rules:
- apiGroups: [ "my-plugin.halo.run" ]
resources: [ "my-plugin/persons" ]
resourceNames: [ "zhangsan" ]
verbs: [ "get" ]
关于 verbs
的详细说明请参考 Verbs 详解。
非资源型规则
凡是不符合资源型 APIs 规则的 APIs 都被定型为非资源型 APIs,例如 /healthz
,可以使用以下配置方式:
rules:
- nonResourceURLs: ["/healthz", "/healthz/*"]
verbs: [ "get", "create"]
非资源型规则使用 nonResourceURLs
来定义,其中 nonResourceURLs
是一个字符串数组,用于定义非资源型 APIs 的路径,verbs
用于定义非资源型 APIs 的请求动词。
nonResourceURL
中的 *
是一个全局通配符,表示匹配所有路径,如 /healthz/*
表示匹配 /healthz/
下的所有路径。
示例:定义人员管理角色模板
以下 YAML 文件展示了如何定义用于人员管理的角色模板:
apiVersion: v1alpha1
kind: Role
metadata:
# 使用 plugin name 作为前缀防止与其他插件冲突,比如这里的 my-plugin
name: my-plugin-role-view-persons
labels:
halo.run/role-template: "true"
annotations:
rbac.authorization.halo.run/module: "Persons Management"
rbac.authorization.halo.run/display-name: "Person Manage"
rbac.authorization.halo.run/ui-permissions: |
["plugin:my-plugin:person:view"]
rules:
- apiGroups: ["my-plugin.halo.run"]
resources: ["my-plugin/persons"]
verbs: ["*"]
---
apiVersion: v1alpha1
kind: Role
metadata:
name: my-plugin-role-manage-persons
labels:
halo.run/role-template: "true"
annotations:
rbac.authorization.halo.run/dependencies: |
[ "role-template-view-person" ]
rbac.authorization.halo.run/module: "Persons Management"
rbac.authorization.halo.run/display-name: "Person Manage"
rbac.authorization.halo.run/ui-permissions: |
["plugin:my-plugin:person:manage"]
rules:
- apiGroups: [ "my-plugin.halo.run" ]
resources: [ "my-plugin/persons" ]
verbs: [ "get", "list" ]
上述便是根据 自定义模型 章节中定义的 Person 自定义模 型来配置角色模板的示例。
- 定义了一个用于管理 Person 自定义模型对象的角色模板
my-plugin-role-manage-persons
,它具有所有权限。 - 定义了一个只允许查询 Person 资源的角色模板
my-plugin-role-view-persons
。 metadata.name
的命名规则参考 metadata name 命名规范。
下面让我们回顾一下这些配置:
rules
是个数组,它允许配置多组规则:
apiGroups
对应GVK
中的group
所声明的值。resources
对应 API 中的 resource 部分。verbs
表示请求动词,可选值为 "create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"。参考 Verbs 详解。
metadata.labels
中必须包含 halo.run/role-template: "true"
以表示它此资源要作为角色模板。
metadata.annotations
中:
rbac.authorization.halo.run/dependencies
:用于声明角色间的依赖关系,例如管理角色必须要依赖查看角色,以避免分配了管理权限却没有查看权限的情况。rbac.authorization.halo.run/module
:角色模板分组名称。在此示例中,管理 Person 的模板角色将和查看 Person 的模板角色将被在 UI 层面归为一组展示。rbac.authorization.halo.run/display-name
:模板角色的显示名称,用于展示为用户可读的名称信息。