ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpiceDB 技术解析:构建可扩展的细粒度授权数据库(Zanzibar 开源实现)

SpiceDB 技术解析:构建可扩展的细粒度授权数据库(Zanzibar 开源实现) SpiceDB 技术解析构建可扩展的细粒度授权数据库Zanzibar 开源实现【免费下载链接】spicedbOpen Source, Google Zanzibar-inspired database for scalably storing and querying fine-grained authorization data项目地址: https://gitcode.com/GitHub_Trending/sp/spicedbSpiceDB 是一个受 Google Zanzibar 系统启发的开源授权数据库用于以可扩展的方式存储和查询细粒度授权数据。本文基于仓库根目录的 README.md 展开并结合源码说明其安装、容器运行、Schema 与关系写入、权限查询 API 及生产部署的完整链路读完你可以独立搭建一个 SpiceDB 实例用 HTTP API 完成定义 Schema → 写入关系 → 执行权限检查的全流程并理解各关键参数在源码中的落点。一、SpiceDB 是什么回答主体 X 能否对资源 Z 执行动作 YSpiceDB 是受 Google 内部授权系统 Zanzibar 启发的开源项目。README 指出自 2021 年起OWASP 将失效的访问控制Broken Access Control列为 Web 安全的第一大威胁SpiceDB 正是为了让平台与产品团队能够轻松回答核心问题而设计Can subject X perform action Y on resource Z?主体 X 能否对资源 Z 执行动作 Y其使用方式与关系型数据库相似开发者定义Schema类型、关系、权限的声明式描述以Relationships关系的形式写入授权数据即对象 A 的关系 R 上挂了主体 B在应用中使用 SpiceDB 客户端发起Permission Checks权限检查判断用户对某资源可执行的动作。除了正向的权限检查SpiceDB 还依赖反向索引支持两类反向查询What cansubjectdo?——某主体能对哪些资源做什么Who can accessresource?——哪些主体可以访问某资源。架构上SpiceDB 常被部署为跨产品套件与微服务架构共享的集中式授权服务。README 还强调了一个重要的边界设计SpiceDB 只负责授权authorization与认证authentication/身份提供方完全解耦——你的用户身份来自哪里OIDC、企业目录等不影响 SpiceDB 的工作方式SpiceDB 只接收你给出的主体标识如user:anne。Zanzibar 背景方面Google 于 2019 年发表了论文《Zanzibar: Googles Consistent, Global Authorization System》描述了其内部 ACL 存储与求值系统的设计、实现与部署最初为 Google Circles 设计后支撑了 Google 全线产品Calendar、Drive、Maps、Photos、YouTube以及 GCP 的 IAM 服务。README 声明 SpiceDB 在功能上已远超论文范围但开发上始终忠实于论文的价值与目标。二、核心特性Why SpiceDBREADME 的 Why SpiceDB? 一节列出了项目的七项卖点结合仓库源码可以逐一落地理解Zanzibar 论文的成熟完整实现权限图求值逻辑位于 internal/graphcheck.go处理检查、lookupresources3.go处理 LookupResources v3 等查询查询计划与执行位于 pkg/query。Global consistency全局一致性一致性可按请求粒度配置如minimizeLatency、atLatestRead、atExactRevision在正确性与延迟之间取舍相关中间件见 internal/middleware/consistency。Multi-paradigm / CaveatsABAC 与 ReBAC 融合支持给关系附加条件约束caveat将基于属性的授权能力叠加到基于关系的授权之上实现位于 pkg/caveatscompile.go、eval.go、structure.go内部执行路径见 internal/caveats。仓库自带示例 development/schema.yaml 中就有caveat only_on_tuesday(day_of_week string)的用法。Reverse Indexes反向索引使 What can subject do / Who can access resource 成为一等查询对应 API 中的 LookupResources 与 LookupSubjects。Safety in tooling支持 Schema 实时校验LSP 实现见 internal/lsp以及在 CI/CD 中做 Schema 验证。生产验证README 声称其核心服务自 2021 年起在 Authzed 生产环境使用。三、安装二进制README 给出三种官方安装途径二进制发布支持 Linux、macOS、Windows 的 AMD64 与 ARM64 架构。HomebrewmacOS 与 Linuxbrew install authzed/tap/spicedb authzed/tap/zedspicedb是服务端zed是官方命令行客户端独立仓库项目。Debian 系 LinuxAPT 源sudo apt update sudo apt install -y curl ca-certificates gpg curl https://pkg.authzed.com/apt/gpg.key | sudo apt-key add - sudo echo deb https://pkg.authzed.com/apt/ * * /etc/apt/sources.list.d/fury.list sudo apt update sudo apt install -y spicedb zedRPM 系 LinuxYUM 仓库sudo cat EOF /etc/yum.repos.d/Authzed-Fury.repo [authzed-fury] nameAuthZed Fury Repository baseurlhttps://pkg.authzed.com/yum/ enabled1 gpgcheck0 EOF sudo dnf install -y spicedb zed说明以上仓库源地址pkg.authzed.com在仓库中属于外部资源链接此处仅按原文保留安装命令供复制使用不展开跳转。四、容器运行4.1 最简启动命令README 给出的 Docker 启动方式暴露 gRPC 与 HTTP 两个端口HTTP 用于下文示例docker run --rm -p 50051:50051 -p 8443:8443 \ authzed/spicedb serve --http-enabled true --grpc-preshared-key somerandomkeyhere这条命令的关键点可以从源码逐一对应端口50051是 gRPC API 默认端口8443是 HTTP 网关反向代理到本地 gRPC默认端口。在 pkg/cmd/serve.go 中可看到 gRPC 服务地址默认为:50051、HTTP 网关默认为:8443Dockerfile 中也声明了EXPOSE 50051。--grpc-preshared-key是必填参数pkg/cmd/serve.go 中该 flag 被标记为 requiredcobra.MarkFlagRequired用于客户端请求的预共享密钥认证实现位于 internal/auth/presharedkey.go。生产环境请更换为随机强密钥。--http-enabled true默认 HTTP 网关是关闭的需显式开启后才能用curl走 HTTP API。4.2 镜像来源与调试镜像容器镜像支持 AMD64 与 ARM64官方 README 列出了多个镜像仓库Docker Hub、GHCR、Quay.io 上的authzed/spicedb。两个值得注意的镜像细节基础镜像基于Chainguard Images静态运行时见 Dockerfile 第 10 行的cgr.dev/chainguard/static用户态极简、有利于安全但也意味着容器内没有 shell 等调试工具任意 tag 追加-debug后缀即可获得带调试工具的镜像docker run --rm -ti --entrypoint sh authzed/spicedb:latest-debug针对main分支每个 git commit 也会构建镜像命名规则为${REGISTRY}/authzed/spicedb-git:${COMMIT}便于跟踪最新变更。从 Dockerfile 可以看到构建细节使用 Go 工具链以 CGO 关闭方式编译./cmd/spicedb并把grpc-health-probe一并放入镜像供健康检查使用——这与仓库开发用 compose 文件中grpc_health_probe -addrlocalhost:50051的健康检查见 docker-compose.yaml相互印证。五、编写 Schema 与写入关系SpiceDB 启动后必须定义Schema并写入Relationships来表达应用中的权限。README 给出四种途径客户端库、Playground、zedCLI或直接调用 gRPC/HTTP API。以下用 HTTP API 完整走一遍 README 的示例。5.1 写入 Schemacurl --location http://localhost:8443/v1/schema/write \ --header Content-Type: application/json \ --header Accept: application/json \ --header Authorization: Bearer somerandomkeyhere \ --data { schema: definition user {} \n definition folder { \n relation parent: folder\n relation viewer: user \n permission view viewer parent-view \n } \n definition document {\n relation folder: folder \n relation viewer: user \n permission view viewer folder-view \n } }这段 Schema 用 SpiceDB 的声明式语言定义了三个类型user叶子类型无任何关系folderparent关系指向其他 folder表达层级包含viewer关系挂 userpermission view viewer parent-view表示直接是 viewer或通过 parent 递归继承 viewdocumentfolder关系指向其所在 folderviewer挂 userview同理。Schema 语言definition/relation/permission 语法、caveat 等的解析与校验实现位于 pkg/development 与 pkg/schemadsllexer、parser、compiler类型系统与可达性检查位于 pkg/schema。5.2 写入关系curl --location http://localhost:8443/v1/relationships/write \ --header Content-Type: application/json \ --header Accept: application/json \ --header Authorization: Bearer somerandomkeyhere \ --data { updates: [ { operation: OPERATION_TOUCH, relationship: { resource: { objectType: folder, objectId: budget }, relation: viewer, subject: { object: { objectType: user, objectId: anne } } } } ] }要点说明OPERATION_TOUCH是幂等写入关系已存在则保持不变不存在则创建一条关系的三元组结构为resource资源对象 relation关系名 subject主体对象对应源码中的关系模型 pkg/tuple写入前会做校验关系是否符合 Schema、主体类型是否正确实现见 internal/relationships/validation.go。仓库内也提供了完整的验证文件格式示例Schema 关系 期望结果断言如 pkg/validationfile 及其testdata以及开发用数据 development/schema.yaml——其中展示了带 caveat 的关系写法relation reader: user with only_on_tuesday及document:1#readeruser:1[only_on_tuesday]可作为 caveat 用法的直接参照。六、查询 SpiceDB API执行权限检查Schema 与关系写入后即可发起权限检查。README 的示例curl --location http://localhost:8443/v1/permissions/check \ --header Content-Type: application/json \ --header Accept: application/json \ --header Authorization: Bearer somerandomkeyhere \ --data { consistency: { minimizeLatency: true }, resource: { objectType: folder, objectId: budget }, permission: view, subject: { object: { objectType: user, objectId: anne } } }预期响应{ checkedAt: { token: GhUKEzE3NTE1NjYwMjUwMDAwMDAwMDA }, permissionship: PERMISSIONSHIP_HAS_PERMISSION }字段解读consistency.minimizeLatency: true表示允许使用最新的本地数据以降低延迟牺牲强一致其他一致性级别可按需配置checkedAt.token是该次检查所基于的数据存储修订版本 token可用于审计这次判断基于哪个时间点的数据permissionship的取值表示授权判定结果本例为拥有权限。从源码结构看一次 Check 请求的路径是API 层 → 查询计划构建pkg/queryregistry.go注册各类查询节点并生成计划→ 权限图上的递归求值internal/graph/check.go沿parent-view这类箭头展开子查询→ 关系数据的存储层读取internal/datastore。反向查询LookupResources / LookupSubjects则复用反向索引实现分别在 internal/graph/lookupresources3.go 与 internal/graph/lookupsubjects.go。除了 curl也可以用官方命令行客户端zed发起查询README 提示 Playground 也提供浏览器内实验zed的选项卡。七、serve 的关键参数源码级补充README 只展示了最小启动参数而 pkg/cmd/serve.go 中注册的完整 flag 集合揭示了更多可调项。以下是与日常运维直接相关的一部分以源码中的默认值为准参数默认值说明--grpc-preshared-key必填客户端认证所用的预共享密钥可配置多个gRPC 监听地址:50051gRPC API 端口--http-enabledfalse是否开启 HTTP 网关HTTP 监听地址:8443HTTP 网关端口--grpc-shutdown-grace-period5s收到 SIGINT/SIGTERM 后的优雅停机时长0 表示不限--streaming-api-response-delay-timeout30s流式 APILookupSubjects、LookupResources、ReadRelationships 等无响应前的最大允许时长--watch-api-heartbeat1sWatch API 心跳间隔--max-read-relationships-limit1000单次请求最多读取的关系数--max-delete-relationships-limit1000单次请求最多删除的关系数--max-lookup-resources-limit1000单次请求最多查询的资源数--max-bulk-export-relationships-limit10000单次批量导出的关系数上限--write-relationships-max-updates-per-call1000单次 WriteRelationships 的最大更新数--update-relationships-max-preconditions-per-call1000单写调用允许的最大前置条件数--telemetry-endpoint内置端点置空禁用遥测上报端点--telemetry-endpoint可关闭此外从 pkg/cmd/serve.go 中的缓存默认值可以看到 SpiceDB 内置了多级缓存策略namespace 缓存32MiB、dispatch 缓存最大成本的 30%、集群 dispatch 缓存70%、LookupResources v3 chunk 缓存50MiB等这也是其能在高 QPS 下保持低延迟的重要因素之一。入口层面cmd/spicedb/main.go 展示了进程启动顺序初始化内存用量保护memoryprotection与 Dockerfile 中的-tags memoryprotection构建标签对应→ 设置全局日志 → 注册 Kubernetes 的 gRPC in-cluster resolver用于服务发现→ 注册一致性哈希环 gRPC 负载均衡器ConsistentHashringBuilder→ 构建并执行根命令cmd.BuildRootCommand()位于 pkg/cmd/root.go聚合了serve、datastore、lsp、postgresfdw等子命令。八、本地多节点开发环境docker-compose 集群README 的生产章节提到 SpiceDB 支持多种数据存储仓库根目录提供了一组开发用 compose 文件正好覆盖了这些后端docker-compose.yamlCockroachDB默认开发栈docker-compose.postgres.yamldocker-compose.mysql.yamldocker-compose.spanner.yamldocker-compose.memdb.yaml内置内存数据库适合快速实验docker-compose.pgbouncer.yamlPostgres 连接池以 docker-compose.yaml 为例它搭建了一个双节点 SpiceDB 集群 完整可观测栈是很好的生产行为参照CockroachDB 单节点cockroachdb/cockroach镜像含健康检查以及一个crdb-init一次性容器用于开启kv.rangefeedSpiceDB 的 Watch 功能依赖 changefeeddatastore migrate head迁移步骤使用本仓库构建的镜像执行spicedb datastore migrate head把存储 schema 升级到最新版本迁移命令实现在 pkg/cmd/migrate.go两个serve节点spicedb-1/spicedb-2通过共享 DNS 别名spicedb-dispatch互相发现并开启SPICEDB_DISPATCH_CLUSTER_ENABLEDtrue与SPICEDB_DISPATCH_UPSTREAM_ADDRdns:///spicedb-dispatch:50053——这正是源码中一致性哈希环 dispatch 集群设计的落地跨节点的子查询通过 50053 端口dispatch endpoint相互转发docker-compose.yaml注释还特别说明用 Envoy 而非 nginx 做 gRPC 负载均衡因为 Envoy 能在 HTTP/2 连接内对单个 RPC做均衡有利于均匀的缓存预热可观测性Prometheus抓取各节点 9090 端口的指标、OpenTelemetry Collector Tempotrace Loki日志 Grafana含预置 dashboard见 development/grafana配置分别位于 development/prometheus.yaml、development/otel-config.yaml、development/tempo.yaml、development/loki.yaml。每个节点暴露四个端口9090Prometheus 指标、50051gRPC、8443HTTP、50053dispatch 集群通信。健康检查使用镜像内自带的grpc-health-probe见第四节 Dockerfile 中的 COPY 步骤。九、数据存储后端与迁移SpiceDB 的存储层抽象定义在 internal/datastore各具体驱动的目录结构也印证了 README 声称的后端支持internal/datastore/crdb —— CockroachDBinternal/datastore/spanner —— Google Cloud Spannerinternal/datastore/postgres —— PostgreSQLinternal/datastore/mysql —— MySQLREADME 致谢一节指出该驱动由 GitHub 授权团队实现并贡献internal/datastore/memdb —— 内存实现开发/测试用见其 README各驱动通过统一的datastore命令族完成迁移管理pkg/cmd/datastore典型流程即开发 compose 中演示的构建镜像后先执行spicedb datastore migrate head再启动serve。不同后端的 SQL schema 与迁移脚本分别在各自的migrations目录中维护如 internal/datastore/crdb/migrations。十、遥测TelemetryREADME 说明 SpiceDB 会收集匿名遥测以帮助项目方了解社区使用方式并决定功能优先级该行为是opt-out默认开启、可退出通过--telemetry-endpoint关闭。仓库内的 TELEMETRY.md 给出了更多实现细节遥测通过 Prometheus Remote Write 协议上报所有spicedb_telemetry前缀的指标按小时频率上报收集内容仅限环境信息CPU 架构、vCPU 数、操作系统、数据引擎、集群/节点标识与运行状况类指标代码位于 internal/telemetry。开发 compose 中同样显式设置了SPICEDB_TELEMETRY_ENDPOINT置空来关闭本地开发的遥测。十一、部署到生产的建议README 的 Deploying to Production 章节给出的要点SpiceDB 核心服务自 2021 年起在 Authzed 生产环境运行支持 Google Cloud Spanner、CockroachDB、MySQL、PostgreSQL 等数据存储与第六节的目录证据一致可自托管也可使用官方全托管服务AuthZed Cloud外部服务此处不展开自托管时推荐使用 Kubernetes 部署README 指向社区维护的 Kubernetes 示例与 Kubernetes Operator 文档更详细的部署最佳实践见官方文档的 best-practices 指南外部资源原文档以链接给出。结合本仓库的 Dockerfile 与 Dockerfile.release生产镜像采用 Chainguard 静态基础镜像、以非构建产物方式直接拷贝二进制/usr/local/bin/spicedb镜像体积与攻击面都很小部署时建议配合grpc-health-probe做存活/就绪探针并将--grpc-preshared-key纳入密钥管理。十二、仓库结构速览延伸阅读入口围绕本文涉及的链路以下目录是继续深入的入口cmd/spicedb二进制入口含集成测试与内存保护集成测试pkg/cmdserve、datastore、migrate、lsp、postgresfdw等 CLI 子命令与 flag 注册internal/graphCheck / LookupResources / LookupSubjects 的图求值核心pkg/query查询计划、advisor 优化器与执行器internal/datastore存储抽象与五种后端驱动pkg/caveatscaveat 的编译、求值与参数化pkg/development、pkg/schemadslSchema 语言解析、校验与编译development本地开发集群 compose 栈、Grafana/Prometheus/OTel/Loki/Tempo 配置与验证数据e2e跨存储后端的端到端测试工具proto 与 buf.yamlAPI 的 protobuf 定义与代码生成配置。小结SpiceDB 以 Zanzibar 模型为核心把谁能对什么做什么抽象为 Schema 定义、关系写入与权限查询三个环节并通过全局一致的存储层、反向索引与多级缓存实现可扩展的授权判定。从 README.md 的最小容器命令起步配合 pkg/cmd/serve.go 中的完整参数、docker-compose.yaml 的双节点开发集群与 TELEMETRY.md 的遥测说明可以完整地复现从实验环境到生产部署的路径所有关键结论均可在仓库源码中找到对应实现便于进一步审计与定制。【免费下载链接】spicedbOpen Source, Google Zanzibar-inspired database for scalably storing and querying fine-grained authorization data项目地址: https://gitcode.com/GitHub_Trending/sp/spicedb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表