Files
pikasTech-HWLAB/docs/reference/spec-v02-openfga-authorization.md
T
2026-06-05 17:23:56 +08:00

159 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v0.2 OpenFGA 授权与 Admin Access 管理规格
本文是 HWLAB `v0.2` 细粒度资源授权、OpenFGA 接入、管理员 Access WebUI 和同路径 CLI 的长期规格。Keycloak 只回答“用户是谁”;OpenFGA 回答“该用户能不能对该对象做该动作”;`hwlab-cloud-api` 是唯一应用层 enforcement point 和授权写入口。
当前 HWPOD 快速闭环阶段只管理用户、Code Agent session 和工具能力,不为旧设备对象保留 OpenFGA type、relation、API 或 CLI。
## 在系统中的职责划分
| 组件 | 职责 |
| --- | --- |
| Keycloak | 身份认证、注册、OIDC issuer;不直接授予 HWLAB 功能权限。 |
| `hwlab-cloud-api` | `AuthPrincipal` 恢复、OpenFGA store/model bootstrap、授权 check、授权写 API、enforce 策略、AgentRun transient env 过滤和审计摘要。 |
| OpenFGA | `hwlab-v02` namespace 内部 PDP 和 relationship tuple store;只接受 cloud-api 调用,不向浏览器、CLI、AgentRun runner 或公网暴露。 |
| HWLAB v0.2 Postgres | 业务对象、用户、session、API key、access_tuples 摘要、OpenFGA store/model 指针和迁移 ledger 的 durable source。 |
| `hwlab-cloud-web` | Admin Access 页面和同源 API proxy;不直接调用 OpenFGA。 |
| `hwlab-cli client` | Web 等价非视觉授权管理入口;通过 `19666` Cloud Web 同源 path 调 cloud-api,不直连 OpenFGA。 |
| AgentRun v0.1 runner | 只消费 cloud-api 根据用户权限注入的短期工具环境;不持有跨用户共享 key、GitHub token 或 UniDesk SSH token。 |
## 授权模型
对象命名必须稳定、可从业务 ID 直接推导,并在日志/trace 中可脱敏展示:
| 对象 | 例子 | 说明 |
| --- | --- | --- |
| 用户 | `user:usr_123` | HWLAB `users.id`,不是 Keycloak `sub`。 |
| 系统 | `system:hwlab` | 平台级 admin、access 管理和全局工具授权。 |
| Code Agent session | `agent_session:ags_123` | 会话 owner/collaborator/viewer 判定。 |
| 工具 | `tool:hwpod``tool:unidesk_ssh``tool:github_pr``tool:trans_cmd` | AgentRun runner 可注入或可调用的功能能力。 |
目标关系模型:
```fga
model
schema 1.1
type user
type system
relations
define admin: [user]
define access_manager: admin
define can_manage_users: admin
define can_manage_tools: admin
type agent_session
relations
define owner: [user]
define viewer: [user] or owner or admin from system
define operator: [user] or owner or admin from system
define admin: admin from system
type tool
relations
define can_use: [user] or admin from system
define admin: admin from system
```
实现可以在第一版用等价模型名称和 relation 名称,但必须保持以下能力语义:
| 功能 | Check |
| --- | --- |
| 管理用户和权限 | `user:<id> access_manager system:hwlab``admin system:hwlab` |
| 查看自己的 Code Agent session | `viewer agent_session:<id>` |
| 继续/取消 Code Agent session | `operator agent_session:<id>` |
| 使用 HWPOD 工具 | `can_use tool:hwpod` |
| 注入 UniDesk SSH 透传能力 | `can_use tool:unidesk_ssh` |
| 允许 trans 透传 cmd | `can_use tool:trans_cmd`,且仍受 UniDesk route/operation 边界限制 |
| GitHub PR/issue 写操作工具 | `can_use tool:github_pr` 或更细工具对象 |
`admin/user` 仍保留为 UX 和 bootstrap 角色,但 runtime 授权必须逐步迁移到 OpenFGA check。`users.role='admin'` 必须镜像为 `system:hwlab#admin@user:<id>` tuple;降级 admin 时必须同步删除 tuple。Keycloak realm role、group、claim 不能直接变成 OpenFGA tuple,除非由 HWLAB admin API 明确写入。
## Cloud API 授权策略
`hwlab-cloud-api` 是唯一 policy enforcement point。所有用户态请求按以下顺序处理:
```text
authenticate -> AuthPrincipal -> load domain object -> openfga check -> execute
```
`enforce` 是唯一正式运行模式。OpenFGA 不可达、store/model 未就绪或 check 超时时,高风险写操作 fail closed;低风险只读可以返回 degraded blocker,不得静默放行。
tuple 写入必须由 cloud-api admin API 统一完成,并和 Postgres domain state 保持事务级或可恢复一致:
- 用户创建、禁用、角色提升/降级时同步写 `users``system:hwlab` tuples。
- Code Agent session 创建时写 `agent_session:<id>#owner@user:<owner>`;取消/归档不删除 owner tuple,便于 trace 回放。
- API key `scopes_json` 只能作为用户权限的收窄条件,不能授予超过 OpenFGA 的能力。
## Admin Access API
Cloud Web 和 CLI 只能通过 cloud-api 的 admin API 管理授权。第一版 API surface
| 接口 | 说明 |
| --- | --- |
| `GET /v1/admin/access/summary` | 返回 mode、OpenFGA readiness、storeId/modelId、user/tool 数量和最近 mismatch 摘要。 |
| `GET /v1/admin/access/users` | 列出用户、role/status、Keycloak 绑定摘要、API key 数量和 effective capability 摘要。 |
| `GET /v1/admin/access/users/{userId}` | 返回单个用户的 agent session 和 tool 权限矩阵。 |
| `PATCH /v1/admin/access/users/{userId}` | 更新用户 `role/status`,并同步 OpenFGA admin tuple。 |
| `PUT /v1/admin/access/users/{userId}/tools/{toolId}/can-use` | 授予工具能力,例如 `hwpod``unidesk_ssh``github_pr``trans_cmd`。 |
| `DELETE /v1/admin/access/users/{userId}/tools/{toolId}/can-use` | 撤销工具能力。 |
| `POST /v1/admin/access/check` | 管理员调试单次 authorization check;响应必须标明 actor/object/relation/mode,但不得泄漏 token。 |
所有 write API 必须要求当前 actor 具备 `access_manager system:hwlab` 或 admin tuple;普通 `user` 不可调用。响应必须包含结构化 `authorization` 字段:`mode``allowed``decisionSource``storeId``modelId``relation``object` 和 redacted actor。
## Admin Access WebUI
Cloud Web 的 Access 页面只管理用户 role/status、Code Agent session 可见性和工具 capability。页面不暴露 OpenFGA tuple 原文作为主要操作面;需要排障时只在详情中显示 redacted object/relation。
## 同路径 CLI
`hwlab-cli client` 必须提供与 WebUI 同一 API surface 的非视觉入口,默认由 runtime namespace/lane 解析到 `19666` Cloud Web origin
| CLI | Web/API 等价 |
| --- | --- |
| `client access summary` | `GET /v1/admin/access/summary` |
| `client access users list` | `GET /v1/admin/access/users` |
| `client access users inspect USER` | `GET /v1/admin/access/users/{userId}` |
| `client access users set-role USER --role admin|user` | `PATCH /v1/admin/access/users/{userId}` |
| `client access tools grant USER TOOL` | `PUT /v1/admin/access/users/{userId}/tools/{toolId}/can-use` |
| `client access tools revoke USER TOOL` | `DELETE /v1/admin/access/users/{userId}/tools/{toolId}/can-use` |
| `client access check --user USER --relation REL --object OBJECT` | `POST /v1/admin/access/check` |
CLI 输出必须是 JSON,包含 `runtimeEndpoint`、HTTP route、actor 摘要、mode、decision 和变更后的 effective matrix 摘要。它不能直接调用 OpenFGA API,不能手动传 OpenFGA token,不能把 `--base-url 19667` 作为 WebUI 等价验收路径。
## AgentRun 工具能力边界
Cloud API 在创建 AgentRun command/runner 时必须按 OpenFGA 决策装配 transient env 和工具说明:
- 用户没有 `can_use tool:hwpod` 时,不注入 `HWLAB_API_KEY``hwpod`,也不在 prompt/tools 中声明 HWPOD 操作可用。
- 用户没有 `can_use tool:unidesk_ssh` 时,不注入 UniDesk SSH client token、workspace route 或相关 alias。
- `tool:trans_cmd` 只代表允许通过受控 UniDesk route 调用透传命令;它不绕过 UniDesk CLI 的 route/operation 安全边界。
- GitHub issue/PR 写入能力必须单独由工具对象授权;拥有 Code Agent session 不等于拥有 GitHub 写权限。
## 测试规格
## T1
阅读 docs/reference/spec-v02-openfga-authorization.md,然后访问 `GET /health/live``GET /v1/admin/access/summary`,确认响应显示 `openfga.mode`、readiness、storeId/modelId 摘要和 degraded reason;响应不得包含 OpenFGA token、Postgres URL 或 Secret 值。
## T2
阅读 docs/reference/spec-v02-openfga-authorization.md,然后撤销普通用户的 `tool:hwpod``tool:unidesk_ssh`,创建新的 Code Agent session 并检查 trace/runner env 摘要,确认对应工具 alias/env 未注入;尝试调用时返回结构化 authorization blocker。
## T3
阅读 docs/reference/spec-v02-openfga-authorization.md,然后从浏览器打开 Access 页面,确认只有 admin/access manager 可见 ActivityRail 入口;普通用户访问 route 显示授权 blocker。
## T4
阅读 docs/reference/spec-v02-openfga-authorization.md,然后在 runtime endpoint locked 环境运行 `hwlab-cli client access summary/users/check/grant/revoke`,确认全部走 Cloud Web 同源 `19666` path,输出 JSON、route、actor、mode、decision 和 effective matrix;不手动传 OpenFGA URL/token,不直连 `19667` 作为最终 Web 等价验收。
## 规格的实现情况
| 规格项 | 状态 | 说明 |
| --- | --- | --- |
| OpenFGA 作为 v0.2 内部授权服务 | 已实现/持续约束 | v0.2 runtime 以 `enforce` 模式运行,summary 暴露 redacted store/model 和 readinessOpenFGA 不向公网、浏览器或 CLI 暴露。 |
| Cloud API OpenFGA client/bootstrap/check/write | 已实现 | Admin Access API 可 check/write tuple,响应包含 structured decision 和 redacted OpenFGA 状态。 |
| session / tool 授权 | 核心已实现/持续扩展 | Code Agent session 和 tool capability 是当前授权来源。 |
| 同路径 CLI | 已实现 | `client access ...` 走 Cloud Web 同源 path,覆盖 summary、users、check 和 tool grant/revoke。 |