审计链 100% 与 HITL 100%:两个数字怎么落到机制上
审计链完整率 100% 与 HITL 覆盖率 100% 各由一套机制支撑:已写入的审计记录能否被独立重算校验;高风险动作是否经过人工门禁,以及门禁主体是本人放行还是他人批准。
有日志为何不足以支撑追责
Section titled “有日志为何不足以支撑追责”常规审计记录操作主体、时间与内容,可用于故障排查时的时间线还原。
追责还要求记录在写入之后仍可被独立重算校验。负责写日志的运行时通常也能改日志;存储中存在一条记录,只说明当前可查询,不代表该记录自写入起未被改动。
因此审计需要可重算结构:同一批进入链的字段必须得到同一摘要;任一记录被改,其后整条链的校验失败。事后改写与正常追加由此在结果上可区分。
哈希链的写入与校验
Section titled “哈希链的写入与校验”每条审计记录携带两个摘要字段:
prev_hash:上一条的摘要;链首为固定创世值(约定长度的零串)hash:由prev_hash与本条规范化正文共同计算
hash = sha256(prev_hash + "\n" + canon(body))body 含租户、会话、事件类型、载荷、时间等进入链的字段。canon 将正文收成稳定、可复现的序列,避免同内容因序列化差异得到不同摘要。
写入按时间顺序接到链尾。校验按时间顺序重算:当前记录的 prev_hash 须等于上一条的 hash,当前 hash 须等于按现正文重算的结果。任一步失败即停止,并返回断点记录标识。
对外校验接口为 GET /audit/verify。响应形态示例:
{ "ok": true, "checked": 50, "broken_at": null }{ "ok": false, "checked": 12, "broken_at": "aud_…" }checked 为已重算条数;broken_at 非空时指向断点。部署验收脚本调用同一接口,要求完成链扫描。
能力边界: 哈希链约束写入完成之后对历史的改写。若写入路径已被控制,仍可先写入虚假内容再生成匹配摘要。在写入路径可信的前提下,事后改写旧记录会被校验发现。该项能力覆盖写入后的完整性,不覆盖写入瞬间的防伪。
mutating 路径上的 100% 覆盖
Section titled “mutating 路径上的 100% 覆盖”操作按外部副作用分层。仅 mutating(会产生外部副作用的动作)强制审计,并按规则强制审批:
| 层 | 例子 | 审计 | 审批 |
|---|---|---|---|
| Read | 读文件、查日志 | 保留 | 否 |
| Write | 改工作区、生成补丁 | 保留 | 视规则 |
| mutating | 推送、发邮件、生产变更、付款 | 必须 | 视规则强制 |
读、查类操作若一律强制人工审批,可用性下降;推送、变更、付款类操作若允许漏记,事故调查会缺少关键片段。因此门禁集中在 mutating。
此处 100% 表示 mutating 路径必须持续落链,不允许间歇性缺失。审计覆盖是二元条件:路径始终落链,或在关键时刻出现空白。
复核口径: GET /audit/verify 的 checked 统计当前租户内已落链且可重算的记录是否完整,不等于业务侧发生过的全部 mutating 次数。后者还取决于动作是否进入落链路径。两套数字须分开使用。
校验假阳性:正文形态不一致
Section titled “校验假阳性:正文形态不一致”常见假阳性:校验报告断链,但存储未被人工改动。根因是计算摘要时的正文形态,与落盘后再读出的正文形态不一致。
字段顺序。 同一内容在序列化时若键序不同,摘要不同,校验会误报篡改。进入哈希前须规范化键序:
const keys = Object.keys(obj) .filter((k) => obj[k] !== undefined) .sort()空值字段。 内存表示可保留空值字段;写入 JSON 等存储后,这类字段常被省略。若按写入前形态计算摘要、按读出后形态校验,正文已变化,校验失败。正确写入顺序:先将正文收敛为与落盘一致的形态,再计算摘要,再入库。
上述问题在仅测试写入时不易暴露,完整校验才会出现。确认属于序列化缺陷导致的假阳性后,可按时间序重算并写回摘要字段;该路径不用于掩盖真实内容篡改,执行前须先导出留存。
本人确认与他人审批分流程
Section titled “本人确认与他人审批分流程”审计链回答记录是否被改写。HITL 回答高风险动作是否经过人工门禁,以及门禁主体是谁。二者对应不同流程与事件:
| 流程 | 条件 | 审计事件 | 是否进入审批待办 |
|---|---|---|---|
| 本人确认 | 执行者在会话内允许本次操作 | permission.* | 否 |
| 他人审批 | 另一角色批准 | approval.*(含 requester_id / decided_by) | 是 |
两类动作若共用待办表,HITL 覆盖率统计会把自批计入人工审批,覆盖率失真。
规则:执行者不能在审批中心批准自己发起的工单。自批不属于审批流程。追责时分别检索 permission.* 与 approval.*。
会话内放行属于既有权限能力;跨人审批与可重算审计属于额外信任边界,须单独度量与复核。
相关阅读: