Files
orbit/docs/api/console-applications.md

15 KiB
Raw Permalink Blame History

控制台应用接入

单管理员在「应用接入」页面创建应用、初始队列与 SDK 凭据,查看环境、队列、权限和有效期,平滑换证,复制或下载 .env 配置。业务认证使用 Token 摘要;当前 Token 使用 AES-256-GCM 加密保管。管理员可以随时查看、复制完整接入配置和下载 orbit.env,列表仅返回脱敏元数据。

1. 启用和使用

部署配置指定唯一有跨应用接入管理权限的控制台登录名:

export ORBIT_CONSOLE_APPLICATION_ADMIN=admin
export ORBIT_CREDENTIAL_KEY_FILE=/run/orbit-secrets/credential-keys.json

该账号必须已经通过 bootstrap 或 console-user create 创建。配置为空时所有应用接入管理请求返回 403,不会自动提升已有账号;多节点使用相同配置。继续使用单管理员,不引入角色管理系统。现有控制台账号与会话的绑定凭据仍须有效;到期前可在本页轮换。轮换 SDK Token 不改变浏览器独立会话秘密。

本地 Compose 已为 admin 配置该入口,访问 http://127.0.0.1:18080/console/#/applications。

  1. 点击「新建应用」,填写应用名称、环境、命名空间、初始队列和操作原因。
  2. 选择 Worker、结果订阅、定时、流程等需要的能力及有效期。基础权限包含任务提交/查询/取消、队列读取/管理。
  3. 创建成功后复制或下载完整 .env,交给该应用的服务端配置。默认地址使用当前页面来源,详情中可改为容器地址或部署域名。
  4. 已接入应用点击「查看接入信息」或「复制接入配置」,获取包含当前 Token 的完整配置;也可下载 orbit.env。
  5. 「平滑换证」保留 application_id、namespace_id、credential_id、队列、任务和订阅;新 Token 立即生效,旧 Token 在配置的过渡期内继续使用(页面默认 7 天,支持 1/7/30 天),便于逐台更新配置。详情展示旧 Token 实际截止,全部服务切换后可点「结束过渡」。
  6. 默认「长期有效」,不需要每月人工换证;已有凭据可点「调整有效期」直接设为长期,原 Token 保持不变。

凭据卡片提供「查看接入信息」「复制接入配置」。配置包含 ORBIT_URL、ORBIT_APPLICATION_ID、ORBIT_NAMESPACE_ID、ORBIT_QUEUE_ID、ORBIT_TOKEN;可直接粘贴为环境配置。先选择业务服务实际可访问的地址和队列,再复制;应用 ID 用于识别,真正认证身份来自 Token。过渡期始终返回当前新 Token,调整有效期或结束旧代过渡后仍可查看。历史凭据尚无密文时提供「导入当前 Token」,不能把仍可用的旧代 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 /console/applications/{namespace_id}/credentials/{credential_id}/token/reveal 管理员读取当前 Token;审计成功后才返回
POST /console/applications/{namespace_id}/credentials/{credential_id}/token/import 校验并加密补存当前 Token,不轮换身份

POST 必须有 Content-Type: application/json 和 X-Orbit-Console: 1;浏览器 Origin 必须匹配当前主机,拒绝跨站 Fetch Metadata,不提供跨域授权。响应禁止缓存,成功信封为 {"data": ...}。未知字段、重复 JSON 键、显式 null 和错误类型被拒绝,正文上限 512 KiB。

3. 新建应用

prepare 请求:

{
  "kind": "CREATE",
  "application": "order-service",
  "namespace": "default",
  "environment": "test",
  "queue": "orders",
  "capabilities": ["worker", "events", "schedules", "workflows"],
  "expected_revision": "0",
  "valid_days": 0,
  "reason": "接入订单服务"
}

名称以字母或数字开头,后续只允许字母、数字、_ . : -,environment 最长 32,其余最长 128。valid_days 为 0–365 的整数,默认 0 表示长期有效;reason 非空、最多 1024 个 Unicode 字符,不含换行或 NUL。capabilities 可选 worker、events、schedules、workflows、recovery、resources,不可重复。新建不传 namespace_id / credential_id,expected_revision 省略或为字符串 "0"。

prepare 响应 data 为固定操作对象:

{
  "version": 2,
  "input": {"kind":"CREATE","application":"order-service","namespace":"default","environment":"test","queue":"orders","capabilities":["worker","events"],"expected_revision":"0","valid_days":0,"reason":"接入订单服务"},
  "operation_id": "11111111111111111111111111111111",
  "application_id": "22222222222222222222222222222222",
  "namespace_id": "33333333333333333333333333333333",
  "queue_id": "44444444444444444444444444444444",
  "credential_id": "55555555555555555555555555555555",
  "token": "服务端生成的完整 Token"
}

以上是结构示意,ID、令牌及时间以服务端返回为准。将 data 整体原样 POST 到 apply,不包 data 外层。应用、额度、命名空间、队列、凭据摘要、Token 密文、审计和幂等回执在同一事务提交。初始队列并发 4、开始速率 10/秒,沿用 bootstrap 默认策略;凭据队列范围为新命名空间的全部队列。重名应用返回 409,不覆盖原资源。

4. 平滑换证

prepare 请求:

{
  "kind": "ROTATE",
  "namespace_id": "33333333333333333333333333333333",
  "credential_id": "55555555555555555555555555555555",
  "expected_revision": "1",
  "valid_days": 0,
  "grace_days": 7,
  "reason": "更新接入凭据"
}

expected_revision 为读取到的字符串版本。只允许上述轮换字段,不混入新应用名称或能力组。准备对象包含原 application_id / namespace_id / credential_id,没有 queue_id。apply 复用原有凭据轮换事务:将原摘要保留到固定过渡截止,原子替换当前摘要、密文与可选到期时间,版本加一,保存脱敏回执及人类账号审计;权限组不改变。已撤销的凭据禁止变更。ROTATE 的 grace_days 范围 0–30,API 省略/0 保持立即停用旧 Token 的兼容语义,页面显式提交 7;实际截止不超过旧 Token 原到期时间。过渡未结束时再次轮换返回 409。

页面在过渡期将入口标为「暂不可换证 · 查看原因」,同时显示实际截止和切换步骤。该入口可以点击,打开只读说明弹窗,不会提交换证或结束过渡。这表示上一轮换证已生效;再次轮换会挤掉仍在使用的旧 Token,所以暂时禁止。将已保存的新 Token 配置到所有服务、Worker 和结果消费者,并收尾在途任务。到期后页面刷新会恢复换证入口;只有确认全部切换完成,才可提前点「结束过渡,停用旧 Token」。结束过渡会立即停用旧 Token,不能仅为解锁按钮而操作。已撤销凭据单独显示「已撤销 · 查看原因」,同样只打开说明。

apply 成功 data:

{
  "operation_id": "11111111111111111111111111111111",
  "application_id": "22222222222222222222222222222222",
  "namespace_id": "33333333333333333333333333333333",
  "credential_id": "55555555555555555555555555555555",
  "revision": "2",
  "deduplicated": false
}

5. 调整有效期与结束过渡

prepare 输入示例:

{
  "kind": "SET_EXPIRY",
  "namespace_id": "33333333333333333333333333333333",
  "credential_id": "55555555555555555555555555555555",
  "expected_revision": "2",
  "valid_days": 0,
  "reason": "服务凭据设置为长期有效"
}

SET_EXPIRY 不生成新 Token,只更新当前有效期;valid_days=0 为长期,1–365 为从准备时间计算的天数。FINALIZE 使用相同身份/版本字段,kind 改为 FINALIZE,valid_days 必须为 0,用于提前停用旧 Token。两者均禁止 grace_days 和新建字段,prepare 不返回 token;FINALIZE 也不返回 expires_at。apply 使用完整原对象,具有相同的并发版本、幂等和审计约束。

新版 prepare 对象带 version=2;expires_at 为空时省略字段,不要传显式 null。ROTATE 有过渡期时另外包含固定 previous_valid_until;详情中的 previous_valid_until 是受旧到期时间约束后的实际截止,未设置时省略。详情/回执不会返回旧秘密。历史不带 version 的固定操作仍按原语义重放。

完整滚动更新及 SDK 客户端生命周期说明见凭据手册。更换配置不会自动刷新已创建的客户端,须在过渡截止前完成重建或逐台重启并排空在途任务。

6. 超时、重复和审计

  • 页面提交前把整个固定操作保留在当前内存;请求超时或结果未知时,按钮变成「重试确认」,重用同一份内容。不能再次 prepare 来代替核对。
  • 页面允许「保存待核对操作」下载私密 JSON;含真实 Token,应放到受限目录。恢复时登录同一管理员后,向 apply 发送该文件正文。不要把 Cookie 或操作文件提交 Git,也不要放到 URL。
  • 关闭窗口后清除浏览器中的明文,管理员可以重新查看,无需再次换证。
  • 原操作返回的回执是历史快照,可能已被后续轮换替代。页面会重新读取当前凭据版本后才展示配置。
  • 管理审计主体是 console:<user_id>;正文只有权限、资源 ID、到期时间等元数据。列表、审计、幂等回执和业务记录都不保存秘密原文。
  • 当前管理员退出、会话过期或账号停用后不能重放管理操作。SDK Token 撤销/到期与控制台登录资格沿用既有账号绑定约束。
错误 HTTP 处理
UNAUTHENTICATED 401 登录有效控制台账号
PERMISSION_DENIED 403 核对唯一管理员配置、会话及同源请求
INVALID_ARGUMENT 400 核对字段、能力组、固定身份及有效期
NOT_FOUND 404 核对命名空间/凭据是否存在
STATE_CONFLICT 409 应用名称已存在、凭据已撤销、版本已变更或旧 Token 仍在过渡期;读取当前状态
IDEMPOTENCY_CONFLICT 409 原操作内容被修改,保留原始操作核对
数据库/网络故障 5xx / 网络错误 不假定失败,保留原操作重报

可重复运行的真实 HTTP 场景见 test-console-applications.py,标准容器入口 make console-e2e 同时验证此链路。基础 SDK 使用方式见 SDK 接入。

业务数据的应用筛选、队列分页及会话隔离见应用范围接口。

7. 当前 Token 与历史导入

详情返回 token_vault_enabled;每张凭据的 token_stored 表示当前 Token 是否已保管。列表、详情、审计和幂等回执都不包含原文。

查看请求:

{"expected_revision":"3"}

导入请求:

{"expected_revision":"3","token":"已保存的当前完整 Token"}

成功响应:

{"data":{"namespace_id":"33333333333333333333333333333333","credential_id":"55555555555555555555555555555555","revision":"3","token":"当前完整 Token"}}

只接受当前凭据版本。版本冲突、撤销或旧记录未保管返回 409;导入的身份或秘密与当前摘要不符返回 400(旧代处于过渡期也不例外);密钥缺失/解密失败返回 503。读取需要 Cookie、同源和 X-Orbit-Console,与其他管理 POST 相同。响应 Cache-Control: no-store;审计动作分别是 console.credential.token.view、console.credential.token.import,不含 Token、摘要或密文。

导入可以重复提交同一当前 Token,每次成功操作记录审计;不修改认证 revision、到期时间、权限或旧代截止。网络结果不明时可重新读取元数据或重报同一导入。读取/导入遇到审计写入失败或提交结果不明,不返回秘密。读取与换证对同一凭据加锁,返回的是该事务看到的当前代次;之后其他管理员的新轮换仍以实际数据库状态为准。

8. 部署 Token 保管

启用 ORBIT_CONSOLE_APPLICATION_ADMIN 时必须配置 ORBIT_CREDENTIAL_KEY_FILE,文件格式:

{"active":"key-v1","keys":{"key-v1":"32 字节随机密钥的标准 Base64 编码"}}

主密钥由部署方生成,权限限定运行用户读取;不要使用示例文字作为密钥。所有服务节点和管理 CLI 使用同一份密钥环,通过只读文件挂载部署,不写进镜像、Git 或数据库。参考本地部署自动生成方案。最多 16 把密钥,文件最多 64 KiB。密文绑定 namespace_id / credential_id,不能跨凭据替换。

升级先停止旧节点、应用迁移 000033、配置密钥再启动全部新节点;旧写节点不认识密文列,不能混合版本承诺回看一致性。迁移仅增加两个可空字段和成对 CHECK,无外键,不改变已有 Token、版本、有效期或过渡时间。

数据库和密钥文件分别备份。更换主密钥时使用新 key ID,将其设为 active,同时保留仍有密文引用的旧 key;在更新所有节点之前不写新 key ID 的数据。历史密文可以先查看、再导入同一 Token 以重新加密,不需要更换业务 Token。不得将旧 ID 映射到不同密钥,也不得在密文尚未迁移时删除旧 key。

管理 CLI 的 bootstrap / credential rotate / apply 读取同一环境变量。未设置时保持摘要模式,轮换会清除旧密文;之后必须导入该次新 Token 才能回看。控制台启用应用管理员时不会允许遗漏主密钥配置。

历史库仅有 SHA-256 摘要,无法凭摘要重建原文。请从既有业务配置或下载文件导入当前 Token;不要为补存秘密提前结束仍在使用的旧 Token 过渡。