JacobRHess/sigma-pipeline
GitHub: JacobRHess/sigma-pipeline
一个为 Sigma 检测规则提供夹具驱动测试、lint 校验、覆盖率分析和 Splunk 自动部署的 Detection-as-CODE CI/CD 流水线工具。
Stars: 0 | Forks: 0
# sigma-pipeline
[](https://github.com/JacobRHess/sigma-pipeline/actions/workflows/ci.yml)
[](LICENSE)
[](https://www.python.org/downloads/)
针对 [Sigma](https://github.com/SigmaHQ/sigma) 检测规则的夹具驱动测试。每条规则都附带了其应该匹配和不应匹配的示例事件 —— 发生回归将像单元测试失败一样中断构建。
```
sigma lint rules/
sigma test rules/ --fixtures tests/fixtures
sigma diff rules/ ../old-rules/ # what changed in our coverage?
sigma coverage rules/ --format navigator --output coverage.json
sigma deploy rules/ --host splunk.example.com --target-index main
```
基于 [splunk-sigma](https://github.com/JacobRHess/splunk-sigma)(规则评估引擎)构建,并可选地支持 [`pySigma`](https://github.com/SigmaHQ/pySigma)(在 `--strict` 模式下提供额外的验证器)。
## 为什么存在这个项目
检测规则没有单元测试。
大多数团队将 Sigma 规则视为配置:有人编写了 YAML,然后将其部署,而下一次有人发现它失效时,往往是因为真实的事件已经漏网。Sigma 生态系统拥有用于验证规则结构([pySigma](https://github.com/SigmaHQ/pySigma)、[sigma-cli](https://github.com/SigmaHQ/sigma-cli))和将规则转换为供应商查询语言的出色工具 —— 但对于提出以下这个最重要的问题,却没有标准化的方法:
`sigma-pipeline` 回答了这个问题。每条规则都有一个包含正向夹具(规则必须匹配的事件)和负向夹具(规则绝不能匹配的事件)的文件夹。`sigma test` 会遍历它们,一旦发现任何遗漏就会让构建失败。lint、coverage、diff 和 deploy 阶段的存在是为了让这个测试循环在实际工作流中真正可用 —— 它们只是脚手架,而不是核心。
| 阶段 | 作用 |
|----------|-----------------------------------------------------------------------------------|
| lint | YAML schema、必填字段、ATT&CK 标签格式、唯一 ID、条件解析。`--strict` 会添加 pySigma 的验证器套件。 |
| test | 每条规则对其正向夹具触发,并对其负向夹具保持静默 |
| diff | 比较两套规则集,报告增加/移除/修改的规则以及覆盖率差异 |
| stats | 按严重性 / ATT&CK 战术 / 日志源统计规则数量 —— 用于一目了然地掌握概况 |
| coverage | 生成 markdown 表格 + ATT&CK Navigator JSON 层,用于热力图可视化 |
| deploy | 验证后的规则在合并到 main 分支时,会幂等地成为 Splunk 中的保存搜索 |
如果有人调整了规则中的正则表达式,test 阶段会捕获到覆盖率悄然失效的情况。这正是当今大多数检测团队所缺少的闭环。
## 适用人群
`sigma-pipeline` 适用于以下团队:
- 在 Git 中管理 Sigma 规则
- 希望在规则更改合并前进行 CI 检查
- 需要确信规则仍然能够匹配已知的恶意样本
- 希望在 MITRE ATT&CK 中获得覆盖率可见性
- 将检测规则部署到 Splunk
## 流水线
```
flowchart LR
PR[Pull request
touches rules/] --> Lint[sigma lint
--strict] Lint --> Test[sigma test
fixtures] Test --> CovDiff[sigma diff
+ coverage delta] CovDiff -->|sticky comment on PR| Reviewer{{Reviewer}} Reviewer -->|approve + merge| Main[main branch] Main -->|workflow_dispatch| Gate[[production
environment
approval]] Gate --> Deploy[sigma deploy
--with-dashboard] Deploy --> Splunk[(Splunk
saved searches
+ dashboard)] ``` 每个阶段都是一个真实的 GitHub Actions 作业:[`ci.yml`](.github/workflows/ci.yml) 在每次推送时运行 lint 和 test,[`pr-coverage-diff.yml`](.github/workflows/pr-coverage-diff.yml) 在涉及规则更改的 PR 上发布覆盖率差异评论,而 [`deploy.yml`](.github/workflows/deploy.yml) 是一个手动的 `workflow_dispatch` 部署操作,通过 `production` 环境进行人工审批。部署作业在推送之前会再次运行 lint 和 test —— 仅仅显示合并成功并不能替代在部署时针对 `main` 分支的确切状态重新进行验证。 ## 快速入门 ``` git clone https://github.com/JacobRHess/sigma-pipeline cd sigma-pipeline pip install -e .[dev] sigma lint rules/ sigma test rules/ --fixtures tests/fixtures sigma deploy rules/ --dry-run # prints the deploy plan, makes no changes ``` ## 仓库结构 ``` sigma-pipeline/ ├── src/sigma_pipeline/ │ ├── cli.py argparse entrypoint, registers subcommands │ ├── lint.py rule-file linter (+ optional pySigma backend) │ ├── pysigma_backend.py pySigma validator wrapper, used by `lint --strict` │ ├── test.py fixture-driven tester │ ├── diff.py rule-set / coverage diff │ ├── stats.py rule-corpus summary (severity / tactic / logsource) │ ├── coverage.py ATT&CK coverage reporter │ └── deploy.py Splunk REST-API deploy ├── rules/ .yml Sigma rules (the detection content) ├── tests/fixtures/ │ └──/
│ ├── positive/ *.json events the rule MUST match
│ └── negative/ *.json events the rule MUST NOT match
└── .github/workflows/ci.yml
```
## 测试如何工作
每条规则在 `tests/fixtures//` 下都有自己的文件夹。在其中,`positive/` 存放规则必须匹配的 JSON 事件文件(真阳性),而 `negative/` 存放规则绝不能匹配的事件(类似于威胁的良性干扰数据)。
夹具文件可以是单个 JSON 对象,也可以是对象数组。
```
tests/fixtures/t1059_001_pwsh_encoded/
├── positive/
│ ├── encoded_command.json
│ └── encoded_pwsh7.json
└── negative/
└── normal_powershell.json
```
```
$ sigma test rules/ --fixtures tests/fixtures
t1059_001_pwsh_encoded (PowerShell Encoded Command Execution)
[PASS] positive encoded_command.json 1/1 events matched
[PASS] positive encoded_pwsh7.json 1/1 events matched
[PASS] negative normal_powershell.json 0/2 events matched (expected 0)
test: 3 rule(s), 8 case(s), 0 failure(s), 0 rule(s) without fixtures
```
失败的情况如下所示:
```
[FAIL] positive encoded_command.json 0/1 events matched
-> 1/3 case(s) failed
```
没有夹具的规则会被报告为未经测试,但不会导致运行失败,因此可以逐步采用该流水线。
## 严格 Lint (pySigma)
`sigma lint --strict` 会在内置检查之外运行 [pySigma](https://github.com/SigmaHQ/pySigma) 验证器套件。pySigma 是由 SigmaHQ 维护的上游参考实现;它了解修饰符语义、已弃用的字段、标题约定以及数十种内置 linter 不必重复实现的其他规则质量问题。
```
pip install -e .[strict]
sigma lint rules/ --strict
```
严格模式是可选的,这样可以使基础安装保持轻量 —— pySigma 会引入一个不小的依赖树。
## 覆盖率差异
`sigma diff` 比较两套规则集并报告变化:
```
sigma diff rules/ ../old-rules/
```
```
Rules:
+ t1546_008_accessibility_features
- t1059_001_pwsh_encoded_legacy
~ t1003_001_lsass_dump (severity: high → critical)
Coverage:
+ T1546.008 (accessibility features)
- T1059.001 (powershell, no longer covered)
score: T1003.001 4 → 5
```
可用作 PR 评论(“这是该分支对我们的检测覆盖率所做的更改”),也可作为发布说明生成器。通过 `--format markdown` 输出 Markdown 格式。
**在 CI 中自动化:** `.github/workflows/pr-coverage-diff.yml` 会在每个涉及 `rules/` 更改的 PR 上运行 `sigma diff`,并将结果作为置顶 PR 评论发布。审查者可以一目了然地看到覆盖率影响,而无需阅读原始的 YAML 差异。该评论会在每次新提交时原地更新。
## 规则概览
`sigma stats` 一目了然地总结规则库 —— 对发布说明或快速健康检查很有用:
```
$ sigma stats rules/
Rules: 6
Techniques: 6
Severity:
high 4
critical 2
By tactic:
command_and_control 1
credential_access 1
defense_evasion 1
execution 1
impact 1
persistence 1
By logsource:
process_creation/windows 6
```
## ATT&CK 覆盖率
`sigma coverage` 遍历规则并以两种格式输出覆盖率:
```
# Markdown 表格 — 添加至 README 或 PR 评论中。
sigma coverage rules/ --format markdown --output docs/COVERAGE.md
# ATT&CK Navigator JSON layer — 上传至
# https://mitre-attack.github.io/attack-navigator/ 以查看 heatmap 视图。
sigma coverage rules/ --format navigator --output coverage.json
```
严重性映射为 1–5 的分数(informational → critical),Navigator
据此为技术着色。被多个规则覆盖的技术采用
最高分。
预渲染的 markdown 报告已签入至 [`docs/COVERAGE.md`](docs/COVERAGE.md)。
## 部署如何工作
`sigma deploy` 将每条规则注册为 Splunk 保存搜索,其 SPL 为:
```
search index= | sigma rules="id:"
```
`splunk-sigma` 应用在搜索时进行实际的评估;保存搜索是一个轻量级的句柄,以便分析师可以从 Splunk Web 中查找、安排每个规则并对其发出警报。部署是幂等的(现有的保存搜索会原地更新;新的则会被创建)。
`--with-dashboard DIR` 会额外通过 `data/ui/views` REST 端点将 `DIR` 下的每个 `*.xml` 作为 Splunk SimpleXML 视图推送,这也是幂等的。[`splunk/dashboards/sigma_overview.xml`](splunk/dashboards/sigma_overview.xml) 中包含了一个参考仪表板 —— 提供规则/技术/战术的单值磁贴、按严重性堆叠的随时间变化的触发次数、触发次数最多的规则、严重性饼图、技术热力图以及最近的触发表。
身份验证使用 `SPLUNK_USERNAME` / `SPLUNK_PASSWORD` 环境变量。`--dry-run` 标志只打印计划而不进行写入。
```
export SPLUNK_USERNAME=admin
export SPLUNK_PASSWORD=''
sigma deploy rules/ --host splunk.example.com --target-index main \
--with-dashboard splunk/dashboards
```
## CI 工作流
三个 GitHub Actions 工作流构成了该流水线:
| 工作流 | 触发器 | 作用 |
|----------|---------|--------------|
| [`ci.yml`](.github/workflows/ci.yml) | push, pull_request | lint(`--strict` 为建议性)、pytest、多 Python 版本矩阵 |
| [`pr-coverage-diff.yml`](.github/workflows/pr-coverage-diff.yml) | 针对 `rules/**` 的 pull_request | 针对基础分支运行 `sigma diff`,并发布一条包含规则和覆盖率差异的置顶评论 |
| [`deploy.yml`](.github/workflows/deploy.yml) | workflow_dispatch | 重新运行 lint 和 test,然后进行部署(`dry-run` 或 `apply`);`apply` 需要通过 `production` GitHub 环境进行人工审批 |
部署身份验证来自 `SPLUNK_USERNAME` 和 `SPLUNK_PASSWORD` 仓库机密。该作业是故意设计为手动的 —— 检测内容不应该在没有人工查看覆盖率差异的情况下就发布。
## 添加规则
1. 按照 Sigma 规范将 YAML 放入 `rules/` 中。
2. 创建 `tests/fixtures//positive/*.json`,其中至少包含一个规则应匹配的事件。
3. 创建 `tests/fixtures//negative/*.json`,其中至少包含一个规则不应匹配的事件(能够测试边界的近似未命中事件比完全无关的事件更有价值)。
4. 在本地运行 `sigma lint rules/` 和 `sigma test rules/ --fixtures tests/fixtures`。
5. 发起一个 PR。CI 会在合并前运行相同的检查。
## 局限性
- 夹具质量决定了测试质量;通过的测试并不能证明规则能捕获所有变体。
- 没有夹具的规则会被报告,但默认情况下不会失败。
- Splunk 部署假定目标 Splunk 环境中已安装并提供了 [`splunk-sigma`](https://github.com/JacobRHess/splunk-sigma)。
- 当前的部署目标是 Splunk;其他 SIEM 后端尚未实现。
## 依赖项
- [`splunk-sigma`](https://github.com/JacobRHess/splunk-sigma) — 提供规则评估引擎(`sigma_engine` 包)。
- [`splunk-sdk`](https://pypi.org/project/splunk-sdk/) — deploy 阶段使用的 Splunk REST API 客户端。
- [`pySigma`](https://github.com/SigmaHQ/pySigma) — 可选,被 `lint --strict` 用于上游验证器套件。
- `pyyaml` — 规则文件解析。
## 许可证
MIT — 见 [`LICENSE`](LICENSE)。
touches rules/] --> Lint[sigma lint
--strict] Lint --> Test[sigma test
fixtures] Test --> CovDiff[sigma diff
+ coverage delta] CovDiff -->|sticky comment on PR| Reviewer{{Reviewer}} Reviewer -->|approve + merge| Main[main branch] Main -->|workflow_dispatch| Gate[[production
environment
approval]] Gate --> Deploy[sigma deploy
--with-dashboard] Deploy --> Splunk[(Splunk
saved searches
+ dashboard)] ``` 每个阶段都是一个真实的 GitHub Actions 作业:[`ci.yml`](.github/workflows/ci.yml) 在每次推送时运行 lint 和 test,[`pr-coverage-diff.yml`](.github/workflows/pr-coverage-diff.yml) 在涉及规则更改的 PR 上发布覆盖率差异评论,而 [`deploy.yml`](.github/workflows/deploy.yml) 是一个手动的 `workflow_dispatch` 部署操作,通过 `production` 环境进行人工审批。部署作业在推送之前会再次运行 lint 和 test —— 仅仅显示合并成功并不能替代在部署时针对 `main` 分支的确切状态重新进行验证。 ## 快速入门 ``` git clone https://github.com/JacobRHess/sigma-pipeline cd sigma-pipeline pip install -e .[dev] sigma lint rules/ sigma test rules/ --fixtures tests/fixtures sigma deploy rules/ --dry-run # prints the deploy plan, makes no changes ``` ## 仓库结构 ``` sigma-pipeline/ ├── src/sigma_pipeline/ │ ├── cli.py argparse entrypoint, registers subcommands │ ├── lint.py rule-file linter (+ optional pySigma backend) │ ├── pysigma_backend.py pySigma validator wrapper, used by `lint --strict` │ ├── test.py fixture-driven tester │ ├── diff.py rule-set / coverage diff │ ├── stats.py rule-corpus summary (severity / tactic / logsource) │ ├── coverage.py ATT&CK coverage reporter │ └── deploy.py Splunk REST-API deploy ├── rules/ .yml Sigma rules (the detection content) ├── tests/fixtures/ │ └──
标签:AMSI绕过, Detection-as-Code, fixture测试, PB级数据处理, pySigma, Python, REST API, SecOps, Sigma规则, URL发现, YAML, 云安全架构, 云计算, 单元测试, 回归测试, 威胁检测, 安全基线, 安全工程, 安全库, 安全检测, 安全运维, 教学环境, 无后门, 检测即代码, 特权提升, 目标导入, 自动化部署, 覆盖率, 规则引擎, 逆向工具