k8s中的权限管理
在k8s中的权限管理默认是使用的的RBAC,其中主要包含这四个核心概念:Role、ClusterRole、RoleBinding和ClusterRole,比如下面的案例就是创建一个role,允许读取development namespace下的pod,将这个role赋予user jane。这样user jane就会拥有读取development namespace下pod的权限。
# 创建一个 Role,允许用户读取指定命名空间中的 pods
kubectl create role pod-reader \
--namespace=development \
--verb=get,list,watch \
--resource=pods
# 将 pod-reader 角色绑定到用户 jane
kubectl create rolebinding read-pods \
--namespace=development \
--role=pod-reader \
--user=jane
RBAC是什么
RBAC(Role-Based Access Control),基于角色的访问控制。RBAC 是一种权限管理模型,用户并不直接拥有具体的权限,而是通过角色与权限建立关系,简化了用户与权限的直接映射关系,提供了灵活、高效的权限管理方案。基本流程如下:
- 用户(User):系统中的主体,例如管理员、普通用户等。
- 角色(Role):权限的抽象集合,例如管理员角色可以管理用户,普通用户只能访问自己的数据。
- 权限(Permission):具体的操作,例如读取、写入、删除资源等。
- 资源(Resource):需要进行访问控制的对象,例如系统中的文件、API、数据表等。
RBAC 的优势:
- 易管理:用户与权限的绑定通过角色完成,减少直接管理用户权限的复杂性。
- 灵活性:角色的权限可以动态调整,满足复杂场景需求。
如果我们想要在golang中实现RBAC,可以使用Casbin
定义rbac_model.conf
[request_definition] # 定义请求的格式
r = sub, obj, act # sub(用户), obj(资源), act(操作)
[policy_definition] # 定义策略的格式
p = sub, obj, act # 与请求格式对应
[role_definition] # 定义角色继承关系
g = _, _ # 用户与角色的对应关系
[matchers] # 定义匹配规则
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
数据库表
-- Casbin 规则表
CREATE TABLE casbin_rule (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
ptype VARCHAR(255),
v0 VARCHAR(255),
v1 VARCHAR(255),
v2 VARCHAR(255),
v3 VARCHAR(255),
v4 VARCHAR(255),
v5 VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
在 Casbin 中,g 代表 “grouping” 或 “group”,用于定义 RBAC 模型中的角色继承关系。
- ptype = ‘p’
- p 表示 “policy”(策略)
- 用于定义具体的权限规则
- 例子:
p, admin, /api/posts, write表示 admin 角色可以写帖子
- ptype = ‘g’
- g 表示 “group”(组)或角色继承
- 用于定义用户和角色的关系
- 例子:
g, alice, admin表示用户 alice 属于 admin 组
-- 定义权限规则
INSERT INTO casbin_rule (ptype, v0, v1, v2) VALUES ('p', 'admin', '/api/posts', 'write');
-- 定义用户角色关系
INSERT INTO casbin_rule (ptype, v0, v1) VALUES ('g', 'alice', 'admin');
示例go代码
安装Casbin
go get github.com/casbin/casbin/v2
func main() {
// 连接数据库
dsn := "root:root@tcp(127.0.0.1:3306)/forum?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
// 初始化 Casbin Adapter
adapter, err := gormadapter.NewAdapterByDB(db)
if err != nil {
log.Fatal(err)
}
// 创建 enforcer
enforcer, err := casbin.NewEnforcer("config/rbac_model.conf", adapter)
if err != nil {
log.Fatal(err)
}
// 加载策略
err = enforcer.LoadPolicy()
if err != nil {
log.Fatal(err)
}
// 添加权限策略
// 管理员可以做任何事
_, err = enforcer.AddPolicy("admin", "/api/posts", "*")
_, err = enforcer.AddPolicy("admin", "/api/users", "*")
_, err = enforcer.AddPolicy("admin", "/api/boards", "*"
// 普通用户的权限
_, err = enforcer.AddPolicy("user", "/api/posts", "read")
_, err = enforcer.AddPolicy("user", "/api/posts", "write")
_, err = enforcer.AddPolicy("user", "/api/comments", "read")
_, err = enforcer.AddPolicy("user", "/api/comments", "write")
// 添加用户到角色
_, err = enforcer.AddGroupingPolicy("alice", "admin") // alice 是管理员
_, err = enforcer.AddGroupingPolicy("tom", "user") // tom 是普通用户
...
}
最佳实践
- 在casbin_rule表中只存储角色级别的权限
- 具体的资源(如帖子)的所有权在业务代码汇中判断
- 不用为每一个具体的资源都建立casbin规则,直接复用申明好的角色即可
举一个具体的案例:论坛系统
角色设计
在论坛系统中,我们通常会有以下几个基本角色:
admin(管理员):系统最高权限user(登录用户):基本操作权限guest(访客):最低权限级别
权限模型设计
对于论坛系统,我们可以使用 Casbin 的 RBAC with domains/tenants 模型。这个模型允许我们定义角色、资源、操作和域(可选)。
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
- 权限规则设计 针对论坛系统,我们可以定义以下基本操作:
read: 读取帖子、评论write: 发布帖子、评论update: 更新自己的帖子/评论delete: 删除帖子/评论manage: 管理其他用户、内容审核等
权限规则示例(policy.csv):
p, admin, posts, manage
p, admin, comments, manage
p, admin, users, manage
p, user, posts, read
p, user, posts, write
p, user, comments, read
p, user, comments, write
p, guest, posts, read
p, guest, comments, read
g, alice, admin
g, bob, user
- Go代码实现示例
package main
import (
"github.com/casbin/casbin/v2"
"log"
)
func main() {
// 初始化 enforcer
e, err := casbin.NewEnforcer("model.conf", "policy.csv")
if err != nil {
log.Fatal(err)
}
// 权限检查示例
checkPermission := func(user, resource, action string) bool {
ok, err := e.Enforce(user, resource, action)
if err != nil {
log.Printf("Error checking permission: %v", err)
return false
}
return ok
}
// 使用示例
log.Println(checkPermission("alice", "posts", "manage")) // true
log.Println(checkPermission("bob", "posts", "write")) // true
log.Println(checkPermission("guest", "posts", "write")) // false
}
为什么这样设计?
a) 分层设计的优势:
- 角色继承关系清晰
- 权限管理更加灵活
- 易于维护和扩展
b) 权限粒度控制:
- 资源级别(posts, comments, users)
- 操作级别(read, write, manage)
- 可以精确控制每个角色的权限范围
c) 实际应用场景:
- 访客(guest)只能查看内容
- 普通用户(user)可以发帖和评论
- 管理员(admin)拥有所有权限,包括内容管理
还有什么其他的权限管理方式?
ABAC
ABAC (Attribute-Based Access Control) 是一种基于属性的访问控制方法,相比 RBAC 更加灵活和细粒度
ABAC的核心概念
- 主体属性:用户的特征,比如部门、职级、年龄
- 对象的属性:资源的特征,比如文档的类型、敏感级别
- 操作属性:操作的特征,比如读、写、审批
- 环境属性:环境的特征,比如时间、位置、设备等
可以看出 ABAC适合需要细粒度的控制,动态策略的场景,而RBAC适合角色清晰,层级分明的场景