跳转至

日志审计报告离线自测(log-audit-report-test.py)

位置:deploy/nfos/tools/log-audit-report-test.py | 语言:python3 | 是否需要 root:否

工具性质:离线自测(会写临时文件;不联网、不调 journalctl、不需要 root) 运行前提:仓库检出必须在场 —— 加载 deploy/nfos/log-audit.py。可从任意位置运行(工具自动向上找到含 deploy/nfos 的祖先目录) 部署状态:随仓库检出运行,不部署到 /opt/Cy/services/system.d/nfos/


用途

对 deploy/nfos/log-audit.py 做离线自测,覆盖报告生成、状态文件原子替换、自动恢复与窗口解析回退。

源码 docstring 的用法与覆盖点(逐字引用):

    python3 .scratch/log-audit-report-test.py

覆盖:
  1. 报告文件:无命中 → 写“未发现异常”;有命中 → 签名/计数/最多 3 条样例
  2. 目录不存在时自动 mkdir -p(幂等,跑两次)
  3. 状态文件:本轮活动键 + 时间戳(原子替换)
  4. 自动恢复:只恢复 `nfos.log:` 前缀的键;平台不可达时返回 recovered=False 而不抛异常
  5. 窗口表达式解析失败时回退为原样字符串(不抛异常)

实际执行的 6 组用例:1(无命中报告)、1b(库缺 log_anomaly 条目时的 aborted 报告,备节点实测形态)、2(有命中:签名/计数/最多 3 条样例 / 工单号 / 自动恢复结果 / --dry-run 另存 *-dryrun.md)、3(报告目录被删后自动 mkdir -p 且重复写入幂等)、4(状态文件覆盖更新 + 原子替换后无残留 .tmp)、5(recover_stale 只碰 nfos.log: 前缀,空列表/None 安全)、6(window_bounds 解析失败原样保留)。

被测入口:write_report、state_put、recover_stale、window_bounds,以及模块常量 REPORT_DIR、STATE_FILE。

典型场景

  • 改动 log-audit.py 的 write_report / 自动恢复逻辑之后的提交前回归;
  • 备节点出现“特征库里没有 detect=log_anomaly 的条目”导致审计空跑时,用 1b 用例确认报告文案是 本次审计未执行 而不是误写成“未发现异常”;
  • 平台不可达(nfarmsd 挂掉)时确认自动恢复不抛异常、报告仍照常产出。

用法与参数

源码 docstring 给出的用法(逐字引用,.scratch/ 为升级前旧路径,本页按新位置书写):

    python3 .scratch/log-audit-report-test.py

本工具不接受任何命令行参数;它在进程内改写三个环境变量(只影响本进程,不写入系统环境):

参数 类型 默认值 说明
(无) — — 无 argparse、不读 sys.argv
NFOS_DIR 环境变量(进程内设置) <repo>/.tmp/log-audit-test/nfos 被加载模块的 NFOS 目录
NFOS_LOG_AUDIT_REPORT_DIR 环境变量(进程内设置) <repo>/.tmp/log-audit-test/reports 报告输出目录
NFARMSD_API 环境变量(进程内设置) http://127.0.0.1:9 故意指向必然连不上的端口,用于验证“平台不可达不抛异常”

无参数时的默认行为:跑完 1–6 组全部用例,打印结论与 ALL_PASS,结束时删除自己的临时目录。

示例

从仓库根目录执行:

python deploy/nfos/tools/log-audit-report-test.py

期望输出(实测:检查项 27、失败 0,末行 ALL_PASS):

检查项 27,失败 0
ALL_PASS

中间会打印 == 1. 报告文件:无命中 == … == 6. 窗口解析回退 == 与逐项 ok ...。

情形 期望退出码
全部通过(检查项 N,失败 0 + ALL_PASS) 0
存在失败项(检查项 N,失败 M 后逐条列出 FAIL) 1
被加载模块缺失 / 模块级代码抛异常 1(importlib 异常,Python traceback,非自检语义)

依赖与权限

  • 语言/版本:Python 3(#!/usr/bin/env python3)。
  • 第三方依赖:无,标准库 importlib.util / io / json / os / shutil / sys / tempfile。
  • 仓库依赖:必需 —— 加载 <repo>/deploy/nfos/log-audit.py;_nf_repo_root() 向上找第一个含 deploy/nfos 的祖先目录。
  • 权限:不需要 root;需要工作区写权限(写 <repo>/.tmp/log-audit-test/)。

风险与注意事项

  • 会写文件(仅自己的临时目录):<repo>/.tmp/log-audit-test/,内含测试用报告(含 *-dryrun.md)与状态文件;正常结束时 shutil.rmtree 删除。
  • 不碰线上:NFARMSD_API 被指向 127.0.0.1:9,因此不会真的调用 nfarmsd 写恢复;不调用 journalctl、不读 /opt/Cy/logs 以外的真实日志、不需要 root —— 源码 docstring 自述“不联网、不调 journalctl、不需要 root”。
  • 环境变量是进程内注入:三个变量在脚本内 os.environ[...] = ... 覆盖,只影响本进程与被它 import 的模块;不会改系统/用户环境,也不会污染父 shell。
  • 会执行被测模块的模块级代码:log-audit.py 的模块级常量(如 REPORT_DIR、STATE_FILE)会在加载时按注入的环境变量求值 —— 这正是用例 3/4 能重定向报告目录与状态文件的原因。
  • 断言锁定的是报告文案契约(未发现异常、本次审计未执行、/libs/apply、已恢复、dry-run、命中条数:0、命中次数:3 等):改动这些文案需同步改本自测。

回滚

本工具不部署到线上、不改线上系统;唯一的落盘物是它自己的临时目录。

  • 落盘位置:<repo>/.tmp/log-audit-test/(报告目录 + 状态文件 + nfos/ 子目录)。
  • 正常情况下运行结束自动删除;被中断时手动清理:
Remove-Item -Recurse -Force .tmp/log-audit-test
  • 不写 deploy/nfos/state/、不写 /opt/Cy/logs/,因此无需回滚线上报告或状态文件。