API 权限控制
插件中的 APIs 无论是自定义模型自动生成的 APIs 或者是通过 @Controller
自定义的 APIs 都只有超级管理员能够访问,如果想将这些 APIs 授权给其他用户访问,
则需要定义一些角色模板的资源以便可以在用户界面上将其分配给其他角色使用。
定义角色模板就是在插件的 src/main/resources/extensions
目录下声明角色的自定义模型资源并标记为模板的过程,文件名称可以任意,它的 kind 为 Role 但需要一个 label halo.run/role-template: "true"
来表示它是角色模板。
Halo 的权限控制对同一种资源一般只定义两个角色模板的自定义模型对象,一个是只读权限,另一个是管理权限,因此如果没有特殊情况需要更细粒度的控制,我们建议你也保持一致:
apiVersion: v1
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: v1
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"。对应的 HTTP 请求方式如下表所示:HTTP verb request verb POST create GET, HEAD get (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources) PUT update PATCH patch DELETE delete (for individual resources), deletecollection (for collections)
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
:模板角色的显示名称,用于展示为用户可读的名称信息。rbac.authorization.halo.run/ui-permissions
:用于控制 UI 权限,规则为plugin:{your-plugin-name}:scope-name
,使用示例为在插件前端部分入口文件index.ts
中用于控制菜单是否显示或者控制页面按钮是否展示:{
path: "",
name: "HelloWorld",
component: DefaultView,
meta: {
permissions: ["plugin:my-plugin:person:view"]
}
}
以上定义角色模板的方式适合资源型请求,即需要符合以下规则
- 以
/api/<version>/<resource>[/<resourceName>/<subresource>]
规则组成 APIs。 - 以
/apis/<group>/<version>/<resource>[/<resourceName>/<subresource>]
规则组成的 APIs。
注:[]
包裹的部分表示可选,只有 Halo 自身使用的 APIs 可以没有 group,所以插件的 APIs 都是以 /apis
开头的。
资源型的 API 通常是对自定义模型对象的操作,例如 /apis/my-plugin.halo.run/v1alpha1/persons
,如果你自定义 APIs 则建议路径层级不要超过 <subresource>
层级,否则会导致角色模板无法生效,例如 /apis/my-plugin.halo.run/v1alpha1/persons/zhangsan/post
,如果 post
后面还有路径则会导致角色模板无法生效。
如果你的 API 不符合以上资源型 API 的规则,则被定型为非资源型 API,例如 /healthz
,需要使用一下配置方式:
rules:
# nonResourceURL 中的 '*' 是一个全局通配符
- nonResourceURLs: ["/healthz", "/healthz/*"]
verbs: [ "get", "create"]