fix(audit): inferAuditFields 下标越界导致进程级 panic(4 段路径全部 500)
=== 现象(线上实际日志)===
http: panic serving 172.19.16.138:35256: runtime error: index out of range [4] with length 4
lokistack/middleware.inferAuditFields(...)
lokistack/middleware/audit.go:179
=== 根因 ===
segments := strings.Split(strings.Trim(path, "/"), "/")
if len(segments) >= 4 {
resource = segments[3]
resourceID = segments[4] // ← 4 段时越界
}
/api/v1/hosts/2 正好拆成 4 段 [api v1 hosts 2],取 segments[4] 直接 panic。
影响面比想象大:**所有 4 段路径的写请求**(PUT/DELETE /hosts/:id、
/storage/:id、/clusters/:id 等)都 500,且中间件 panic 后审计也写不进去
—— 等于审计功能在最常用的更新/删除接口上完全失效。
=== 修法 ===
每个下标单独判断长度:
if len(segments) >= 3 { module = segments[2] }
if len(segments) >= 4 { resource = segments[3] }
if len(segments) >= 5 { resourceID = segments[4] }
=== 回归测试(middleware/audit_test.go)===
TestInferAuditFieldsNoPanic : 0/1/2/3/4/5 段的 12 种路径 × 3 种方法,
全部不得 panic(原 bug 的 4 段路径在列)
TestInferAuditFieldsFourSegments : 4 段时 module/resource 正确、resourceID 为空
TestInferAuditFieldsFiveSegments : 5 段时能解出 resourceID
TestInferAuditFieldsSemanticActions: deploy/stop/install/uninstall/reset-password/
validate/test 语义动作不被位置解析覆盖
TestShouldAudit : 只读接口跳过、部署安装类必须记
=== 顺带修:CLI 模式下的两处误报 ===
1) backup 的 manifest.recordCount 恒为 0
原因:CLI(CronJob 里跑 lokistack backup)没 init DB,GetDB() 返回 nil。
改为 countRecords() 直接从备份出的字节数集合。
2) self-check 报「数据库: 未初始化」
同上原因,误报会让巡检脚本以为库坏了。
改为 CLI 模式直接解析数据文件统计(fileDBStats)。
=== 实测(修复后)===
修复前:POST /api/v1/hosts/2/validate → panic,无审计记录
修复后:POST /api/v1/hosts/2/validate → 200
audit-logs total=5,含
[hosts/validate] admin POST /api/v1/hosts/2/validate -> 200
[auth/login] POST /api/v1/auth/login -> 200
panic serving 计数 = 0
用户数据完好(initial-admin-password.txt 不存在,说明不是首次部署)
镜像:lghost/lokistack:latest + v0.1 = 2493a288758d
This commit is contained in:
1 parent
c44ffad61f
commit
b2c82da377
4 files changed
+179
-10
No files matched your search
@@ -171,11 +171,19 @@ func inferAuditFields(method, path string) (module, action, resource, resourceID
|
||||
|
||||
segments := strings.Split(strings.Trim(path, "/"), "/")
|
||||
// /api/v1/<module>/<resource>/<id>
|
||||
//
|
||||
// ⚠️ 每个下标必须单独判断长度。曾经写成:
|
||||
// if len(segments) >= 4 { resource = segments[3]; resourceID = segments[4] }
|
||||
// 而 /api/v1/hosts/2 正好只有 4 段([api v1 hosts 2]),
|
||||
// segments[4] 直接 index out of range → 中间件 panic →
|
||||
// 所有「4 段路径」的写请求 500 且不落审计(线上实际发生过)。
|
||||
if len(segments) >= 3 {
|
||||
module = segments[2]
|
||||
}
|
||||
if len(segments) >= 4 {
|
||||
resource = segments[3]
|
||||
}
|
||||
if len(segments) >= 5 {
|
||||
resourceID = segments[4]
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user