收口三个匿名可读端点: - 根路径 /metrics:默认完全不注册(访问 404);配置 METRICS_ALLOW_CIDR 后按内网白名单开放 - /health:改为鉴权(原本匿名泄漏版本、commit、运行时长、内存、goroutine 与配置错误文本) - /dashboard:改为鉴权(原本匿名,且它同时聚合 /health 与 /metrics,是单点泄漏最严重的端点) - /api/setup/status:改为鉴权(原本 normal 模式下仍匿名返回 installed/mode) 新增 /healthz 匿名存活探针,只回 200 与字面量 ok、不含任何字段,解决 "给 /health 加鉴权后 K8s 探针与 Docker HEALTHCHECK 会一律 401 导致 Pod 反复重启" 的问题; 新增 /api/admin/health 鉴权版详细健康数据,与 /api/admin/metrics 风格一致。 /dashboard 对浏览器 HTML 请求做内容协商:返回页面外壳由前端显示登录视图(SPA 登录态存在 sessionStorage、不随请求发送,服务端无从判断,强行 401 会把现有体验变成直接报错); 非 HTML 请求(脚本、抓取)无凭证一律 401。页面外壳本身不含数据,数据全部来自鉴权后的 API。 IP 白名单中间件复用 GetClientIP(已处理 XFF 与 TRUSTED_PROXY_HOPS),非白名单返回 404 而非 403,避免向扫描者确认端点存在。main.go 启动日志同步改为指向 /healthz 与 /api/admin/health。 验证(真实服务器端到端,非仅单元测试): - 安装前 /healthz=200、/health=401 - 安装后未带凭证:/healthz=200 /health=401 /metrics=404 /dashboard=401 /api/setup/status=401 - /dashboard 带 Accept: text/html 得 200 页面外壳,Accept: application/json 得 401 - /healthz 响应体确认为字面量 ok(不含任何字段) - 回退模式(未配 admin_key):业务 key 访问管理接口全部 200,向后兼容成立 - 配置独立 admin_key 后:业务 key 访问 /health /api/admin/* /api/voices /api/settings 全部 401, admin_key 全部 200,而 /v1/audio/speech 不受影响;GET /api/settings 只回打码值 另新增 middleware/metricsip_test.go 覆盖 CIDR 命中、越界、非法 IP、空列表拒绝, 以及伪造 X-Forwarded-For 不能绕过白名单。 go build ./... / go vet ./... / go test ./... -count=1 全绿。
This commit is contained in:
+23
-7
@@ -6,10 +6,18 @@
|
||||
|
||||
### v0.3.0 · 进行中
|
||||
|
||||
按 [docs/IMPLEMENT_v0.3.0.md](docs/IMPLEMENT_v0.3.0.md) 分阶段实施,当前完成 **阶段 1**。
|
||||
按 [docs/IMPLEMENT_v0.3.0.md](docs/IMPLEMENT_v0.3.0.md) 分阶段实施,当前完成 **阶段 1、阶段 2**。
|
||||
|
||||
#### 新增
|
||||
|
||||
- **`GET /healthz` 匿名存活探针**:只返回 `200` 与字面量 `ok`,**不含任何字段**。
|
||||
供 K8s liveness/readiness、Docker HEALTHCHECK、负载均衡健康检查使用 ——
|
||||
这些探针默认不带 `Authorization`,若继续指向 `/health` 会因鉴权而全部失败。
|
||||
- **`GET /api/admin/health` 鉴权版详细健康数据**:与 `/api/admin/metrics` 风格一致,
|
||||
供管理面板与运维使用。
|
||||
- **`METRICS_ALLOW_CIDR` 内网白名单**(逗号分隔 CIDR,支持裸 IP 自动补掩码):
|
||||
配置后在根路径注册 `/metrics`,仅放行白名单来源;**非白名单返回 404 而非 403**,
|
||||
不向扫描者确认端点存在。未配置时根路径 `/metrics` **完全不注册**。
|
||||
- **独立管理凭证 `admin_key`(可选)**:管理接口凭证与业务调用凭证分离。
|
||||
取值优先级 `admin_key`(DB) → `auth_key`(DB) → `OPENAI_TTS_API_KEY`(env)。
|
||||
**不配置时行为与旧版完全一致**(回退用 `auth_key`),配置后业务 key 无法访问管理接口。
|
||||
@@ -18,14 +26,22 @@
|
||||
|
||||
#### 变更(Breaking Change)
|
||||
|
||||
- **`/health`、`/metrics`、`/dashboard` 不再匿名可读**:
|
||||
- `/health` → 鉴权(原匿名,泄漏版本 / commit / 内存 / goroutine / 配置错误文本)
|
||||
- `/dashboard` → 鉴权(原匿名,且它同时聚合 `/health` + `/metrics`,是单点泄漏最严重的端点)。
|
||||
对浏览器 HTML 请求做内容协商:返回页面外壳由前端显示登录视图;非 HTML 请求(脚本、抓取)无凭证一律 401。
|
||||
- 根路径 `/metrics` → 需要 `METRICS_ALLOW_CIDR`,否则 404
|
||||
- `/api/setup/status` → 鉴权(原本 normal 模式下仍匿名返回 `{installed, mode}`)
|
||||
- **`RequireAdmin` 在凭证未配置时不再放行**。此前 `len(keys)==0` 直接放行,导致未配置凭证的
|
||||
部署上管理接口完全裸奔(也使得给 `/metrics`、`/health` 加鉴权的加固形同虚设)。
|
||||
现在该情况返回 **401**。
|
||||
- **normal 模式下未配置任何管理凭证时服务拒绝启动**(fail-fast),并在启动摘要中打印
|
||||
管理凭证来源。此前会正常启动但后台实际无保护。
|
||||
部署上管理接口完全裸奔(也使得给 `/metrics`、`/health` 加鉴权的加固形同虚设)。现在该情况返回 **401**。
|
||||
- **normal 模式下未配置任何管理凭证时服务拒绝启动**(fail-fast),启动摘要打印管理凭证来源。
|
||||
|
||||
> ⚠️ **升级提示**:若你的部署当前未配置 `auth_key` / `admin_key` / `OPENAI_TTS_API_KEY`
|
||||
> 中的任何一个,升级到本版本后服务将拒绝启动。请先配置其中之一。
|
||||
> ⚠️ **升级提示**
|
||||
> 1. 若部署未配置 `auth_key` / `admin_key` / `OPENAI_TTS_API_KEY` 中任何一个,升级后服务将拒绝启动。
|
||||
> 2. K8s 探针 / Docker HEALTHCHECK 请改指 **`/healthz`**;Prometheus 请改用鉴权版
|
||||
> `/api/admin/metrics`,或配置 `METRICS_ALLOW_CIDR`。
|
||||
> 3. `METRICS_ALLOW_CIDR` 在 Docker 中**不要填 `127.0.0.1/32`**(那是容器自身回环),
|
||||
> 请填容器内网网段(如 `172.16.0.0/12`)。
|
||||
|
||||
### 修复
|
||||
|
||||
|
||||
Reference in New Issue
Block a user