feat: add single-admin application onboarding and token rotation
This commit is contained in:
124
docs/api/console-applications.md
Normal file
124
docs/api/console-applications.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# 控制台应用接入
|
||||
|
||||
单管理员在「应用接入」页面创建应用、初始队列与 SDK 凭据,查看环境、队列、权限和有效期,重新生成 Token,复制或下载 `.env` 配置。数据库只保存 Token 摘要:完整 Token 仅在新建或轮换时交付,列表和详情不能反查旧秘密。
|
||||
|
||||
## 1. 启用和使用
|
||||
|
||||
部署配置指定唯一有跨应用接入管理权限的控制台登录名:
|
||||
|
||||
```sh
|
||||
export ORBIT_CONSOLE_APPLICATION_ADMIN=admin
|
||||
```
|
||||
|
||||
该账号必须已经通过 bootstrap 或 console-user create 创建。配置为空时所有应用接入管理请求返回 403,不会自动提升已有账号;多节点使用相同配置。继续使用单管理员,不引入角色管理系统。现有控制台账号与会话的绑定凭据仍须有效;到期前可在本页轮换。轮换 SDK Token 不改变浏览器独立会话秘密。
|
||||
|
||||
本地 Compose 已为 `admin` 配置该入口,访问 `http://127.0.0.1:18080/console/#/applications`。
|
||||
|
||||
1. 点击「新建应用」,填写应用名称、环境、命名空间、初始队列和操作原因。
|
||||
2. 选择 Worker、结果订阅、定时、流程等需要的能力及有效期。基础权限包含任务提交/查询/取消、队列读取/管理。
|
||||
3. 创建成功后复制或下载完整 `.env`,交给该应用的服务端配置。默认地址使用当前页面来源,详情中可改为容器地址或部署域名。
|
||||
4. 已接入应用可以随时查看元数据和配置模板。模板中的 Token 是占位值,必须替换成已经保存的原 Token。
|
||||
5. 「重新生成 Token」保留 application_id、namespace_id、credential_id、队列、任务和订阅;旧 Token 在轮换事务提交后不能再通过业务认证,服务端配置需要同步更新。
|
||||
|
||||
环境与命名空间形成隔离边界。不同应用应分别创建;同一应用的多个命名空间在列表中分别展示。页面目前支持新建应用及其初始队列,未提供应用删除、身份迁移、跨应用任务列表或现有应用新增命名空间的表单;已有 CLI 的 `--application-id` 仍可增加命名空间,队列 SDK 可增加同范围队列。接入管理页不会改变其他业务页面的账号默认范围。
|
||||
|
||||
## 2. 路由与认证
|
||||
|
||||
这些是浏览器管理端接口,不属于业务 SDK。只接受有效的 `orbit_console_session` HttpOnly Cookie,并在数据库事务中重新核验部署指定的管理员账号和会话;即使 SDK 凭据拥有全部业务权限也不能访问。
|
||||
|
||||
| 方法与路径 | 用途 |
|
||||
| --- | --- |
|
||||
| `GET /console/applications?after=<namespace_id>` | 按命名空间 ID 升序读取 50 条接入范围,返回 `items`、可选 `next`;`after` 为排他起点 |
|
||||
| `GET /console/applications/{namespace_id}` | 应用/环境详情、最多 100 个队列和 100 张脱敏凭据;超出返回 `truncated=true` |
|
||||
| `POST /console/applications/prepare` | 校验意图,生成固定操作 ID、资源 ID、Token、绝对到期时间;不创建资源、不轮换秘密 |
|
||||
| `POST /console/applications/apply` | 提交准备结果,原样重报返回原脱敏回执 |
|
||||
|
||||
POST 必须有 `Content-Type: application/json` 和 `X-Orbit-Console: 1`;浏览器 Origin 必须匹配当前主机,拒绝跨站 Fetch Metadata,不提供跨域授权。响应禁止缓存,成功信封为 `{"data": ...}`。未知字段、重复 JSON 键、显式 null 和错误类型被拒绝,正文上限 512 KiB。
|
||||
|
||||
## 3. 新建应用
|
||||
|
||||
prepare 请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": "CREATE",
|
||||
"application": "order-service",
|
||||
"namespace": "default",
|
||||
"environment": "test",
|
||||
"queue": "orders",
|
||||
"capabilities": ["worker", "events", "schedules", "workflows"],
|
||||
"expected_revision": "0",
|
||||
"valid_days": 30,
|
||||
"reason": "接入订单服务"
|
||||
}
|
||||
```
|
||||
|
||||
名称以字母或数字开头,后续只允许字母、数字、`_ . : -`,environment 最长 32,其余最长 128。valid_days 为 1–365 的整数;reason 非空、最多 1024 个 Unicode 字符,不含换行或 NUL。capabilities 可选 `worker`、`events`、`schedules`、`workflows`、`recovery`、`resources`,不可重复。新建不传 namespace_id / credential_id,expected_revision 省略或为字符串 `"0"`。
|
||||
|
||||
prepare 响应 data 为固定操作对象:
|
||||
|
||||
```json
|
||||
{
|
||||
"input": {"kind":"CREATE","application":"order-service","namespace":"default","environment":"test","queue":"orders","capabilities":["worker","events"],"expected_revision":"0","valid_days":30,"reason":"接入订单服务"},
|
||||
"operation_id": "11111111111111111111111111111111",
|
||||
"application_id": "22222222222222222222222222222222",
|
||||
"namespace_id": "33333333333333333333333333333333",
|
||||
"queue_id": "44444444444444444444444444444444",
|
||||
"credential_id": "55555555555555555555555555555555",
|
||||
"token": "服务端生成的完整 Token",
|
||||
"expires_at": "2026-10-27T02:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
以上是结构示意,ID、令牌及时间以服务端返回为准。将 **data 整体原样** POST 到 apply,不包 `data` 外层。应用、额度、命名空间、队列、凭据摘要、审计和幂等回执在同一事务提交。初始队列并发 4、开始速率 10/秒,沿用 bootstrap 默认策略;凭据队列范围为新命名空间的全部队列。重名应用返回 409,不覆盖原资源。
|
||||
|
||||
## 4. 重新生成 Token
|
||||
|
||||
prepare 请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": "ROTATE",
|
||||
"namespace_id": "33333333333333333333333333333333",
|
||||
"credential_id": "55555555555555555555555555555555",
|
||||
"expected_revision": "1",
|
||||
"valid_days": 30,
|
||||
"reason": "更新接入凭据"
|
||||
}
|
||||
```
|
||||
|
||||
expected_revision 为读取到的字符串版本。只允许上述轮换字段,不混入新应用名称或能力组。准备对象包含原 application_id / namespace_id / credential_id,没有 queue_id。apply 复用原有凭据轮换事务:替换秘密摘要与到期时间,版本加一,保存脱敏回执及人类账号审计;权限组不改变。已撤销的凭据禁止轮换。
|
||||
|
||||
apply 成功 data:
|
||||
|
||||
```json
|
||||
{
|
||||
"operation_id": "11111111111111111111111111111111",
|
||||
"application_id": "22222222222222222222222222222222",
|
||||
"namespace_id": "33333333333333333333333333333333",
|
||||
"credential_id": "55555555555555555555555555555555",
|
||||
"revision": "2",
|
||||
"deduplicated": false
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 超时、重复和审计
|
||||
|
||||
- 页面提交前把整个固定操作保留在当前内存;请求超时或结果未知时,按钮变成「重试确认」,重用同一份内容。不能再次 prepare 来代替核对。
|
||||
- 页面允许「保存待核对操作」下载私密 JSON;含真实 Token,应放到受限目录。恢复时登录同一管理员后,向 apply 发送该文件正文。不要把 Cookie 或操作文件提交 Git,也不要放到 URL。
|
||||
- 关闭/刷新页面会丢失内存中的 Token,页面会提醒先保存。若新建已经成功、交付内容未保存,可从应用列表重新生成同一凭据的 Token;不要再次创建同名应用。
|
||||
- 原操作返回的回执是历史快照,可能已被后续轮换替代。页面会重新读取当前凭据版本后才展示配置。
|
||||
- 管理审计主体是 `console:<user_id>`;正文只有权限、资源 ID、到期时间等元数据。列表、审计、幂等回执和业务记录都不保存秘密原文。
|
||||
- 当前管理员退出、会话过期或账号停用后不能重放管理操作。SDK Token 撤销/到期与控制台登录资格沿用既有账号绑定约束。
|
||||
|
||||
| 错误 | HTTP | 处理 |
|
||||
| --- | --- | --- |
|
||||
| UNAUTHENTICATED | 401 | 登录有效控制台账号 |
|
||||
| PERMISSION_DENIED | 403 | 核对唯一管理员配置、会话及同源请求 |
|
||||
| INVALID_ARGUMENT | 400 | 核对字段、能力组、固定身份及有效期 |
|
||||
| NOT_FOUND | 404 | 核对命名空间/凭据是否存在 |
|
||||
| STATE_CONFLICT | 409 | 应用名称已存在、凭据已撤销或版本已变更;读取当前状态 |
|
||||
| IDEMPOTENCY_CONFLICT | 409 | 原操作内容被修改,保留原始操作核对 |
|
||||
| 数据库/网络故障 | 5xx / 网络错误 | 不假定失败,保留原操作重报 |
|
||||
|
||||
可重复运行的真实 HTTP 场景见 [test-console-applications.py](../../scripts/test-console-applications.py),标准容器入口 `make console-e2e` 同时验证此链路。基础 SDK 使用方式见 [SDK 接入](../sdk/README.md)。
|
||||
Reference in New Issue
Block a user