golang实现Google Zanzibar风格的全局授权系统插件库keto的使用
Golang 实现 Google Zanzibar 风格的全局授权系统插件库 Keto 的使用
Ory Keto 是第一个也是最受欢迎的开源实现,实现了"Zanzibar: Google 的全局一致性授权系统"!
快速开始
你可以使用 Docker 在本地运行 Ory Keto,或者使用 Ory CLI 来尝试 Ory Keto:
# 这个示例在 Bash 中效果最佳
bash <(curl https://raw.githubusercontent.com/ory/meta/master/install.sh) -b . ory
sudo mv ./ory /usr/local/bin/
# 或者如果你安装了 Homebrew
brew install ory/tap/cli
创建一个新项目(你也可以使用 Docker):
ory create project --name "Ory Keto Example"
export project_id="{设置为输出中的 ID}"
使用 Ory 权限语言创建命名空间
# 编写一个简单的配置,包含一个命名空间
echo "class Document implements Namespace {}" > config.ts
# 应用该配置
ory patch opl --project $project_id -f file://./config.ts
# 创建一个关系,授予 tom 访问文档的权限
echo "Document:secret#read@tom" \
| ory parse relation-tuples --project=$project_id --format=json - \
| ory create relation-tuples --project=$project_id -
# 列出所有关系
ory list relation-tuples --project=$project_id
# 输出:
# NAMESPACE OBJECT RELATION NAME SUBJECT
# Document secret read tom
#
# NEXT PAGE TOKEN
# IS LAST PAGE true
Golang 示例代码
下面是一个使用 Golang 客户端与 Keto 交互的完整示例:
package main
import (
"context"
"fmt"
"log"
keto "github.com/ory/keto-client-go"
)
func main() {
// 创建 Keto 客户端
cfg := keto.NewConfiguration()
cfg.Servers = []keto.ServerConfiguration{
{
URL: "http://localhost:4466", // Keto 服务地址
},
}
client := keto.NewAPIClient(cfg)
// 创建关系元组
rel := keto.RelationTuple{
Namespace: "Document",
Object: "secret",
Relation: "read",
Subject: "tom",
}
// 创建关系
_, _, err := client.WriteApi.CreateRelationTuple(context.Background()).RelationTuple(rel).Execute()
if err != nil {
log.Fatalf("Failed to create relation tuple: %v", err)
}
// 检查权限
allowed, _, err := client.PermissionApi.CheckPermission(context.Background()).
Namespace("Document").
Object("secret").
Relation("read").
Subject("tom").
Execute()
if err != nil {
log.Fatalf("Failed to check permission: %v", err)
}
fmt.Printf("Is allowed: %v\n", allowed)
}
安装
前往文档了解安装 Ory Keto的各种方法。
生态系统
我们基于几个指导原则构建 Ory 架构:
- 最小依赖
- 随处运行
- 轻松扩展
- 最小化人为和网络错误的可能性
Ory 的架构设计最适合在 Kubernetes、CloudFoundry、OpenShift 等容器编排系统上运行。
安全
如果你认为发现了安全漏洞,请不要在论坛、聊天或 GitHub 上公开讨论。你可以在我们的security.txt中找到负责任披露的所有信息。
开发
我们鼓励所有贡献,并建议你阅读我们的贡献指南。
依赖
你需要 Go 1.19+ 和(用于测试套件):
- Docker 和 Docker Compose
- GNU Make 4.3
- NodeJS / npm >= v7
从源代码安装
make install
运行测试
有两种类型的测试可以运行:
- 短测试(不需要像 PostgreSQL 这样的 SQL 数据库)
- 常规测试(需要 PostgreSQL、MySQL、CockroachDB)
短测试
短测试运行相当快。你可以一次性测试所有代码:
go test -short -tags sqlite ./...
或者只测试特定模块:
go test -tags sqlite -short ./internal/check/...
常规测试
常规测试需要数据库设置。我们建议使用:
source ./scripts/test-resetdb.sh
go test -tags sqlite ./...
构建 Docker
你可以使用以下命令构建开发 Docker 镜像:
make docker
更多关于golang实现Google Zanzibar风格的全局授权系统插件库keto的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现Google Zanzibar风格的全局授权系统插件库keto的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用Go实现Google Zanzibar风格的授权系统(Keto)
Google Zanzibar是一种全球分布式授权系统,为Google Drive、YouTube等产品提供权限管理。Keto是Zanzibar的开源实现,下面我将介绍如何在Go中使用Keto构建授权系统。
Keto简介
Keto是一个实现了Zanzibar论文中核心概念的授权系统,主要特点包括:
- 基于关系的访问控制(ReBAC)
- 全局一致性
- 高性能和可扩展性
- 支持复杂的权限检查
安装Keto客户端
首先安装Keto Go客户端:
go get github.com/ory/keto-client-go
基本使用示例
1. 初始化客户端
package main
import (
"context"
"fmt"
keto "github.com/ory/keto-client-go"
)
func main() {
configuration := keto.NewConfiguration()
configuration.Servers = []keto.ServerConfiguration{
{
URL: "http://localhost:4466", // Keto服务地址
},
}
client := keto.NewAPIClient(configuration)
ctx := context.Background()
// 下面的示例将使用这个client
}
2. 定义关系元组
Zanzibar/Keto使用关系元组(relation tuples)来表示权限,格式为:namespace:object#relation@subject
// 添加关系元组
func addRelationTuple(client *keto.APIClient, ctx context.Context) {
tuple := keto.RelationQuery{
Namespace: "files",
Object: "file1",
Relation: "view",
SubjectId: "user1",
}
_, _, err := client.WriteApi.CreateRelationTuple(ctx).RelationQuery(tuple).Execute()
if err != nil {
fmt.Printf("Error creating relation tuple: %v\n", err)
return
}
fmt.Println("Relation tuple created successfully")
}
3. 检查权限
// 检查权限
func checkPermission(client *keto.APIClient, ctx context.Context) {
check := keto.GetCheckRequest{
Namespace: "files",
Object: "file1",
Relation: "view",
SubjectId: "user1",
}
resp, _, err := client.PermissionApi.CheckPermission(ctx).GetCheckRequest(check).Execute()
if err != nil {
fmt.Printf("Error checking permission: %v\n", err)
return
}
if resp.GetAllowed() {
fmt.Println("Permission granted")
} else {
fmt.Println("Permission denied")
}
}
4. 扩展关系
Keto支持定义关系之间的继承:
// 定义继承关系
func addInheritance(client *keto.APIClient, ctx context.Context) {
// 管理员可以执行所有操作
adminTuple := keto.RelationQuery{
Namespace: "files",
Object: "file1",
Relation: "admin",
SubjectId: "user2",
}
// 定义admin包含view权限
inheritanceTuple := keto.RelationQuery{
Namespace: "files",
Object: "file1",
Relation: "view",
SubjectSet: &keto.SubjectSet{
Namespace: "files",
Object: "file1",
Relation: "admin",
},
}
_, _, err := client.WriteApi.CreateRelationTuple(ctx).RelationQuery(adminTuple).Execute()
if err != nil {
fmt.Printf("Error creating admin tuple: %v\n", err)
return
}
_, _, err = client.WriteApi.CreateRelationTuple(ctx).RelationQuery(inheritanceTuple).Execute()
if err != nil {
fmt.Printf("Error creating inheritance tuple: %v\n", err)
return
}
fmt.Println("Inheritance relationship created")
}
5. 批量操作
// 批量操作
func batchOperations(client *keto.APIClient, ctx context.Context) {
// 创建多个关系
tuples := []keto.RelationQuery{
{
Namespace: "files",
Object: "file2",
Relation: "view",
SubjectId: "user1",
},
{
Namespace: "files",
Object: "file3",
Relation: "edit",
SubjectId: "user2",
},
}
for _, tuple := range tuples {
_, _, err := client.WriteApi.CreateRelationTuple(ctx).RelationQuery(tuple).Execute()
if err != nil {
fmt.Printf("Error creating tuple: %v\n", err)
continue
}
}
fmt.Println("Batch operations completed")
}
实际应用示例
下面是一个更完整的示例,模拟文件共享系统:
type FileSharingSystem struct {
client *keto.APIClient
ctx context.Context
}
func NewFileSharingSystem() *FileSharingSystem {
cfg := keto.NewConfiguration()
cfg.Servers = []keto.ServerConfiguration{{URL: "http://localhost:4466"}}
return &FileSharingSystem{
client: keto.NewAPIClient(cfg),
ctx: context.Background(),
}
}
func (f *FileSharingSystem) ShareFile(fileID, userID, permission string) error {
tuple := keto.RelationQuery{
Namespace: "files",
Object: fileID,
Relation: permission,
SubjectId: userID,
}
_, _, err := f.client.WriteApi.CreateRelationTuple(f.ctx).RelationQuery(tuple).Execute()
return err
}
func (f *FileSharingSystem) CheckAccess(fileID, userID, permission string) (bool, error) {
check := keto.GetCheckRequest{
Namespace: "files",
Object: fileID,
Relation: permission,
SubjectId: userID,
}
resp, _, err := f.client.PermissionApi.CheckPermission(f.ctx).GetCheckRequest(check).Execute()
if err != nil {
return false, err
}
return resp.GetAllowed(), nil
}
func main() {
fss := NewFileSharingSystem()
// 分享文件
err := fss.ShareFile("report.pdf", "alice", "view")
if err != nil {
fmt.Printf("Error sharing file: %v\n", err)
return
}
// 检查权限
allowed, err := fss.CheckAccess("report.pdf", "alice", "view")
if err != nil {
fmt.Printf("Error checking access: %v\n", err)
return
}
if allowed {
fmt.Println("Alice can view the report")
} else {
fmt.Println("Alice cannot view the report")
}
}
最佳实践
- 命名空间设计:合理规划命名空间,如按资源类型划分
- 关系设计:设计清晰的关系层次结构
- 批量操作:尽量使用批量接口减少网络开销
- 缓存:对频繁检查的权限考虑本地缓存
- 监控:监控权限检查的延迟和错误率
Keto提供了强大的权限管理能力,特别适合需要复杂权限关系的分布式系统。通过合理设计关系模型,可以实现灵活的权限控制策略。