Files
pikasTech-HWLAB/docs/reference/spec-v03-eso-secret-ui.md
T
2026-07-01 15:24:16 +08:00

199 lines
11 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.
# HWLAB v0.3 ESO 密钥管理 UI 规格
SPEC: HWLAB-ESO-UI-20260630 ESO UI draft-2026-07-01-p2-compact-detail.
Issue: [#2292](https://github.com/pikasTech/HWLAB/issues/2292), [#2324](https://github.com/pikasTech/HWLAB/issues/2324).
上级: [#2233](https://github.com/pikasTech/HWLAB/issues/2233), [#2277](https://github.com/pikasTech/HWLAB/issues/2277).
参考: Weave GitOps 0.22.0 Manage Secrets UI, HWLAB `config/hwlab-v03/secrets.yaml`.
本文只定义 `hwlab.pikapython.com` 的 ESO / External Secrets Operator 密钥管理界面。它不是生产 Secret 迁移方案,也不触发部署、apply、rollout 或后端选型变更。
## 范围
- 在 Cloud Web 管理侧边栏新增 `密钥` 入口,路由建议为 `/admin/secrets``navId``admin.secrets`,排序固定在 `授权``用户` 之间。
- 仅覆盖 ESO、`ExternalSecret``SecretStore``ClusterSecretStore`、目标 Kubernetes Secret cache 和 consumer rollout 可视化。
- 默认上下文由同源 API 返回的 active target 决定;当前 JD01 作为 [#2277](https://github.com/pikasTech/HWLAB/issues/2277) 设计目标展示,不在前端硬编码。D518 和 D601 只作为历史或明确选择的 target。
- SOPS、age/GPG、Git 加密文件、PR 生成、手工 `kubectl` 指令和 secret value 输入框不进入本界面。
## 信息架构
管理区导航顺序:
```text
管理
授权 /admin/access admin.access
密钥 /admin/secrets admin.secrets
用户 /admin/users admin.users
账务 /admin/billing admin.billing
HWPOD /admin/hwpod-groups admin.hwpodGroups
Profiles /admin/provider-profiles admin.providerProfiles
```
`admin.secrets` 必须受 HWLAB RBAC 控制。无权限用户看不到导航项;只读用户可看脱敏状态,不能进入 apply、rotate、rollback 或 destructive 操作。
## 页面结构
### `/admin/secrets` 首页
首页首屏直接聚焦 `ExternalSecrets` 紧凑列表和必要操作区,不再展示上一轮同一行的 `JD01 / v03``hwlab-admin-secrets-v1``ESO` 三个顶部摘要模块,也不使用同等体量的新卡片替代它们。
允许保留低噪声刷新、Plan 入口、行数、更新时间和脱敏状态提示;target、contract、ESO readiness、fingerprint、consumer rollout 等诊断信息进入详情页、受控 API 或专门 drill-down,不长期占据首页首屏。
### ExternalSecrets 列表
首页列表固定列顺序:`NAME``STATUS``NAMESPACE``CLUSTER``K8S SECRET``SECRET STORE``AGE`
- `NAME` 可点击,进入 `/admin/secrets/external-secrets/:namespace/:name`
- `STATUS` 覆盖 `Ready``NotReady``Pending``SyncError``Unknown` 和安全阻断状态。
- `CLUSTER` 来自同源 read model 的 target/cluster 字段,不由前端硬编码 JD01/D518/D601/G14。
- `K8S SECRET` 显示 target Kubernetes Secret 名称和必要 resourceVersion/presence 摘要。
- `SECRET STORE` 显示 SecretStore 或 ClusterSecretStore 的脱敏名称与 scope。
- `AGE` 来自后端 `createdAt``ageSource``lastUpdated` 或等价 timestamp;前端只能格式化显示,不硬编码时间。
- 桌面端保持高密度可扫描行高;窄屏允许表格横向滚动,但不得改变列顺序或造成文本重叠。
列表不得提供复制、下载、解码或 reveal secret value 的操作。
### ExternalSecret 详情
详情页路由为 `/admin/secrets/external-secrets/:namespace/:name`,刷新浏览器后必须能恢复当前资源。页面左上角提供返回按钮和刷新按钮;返回进入 `/admin/secrets` 列表,刷新只刷新当前 ExternalSecret detail 与当前资源 events。
详情页顶部状态区固定两行:第一行 `status`,第二行 `last updated`。顶部状态区下方提供同一行 `DETAILS` / `EVENTS` 切换按钮;切换只影响按钮下方内容区,不重排顶部状态区。
`DETAILS` 分区展示:
- 基本信息:ExternalSecret、target Secret、node/lane、namespace、store kind/name/scope。
- 数据映射:remoteRef path、property、version、target key、fingerprint;路径可脱敏或 hash,不能显示 value。
- 目标 Secretkey presence、fingerprint、resourceVersion、valuesPrinted=false。
- Conditionstype、status、reason、lastTransitionTime。
- ConsumerDeployment/Job、image、pod readiness、rollout revision、template fingerprint annotation、最后 validate 结果。
- Provenance:配置来源文件、Git source commit、GitOps revision、Argo revision 或 status job id。
`EVENTS` 分区只展示当前 ExternalSecret 相关 events,包括 reason、message 摘要、resource、时间、trace/job id;不得展示全局无关 events。
### 创建/编辑向导
本 issue 只设计向导,不启用生产 apply。向导提交后的默认动作是 dry-run/plan。
1. 选择 node/lane/namespace。默认值来自 API active targetJD01/v0.3 只有在 API 标记为 active 时自动选中。
2. 输入 ExternalSecret 名称和目标 Kubernetes Secret 名称。
3. 选择 `SecretStore``ClusterSecretStore`。namespace scoped store 只能绑定同 namespacecluster scoped store 必须显示目标 namespace。
4. 配置 remoteRef path/property/version、target key、refresh interval、consumer rollout 标记。
5. 展示 dry-run/plan 结果、受影响 consumer、脱敏摘要和风险提示。
未来 apply 能力必须走 HWLAB/UniDesk 受控 API;前端不展示裸 `kubectl`、Helm 或 YAML 复制执行步骤。
### 事件与排障
事件页按资源归组,覆盖:
- Store auth failed。
- Store unavailable。
- ExternalSecret sync failed。
- Target Secret missing。
- Consumer rollout pending。
- Consumer validation failed。
- Unknown / stale status。
每条事件显示时间、资源、reason、message 摘要、建议 drill-down 和关联 trace/job id。message 需要经过后端脱敏;如果后端判定消息可能含有凭据,前端只显示 redacted reason 和 raw drill-down id。
## 状态模型
状态优先级从高到低:
1. `SecretLeakBlocked`: 发现响应含疑似 value、base64 payload、token、DSN、password 或 auth header,整页进入 blocked,要求后端修脱敏。
2. `StoreUnavailable`: ESO 可达但 Store 不 Ready 或认证失败。
3. `SyncError`: Store Ready,但 ExternalSecret 同步失败。
4. `TargetMissing`: ExternalSecret Ready 但目标 Secret/key 不存在。
5. `RolloutPending`: 目标 Secret fingerprint 更新,但 consumer 未滚动到新 fingerprint。
6. `ValidationFailed`: rollout 已完成,但原入口 validate 失败。
7. `Ready`: Store、ExternalSecret、target Secret、consumer fingerprint 和 validate 全部对齐。
8. `Unknown`: 信息缺失、API 超时或 status 过期。
UI 可以把 `Pending` 作为 `Unknown` 与明确错误之间的中间态,但不得把 `Pending` 渲染成成功。
## API 契约草案
所有接口走 Cloud Web 同源 `/v1/admin/secrets/*`,由后端调用受控 node/lane API、GitOps status 或 UniDesk CLI。前端不得直连 Kubernetes API、Vault/OpenBao、ESO webhook 或 platform-infra 服务。
```text
GET /v1/admin/secrets/summary
GET /v1/admin/secrets/external-secrets?node=<id>&lane=<lane>&namespace=<ns>
GET /v1/admin/secrets/external-secrets/:namespace/:name
GET /v1/admin/secrets/events?node=<id>&lane=<lane>&namespace=<ns>&name=<externalSecret>&limit=<n>
POST /v1/admin/secrets/external-secrets/plan
POST /v1/admin/secrets/external-secrets/validate
```
未来写入接口需要单独 issue 评审:
```text
POST /v1/admin/secrets/external-secrets/apply
POST /v1/admin/secrets/external-secrets/rollback
POST /v1/admin/secrets/rotate
```
响应共同字段:
```json
{
"ok": true,
"contractVersion": "hwlab-admin-secrets-v1",
"target": {
"node": "JD01",
"lane": "v03",
"runtimeNamespace": "hwlab-v03",
"infraNamespace": "platform-infra",
"source": "yaml-active-target"
},
"valuesPrinted": false,
"secretMaterialStored": false,
"generatedAt": "2026-06-30T00:00:00.000Z"
}
```
错误响应必须包含 `valuesPrinted=false``layer``code``retryable` 和可审计 request/trace id。后端不能把 live Secret 解码结果作为 response 的任何字段。
## 脱敏规则
允许展示:
- 对象名、namespace、node、lane、store kind/name、scope。
- target Secret 名称、target key 名、presence、resourceVersion。
- remoteRef path/property/version 的脱敏形式。
- fingerprint、字节数、状态、reason、时间、trace id、job id。
- `valuesPrinted=false``secretMaterialStored=false`
禁止展示:
- Secret value、base64 payload、token、password、API key、Authorization header、Cookie、DSN、private key、Vault root token。
- 可直接还原凭据的完整 JSON、TOML、YAML、env dump、stdout/stderr。
- 从 runtime Secret、pod env、日志或数据库反推 sourceRef 的结果。
如果任一后端字段命中凭据模式,后端必须删除或替换为 fingerprint;前端发现疑似泄露时进入 `SecretLeakBlocked`
## 权限
- `admin.secrets.read`: 读取概览、列表、详情、事件和 validate 结果。
- `admin.secrets.plan`: 提交 dry-run/plan,不写运行面。
- `admin.secrets.apply`: 未来 apply/rollback/rotate;本 SPEC 不启用。
- `admin.secrets.audit`: 查看操作历史、trace、job id 和 rollout provenance。
权限来自 HWLAB Access/RBAC,同一用户 session 下不新增第二套登录或临时 token。
## 验收标准
- 侧边栏设计明确 `密钥` 位于 `授权``用户` 之间。
- `/admin/secrets` 首页覆盖紧凑 ExternalSecrets 列表、刷新和 dry-run Plan 入口;不再展示顶部三模块、内联详情或全局 Events。
- ExternalSecret 详情深链覆盖状态、last updated、脱敏 details、当前资源 events、返回和刷新。
- 所有 target 默认值由 API/YAML active target 解析,前端不硬编码 JD01、D518、D601 或 G14。
- UI 只覆盖 ESO;没有 SOPS、age/GPG、Git 加密文件、PR 工作流或 secret value 输入框。
- API 草案只通过同源受控 API 暴露脱敏状态,不要求用户执行裸 `kubectl`
- 任意页面、事件和错误态都只能展示 presence、fingerprint、状态、reason 和引用,不展示 secret value。
- 本设计可以映射现有 `config/hwlab-v03/secrets.yaml``secretPlane``ExternalSecret`、target Secret 和 consumer envRef。
## 后续阶段
- P1 只读 MVP:新增导航、概览、列表、详情和事件页,后端只读 status。
- P2 dry-run:新增创建/编辑向导和 plan API,不执行 apply。
- P3 validate/rollout 可视化:串联 Secret fingerprint、consumer rollout revision 和原入口 validate 结果。
- P4 受控 apply/rollback:必须另开 issue,确认生产 backend、RBAC、审计、rollback 和 rollout 验收后才能实现。