跳转至

自动处置离线干跑矩阵(ar-local-matrix.py)

位置:deploy/nfos/tools/ar-local-matrix.py | 语言:python3 | 是否需要 root:否

工具性质:离线干跑矩阵(纯评估不动系统;子进程一律 --dry-run;会写自己的临时目录) 运行前提:仓库检出必须在场 —— 把 deploy/nfos/monitoring/auto-respond.py 当子进程跑。可从任意位置运行(工具自动向上找到含 deploy/nfos 的祖先目录) 部署状态:随仓库检出运行,不部署到 /opt/Cy/services/system.d/nfos/


用途

对 deploy/nfos/monitoring/auto-respond.py 做本地干跑矩阵:把一批构造好的告警条目逐条喂给它,核对“该封禁的封禁、该拒绝的拒绝、该转人工的转人工”。

源码 docstring(逐字引用):

auto-respond.py 离线干跑矩阵(本地 Windows/Linux 均可跑,纯评估不动系统)。

用法: python .scratch/ar-local-matrix.py

矩阵共 17 个用例,覆盖:

类别 用例(标签逐字来自源码 CASES)
应动作 WA-002 公网 IP(应自动封禁)、RS-002 普通反弹 shell 进程(应取证+杀+封对端)、MW-002 解释器执行 /tmp 脚本(应取证+杀+隔离)、AU-001 SSH 爆破公网源(应 nft drop)
应拒绝 WA-001 私网 IP(应拒绝)、WA-002 运维出口白名单 IP(应拒绝)、WA-002 回环(应拒绝)、WA-002 邮件中继(应拒绝,防自断告警邮件)、MW-001 关键路径载荷(应拒绝隔离)、AU-001 来源是运维白名单网段(应拒绝)
应抑制/不动作 RS-001 平台告警通道 ticket-notify.py(应 suppress 不动作)、RS-003 sshd 派生 shell(受保护/不动作)
不处置、转人工开单 PS-001 计划任务新增(不处置,转人工开单)、IN-001 信任根被修改(不处置,转人工开单)、EG-001 异常外联(不处置,转人工开单)、SL-001 日志异常(不处置,转人工开单)
输入健壮性 输入非法 JSON(应 INTERNAL 且退出码 0)

每个用例的调用方式(源码):subprocess.run([PY, AR, "--dry-run"], input=<JSON>, capture_output=True, env=env, timeout=120),其中 PY = sys.executable or "python3";随后解析最后一行 stdout 为 JSON,并打印 exit / handled / suppress / escalate / reason_code / would_handle、action、targets、planned_steps、detail。

末尾固定打印 非零退出数: <N>(必须为 0)、三个“应为 False”的落盘状态、以及 MATRIX_DONE。

典型场景

  • 改动 auto-respond.py(--dry-run 分支、白名单判定、suppress 规则、planned_steps 文案)之后的提交前回归;
  • 白名单/防自断逻辑出问题时(例如把邮件中继 122.14.236.108 或平台告警通道的 ticket-notify.py 误封)在本地复现;
  • 新加特征签名时,用矩阵确认它在 auto-respond 里的处置分类(动作 / 拒绝 / 抑制 / 转人工)符合预期。

用法与参数

源码 docstring 给出的用法(逐字引用,.scratch/ 为升级前旧路径,本页按新位置书写为 python deploy/nfos/tools/ar-local-matrix.py):

用法: python .scratch/ar-local-matrix.py
参数 类型 默认值 说明
(无命令行参数) — — 不读 sys.argv、无 argparse
AR_VERBOSE 环境变量(可选开关) 未设置(假) 非空时额外打印每例的 commands 与子进程 stderr(截断 300 字符)

无参数时的默认行为:跑完 17 个用例,打印汇总与 MATRIX_DONE。

示例

从仓库根目录执行:

python deploy/nfos/tools/ar-local-matrix.py

需要看每例的 commands 时:

$env:AR_VERBOSE = "1"
python deploy/nfos/tools/ar-local-matrix.py

期望输出(实测:退出码 0,末行 MATRIX_DONE):

非零退出数: 0(必须为 0)
工作目录(tmp): ...\deploy\nfos\tools\ar-tmp
状态文件是否被写(应为 False): False
审计日志是否被写(应为 False): False
封禁清单是否被创建(应为 False): False
MATRIX_DONE
情形 期望退出码
正常跑完(末行 MATRIX_DONE) 0
某个用例子进程非 0 仍是 0(只把 非零退出数 累加并打印 !! 退出码非 0)
脚本自身崩掉(如 deploy/nfos/monitoring/auto-respond.py 路径不存在、临时目录不可建) 1(Python traceback)

重要:本脚本没有 sys.exit,退出码不代表矩阵结论。判定必须看 非零退出数: 0(必须为 0) 这一行以及上方逐例的 handled / suppress / escalate / action 是否与用例标签相符。

依赖与权限

  • 语言/版本:Python 3(#!/usr/bin/env python3)。
  • 第三方依赖:无,标准库 json / os / shutil / subprocess / sys。
  • 仓库依赖:必需 —— 子进程执行 <repo>/deploy/nfos/monitoring/auto-respond.py;_nf_repo_root() 向上找第一个含 deploy/nfos 的祖先目录。
  • 权限:不需要 root;需要工作区写权限(建 ar-tmp)。矩阵会写一份临时特征库与一组环境变量,全部指向临时目录。

风险与注意事项

  • 不在真机上执行系统动作:子进程固定带 --dry-run;env 把 NFOS_AR_ROOT / NFOS_AR_NGINX_D / NFOS_AR_NFOS_DIR / NFOS_AR_LIBOPS / NFOS_AR_GUARD 全部重定向到临时目录,NFARMSD_API 指向 http://127.0.0.1:19990(不会打到真实平台),并设 NFOS_AR_MAX_ACTIONS=3。因此不会封 IP、不会执行 nft/nginx 变更、不会写线上状态。
  • 会写文件(自己的临时目录):<工具所在目录>/ar-tmp/ —— 源码写作 tmp = os.path.join(HERE, "ar-tmp"),而 HERE = os.path.dirname(os.path.abspath(__file__)),即产物落在工具旁边:deploy/nfos/tools/ar-tmp/。该目录在每次启动时先 shutil.rmtree 再重建,内含:
  • ar-tmp/nfos/signature-library.yml(矩阵自带的临时特征库,含白名单网段)
  • ar-tmp/nfos/lib-ops.sh、ar-tmp/nfos/security-guard.sh(路径占位,指向临时目录)
  • ar-tmp/logs/、ar-tmp/nginx.d/(运行期目录)
  • 末尾三项自证:脚本会打印 logs/auto-respond.state.json、logs/auto-respond.log、nginx.d/10-nfos-blocklist.conf 是否存在,期望全为 False —— 若出现 True,说明 --dry-run 语义被破坏,属于需要立刻排查的回归。
  • 用工作区内的临时目录是有意设计(源码注释:Windows 上 %TEMP% 在沙箱里可能不可写),所以别指望它落在系统临时目录。
  • 环境变量是传给子进程的,不修改当前 shell;但 HERE 依赖脚本自身位置 —— 若把本工具挪出 deploy/nfos/tools/,ar-tmp 会跟着挪到新位置。

回滚

本工具不部署到线上、不改线上系统;不产出交付物。

  • 产出/改动位置:deploy/nfos/tools/ar-tmp/(每次运行自动清空重建)。
  • 清理方式:
Remove-Item -Recurse -Force deploy/nfos/tools/ar-tmp
  • 不写 auto-respond.state.json / auto-respond.log / 封禁清单到线上路径(末尾三项自证应全为 False);因此无需回滚线上自动处置状态。