feat!: capabilities replace API token scopes; every admin endpoint declares one, with a picker UI [CI]

This commit is contained in:
justme committed 2026-10-07 20:56:36 +08:00
1 parent 55b80f0a97
commit ddb6608e32
38 files changed
+1148 -218

No files matched your search

+1 -1
View File
@@ -272,7 +272,7 @@
## 12. 实施顺序(每步可独立验证和推送)
1. **能力模型与守卫**:`Capability`、`Principal.Has`、端点声明、对账测试、现有令牌迁移、API key 创建界面(预设、全选、能力子集校验)、IP 白名单。不改节点。
1. **能力模型与守卫**:`Capability`、`Principal.Has`、端点声明、对账测试、API key 创建界面(预设、全选、能力子集校验)。不改节点。**已实现**(破坏性:旧令牌作废,数据库迁移 v11 重建 `api_tokens`)。登录会话在步骤 2 之前拥有全部能力(包括信任类),信任类的 passkey 要求从步骤 2 起强制。IP 白名单推迟:本部署经 Cloudflare、frp 和 Caddy,后端看到的来源地址是代理,需要先有「可信代理」配置,才做得对。`events.read` 对应现有的 `GET /api/admin/events`,不是预留。
2. **账户、passkey、会话分级、审计**:WebAuthn 注册与登录、提权窗口(接入、吊销、凭证三类)、审计日志、归属列和详情页显示。
3. **操作员集合与创世公钥固定**:`fleet-enroll` 和安装命令改造、弱信任开关、离线恢复密钥的创建与导出。
4. **入网链**:Grant、Ticket(含属主 `controllers`)、Binding 的签发和节点验证(验证一次、缓存结果);成员条目随期望状态下发、节点在状态同步时验证;Probe 只拨公网地址;`enroll` key;节点信任状态上报和管理页显示(第 14 节)。添加节点的界面可以选属主(默认添加者的全部 passkey)。
+4 -3
View File
@@ -15,7 +15,7 @@
```text
/api/public/* 只读。站点设为公开时匿名可访问,设为私有时需要登录或只读令牌;
public_visible = false 的 Agent 对匿名访客隐藏
/api/admin/* 管理。需要 Cookie 会话(含 CSRF 校验)或 admin 作用域的 API 令牌(`POST /api/admin/releases` 也接受只能登记发布清单的 release 令牌)
/api/admin/* 管理。需要 Cookie 会话(含 CSRF 校验)或带有对应**能力**的 API 令牌;每个端点声明自己需要的一项能力(OpenAPI 里的 `x-moshiro-capability`),完整目录见 `GET /api/admin/capabilities`,设计见 [access.md](access.md)
/api/agent/v1/* 节点专用:注册(使用加入令牌)和 RPC(使用签名认证)
/healthz /metrics /openapi/v1.json /install /install.ps1
```
@@ -140,7 +140,8 @@
| GET | `/api/admin/raw/chunks/{chunk_id}` | 下载原始块(`application/vnd.moshiro.rawchunk`);过期返回 410 `raw_expired` |
| GET | `/api/admin/events?agent_id=&kind=&from=&to=` | 事件 |
| GET | `/api/admin/analysis/recompute` | 指标重算进度 |
| GET/POST/DELETE | `/api/admin/api-tokens` | 作用域为 `read`、`admin` 或 `release`(只能登记发布清单,给 CI 用,什么都读不了);明文只显示一次 |
| GET/POST/DELETE | `/api/admin/api-tokens` | 创建时勾选能力(`capabilities`,只能是创建者自己拥有能力的子集,写蕴含读)和可选的有效期(`expires_in_days`);明文只显示一次 |
| GET | `/api/admin/capabilities` | 能力目录:分组、哪些改变信任、哪些是预留、依赖关系和预设(只读、运维、接入、CI 发布、全部) |
| GET/PATCH | `/api/admin/settings` | 站点公开或私有、是否对访客显示构建信息(`site.show_build`)、保留期、节点定时重启(`fleet.restart_enabled`、`fleet.restart_hour`、`fleet.restart_minute`、`fleet.restart_utc_offset_minutes`,默认开、04:30、UTC+8;改完立即通知在线节点)等 |
| GET | `/api/admin/build-info` | 后端和每个 Agent、Probe 的版本、tag、提交、构建时间、系统,以及节点宿主机更新器报告的更新状态(管理端「系统 → 版本」) |
| GET/POST | `/api/admin/releases` | CI 签名的发布清单:POST 登记(`{manifest, signature}`,面板不验签、原样转给在线的节点和之后连上的节点),GET 看每个组件最新的一份 |
@@ -178,7 +179,7 @@
| --- | --- |
| 400 | `validation_failed`、`budget_exceeded` |
| 401 | `unauthorized`、`csrf_failed` |
| 403 | `forbidden`(令牌作用域不足)、`site_private` |
| 403 | `forbidden`(凭证缺少端点需要的能力)、`site_private` |
| 404 | `agent_not_found`、`task_not_found`、`test_not_found`、`chunk_not_found`、`unknown_kind`、`unknown_plan` |
| 409 | `name_conflict`、`probe_offline`、`test_busy`、`agent_not_active` |
| 410 | `raw_expired`、`join_token_expired` |
+1 -1
View File
@@ -9,7 +9,7 @@
| Agent | Fleet 节点身份(ECDSA P-256)+ 面向 Probe 的 TLS 证书 | `fleet-enroll` | 公钥、SPKI 指纹 |
| Probe | Fleet 节点身份(连面板)+ 另一把独立的密钥(连 Agent,放在 `tls.pfx`) | `fleet-enroll`,和 Agent 一样用加入令牌(`role=probe`);可以有多个 Probe,每个独立吊销 | 两把公钥 |
| 面板用户 | 账号 + 密码(PBKDF2-SHA256) | 面板 | 密码哈希 |
| API 令牌 | 随机高熵令牌,作用域为 `read` 或 `admin` | 面板 | SHA-256 |
| API 令牌 | 随机高熵令牌,带一组能力(见 [access.md](access.md)) | 面板 | SHA-256 |
| 发布签名 | ECDSA P-256 发布密钥 | CI(Woodpecker 密钥 `release_signing_key`)或离线环境 | 只在节点宿主机的更新器里配置公钥(容器节点是 `moshiro-update`,见 [deployment.md](deployment.md);纯二进制节点的更新是待办),**面板不保存私钥,也不验签** |
## 2. Agent 接入流程