abuis78/skill_Claude_generate_SOAR_playbook
GitHub: abuis78/skill_Claude_generate_SOAR_playbook
一个将自然语言描述转化为 Splunk SOAR 8.5 可运行且 VPE 可编辑 playbook 的 Claude Code Skill,通过逆向工程真实导出 schema 并结合 MCP 实时自测实现端到端闭环生成。
Stars: 0 | Forks: 0
# skill_Claude_generate_SOAR_playbook
一个 **Claude Code skill** (`soar-playbook-builder`),它可以将自然语言描述转化为
**Splunk SOAR On-Prem 8.5** playbook —— 它不仅能**运行**,而且可以在 **Visual
Playbook Editor (VPE)** 中保持**可编辑** —— 然后通过 SOAR MCP server **导入并对其进行实时自测**。
本仓库中的每一个 schema 都是**通过对真实的 8.5 版本导出文件进行逆向工程获得的**,并且**已通过真实的
REST import 验证** —— 没有任何猜测成分(参见 [来之不易的经验教训](#hard-won-lessons))。
## 目录
- [存在的原因](#why-this-exists)
- [核心原则:一个计划 → 两个生成器](#core-principle-one-plan--two-emitters)
- [架构](#architecture)
- [支持的 block 类型](#supported-block-types)
- [工作流(阶段 0–4 + 自测)](#the-workflow)
- [仓库结构](#repository-layout)
- [快速开始](#quick-start)
- [声明式计划 schema](#the-declarative-plan-schema)
- [测试](#testing)
- [已验证的端到端实现](#proven-end-to-end)
- [来之不易的经验教训](#hard-won-lessons)
- [依赖项(MCP server)](#dependencies-the-mcp-server)
- [状态与未来工作](#status--future-work)
## 存在的原因
手动编写 SOAR playbook 非常缓慢,而天真地生成它们往往会失败:一个 VPE 能够编辑的 SOAR playbook **不仅仅**是 Python 代码 —— 它是一个可视化的 **`coa.data`** 图,并且这两者必须保持一致。这个
skill 会一致地生成这两者,通过**实时发现**将每个特定于 connector 的值落地(没有幻觉产生的 app 或 datapath),并通过导入和运行最终结果来形成闭环。
## 核心原则:一个计划 → 两个生成器
一个 SOAR playbook 导出文件 (`.tgz`) 包含两个必须保持一致的部分:
- **`coa.data`** —— VPE 渲染的可视化图:`nodes` (字典) + `edges` (列表)。(顶层的
`blockly` 字段只是一个布尔标志;图结构**并不**在那里。) 参见
[`references/coa-structure.md`](references/coa-structure.md)。
- **`.py`** —— 可执行的真相:每个 block 都是一个 `@phantom.playbook_block()` 函数,
边即为 `callback=` 或直接调用。参见 [`references/py-structure.md`](references/py-structure.md)。
该 skill 构建**一个**抽象的 `playbook_plan.Plan` 并在其上运行**两个生成器**,因此
可运行的逻辑和 VPE 渲染在**构建上**就是一致的 —— 绝不从两个独立的来源编写,
也绝不是凭空想象手写的(coa 的元数据继承自真实的**黄金模板**)。
## 架构
```
natural-language request
│ (Claude, guided by SKILL.md + references/plan-schema.md)
▼
declarative plan (JSON)
│ playbook_plan.plan_from_dict() ← validates structure, lists every problem at once
▼
playbook_plan.Plan
├───────────────────────────────┬───────────────────────────────┐
▼ ▼
coa_assembly.build_coa_from_plan emit_python.emit
→ coa.data (visual graph) → .py (executable preview)
└───────────────┬───────────────┘
▼
build_playbook.build() → .json + .py
▼
pack_playbook.pack() → base64(gzip TAR) ← SOAR /rest/import_playbook format
▼
import_playbook (MCP, scm=) → a playbook that renders in the VPE
▼
self-test: create_container → create_artifact → run_playbook → get_playbook_run → assert effect
```
## 支持的 block 类型
所有类型都基于真实的导出文件,并且**已通过实时 REST import 验证**(括号内为 playbook id):
| Block | 作用 | 备注 |
|---|---|---|
| `start` / `end` | 入口 / 出口 | `on_start` / `on_finish`,无 functionId |
| `action` | 运行 connector 操作 | 通过 `phantom.collect2` 获取 datapath 参数;受 asset 作用域限制 |
| `decision` | 根据条件分支 | if/elif/else;通过 edge `branch` 扇出(基于 1 的键) |
| `format` | 人类可读的文本 | `{0}..{n}` 模板 + datapath `format_params` |
| `utility_note` | 原生 "add note" | 写入一个 container note |
| `set_severity` (549/554) | 原生 "set severity" | `choices:"notableSeverity"` (一个 **字符串**),`refreshNotableData` |
| `filter` (550) | 仅转发匹配的 artifacts | `phantom.condition`;基于 0 的条件键 |
| `playbook` (551) | 调用子 playbook | `playbookName/Repo/Type/synchronous/inputs` |
| `prompt` (553) | 人工干预审批 | `phantom.prompt2`;**线性** → 下游的 `decision` 读取 `…responses.0` |
## 工作流
由 Claude 遵循 [`SKILL.md`](SKILL.md) 执行:
- **阶段 0 — 学习 (LEARN)**:一个黄金模板 (`samples/`) 提供真实的 `coa` 封装
(version/schema/python_version),并为 node/`.py` schema 提供基础。
- **阶段 1 — 发现 (DISCOVERY)** *(反幻觉)*:`list_apps` + `list_assets` + `get_action_schema`
解析真实的 app/asset 和确切的输出 datapath(例如,恶意计数路径)。如果缺少必需的
connector,则停止 —— 不要替换为其他供应商。
- **阶段 2 — 计划 (PLAN)**:将意图转化为一个声明式计划 JSON(参见
[计划 schema](#the-declarative-plan-schema));`plan_from_dict()` 会对它进行验证。
- **阶段 3 — 生成 (EMIT)**:`build_playbook.build()` 运行两个生成器并打包存档文件。
- **阶段 4 — 验证与导入 (VERIFY & IMPORT)**:先在本地运行 `coa_assembly.validate()` + `compile()`,然后执行
`import_playbook(scm=)`。使用 `get_playbook_coa_summary` 进行确认
(`passed_validation=True`,预期的 node/edge 数量)。
- **自测**:`create_container(label="events")` → `create_artifact` → `run_playbook` →
`get_playbook_run` (轮询直到 `success`) → 断言效果(例如 `get_case` 的 severity,或是一个 note)。
## 仓库结构
| 路径 | 用途 |
|---|---|
| [`SKILL.md`](SKILL.md) | Skill 定义 + 完整的阶段 0–4 / 自测工作流 |
| `scripts/playbook_plan.py` | `Plan`/`Block` 模型 + `plan_from_dict()` (声明式 → 已验证的 Plan) |
| `scripts/coa_assembly.py` | `build_coa_from_plan` + 基于类型的 node 构建器 (基于真实导出) |
| `scripts/emit_python.py` | Plan → 可执行的 `.py` 预览 |
| `scripts/build_playbook.py` | Plan → `{.py, .json}` (+ 打包) |
| `scripts/pack_playbook.py` | 确定性 `base64(gzip TAR)` 编解码器 (SOAR import 格式) |
| `scripts/test_*.py` | 离线测试套件 (47 个测试,不需要实时 SOAR) |
| `references/coa-structure.md` | 已验证的 `coa.data` node/edge schema |
| `references/py-structure.md` | 已验证的 `.py` block/function 模式 |
| `references/plan-schema.md` | 声明式计划 schema + 实战示例 |
| `samples/*.tgz` | 黄金模板导出 (结构真值)。`golden_full` 已脱敏 |
| `docs/SOAR-MCP-Playbook-Tools-Instruction.md` | 该 skill 调用的 MCP-server 工具规范 |
| `examples/` | 已生成的 playbook 存档 |
| `SKILL-EXTENSION-NEEDS.md` | 哪些 MCP-server 能力解锁哪些 skill 功能 |
## 快速开始
**作为 Claude Code skill 使用** —— 连接 SOAR MCP server 后,只需询问:
Claude 会运行整个工作流(发现 → 生成 → 导入 → 运行 → 断言)并报告结果。
**直接驱动生成器**(离线,无需 SOAR):
```
import sys; sys.path.insert(0, "scripts")
from playbook_plan import plan_from_dict
from build_playbook import build
spec = { ... } # see references/plan-schema.md
plan = plan_from_dict(spec) # validates; raises with every problem listed
res = build(plan, "samples", "out", pack_archive=True)
print(res["archive_b64"]) # base64(gzip TAR) → feed to import_playbook(scm=)
```
## 声明式计划 schema
完整参考及示例:[`references/plan-schema.md`](references/plan-schema.md)。基本结构如下:
```
{
"name": "URL_Reputation_SetSeverity",
"playbook_type": "automation",
"blocks": [
{"key": "on_start", "type": "start"},
{"key": "url_reputation_1", "type": "action", "action": "url reputation",
"connector": "VirusTotal v3", "asset": "virustotal",
"parameters": {"url": "artifact:*.cef.requestURL"}, "datapath_params": true},
{"key": "decision_1", "type": "decision", "conditions": [
{"kind": "if", "comparisons": [
{"param": "url_reputation_1:action_result.data.*.attributes.last_analysis_stats.malicious",
"op": ">", "value": 0}]}]},
{"key": "set_severity_1", "type": "set_severity", "severity": "high"},
{"key": "on_finish", "type": "end"}
],
"edges": [
{"src": "on_start", "dst": "url_reputation_1"},
{"src": "url_reputation_1", "dst": "decision_1"},
{"src": "decision_1", "dst": "set_severity_1", "branch": 0},
{"src": "decision_1", "dst": "on_finish", "branch": "else"},
{"src": "set_severity_1", "dst": "on_finish"}
]
}
```
`plan_from_dict()` 会一次性报告**所有**结构问题(未知的 block 类型、悬空的 edge、
缺少必需字段、非线性的 `prompt`,等等),以便作者可以在一轮内完成自我修正。
## 测试
```
cd scripts
python3 -m unittest discover -p 'test_*.py' # 47 tests, all offline
```
测试会构建/验证 `coa.data`,对生成的 `.py` 执行 `compile()`,并对打包编解码器进行往返测试 —— 不需要
SOAR 实例。实时 REST-import 验证是单独针对一个 8.5 实例进行的。
## 已验证的端到端实现
在实时 SOAR **8.5.0.248** 上,通过单个自然语言 (NL) prompt 实现的**自动化运行**:
1. **发现**解析了 VirusTotal v3 (app 334)、asset `virustotal`,以及真实的恶意
datapath `…attributes.last_analysis_stats.malicious`。
2. **生成** → coa 有效,`.py` 编译通过。
3. **导入** → playbook **554** (`scm=4`),`passed_validation=True`。
4. **自测** → 测试 container (severity 为 `low`) + URL artifact → `run_playbook` → 运行
`success` (VirusTotal 返回 **Malicious: 10**) → `get_case` → **Severity = high** ✅。
每种 block 类型都单独进行了 REST-import 验证:set_severity、filter (550)、子 playbook
(551)、prompt (553)。
## 来之不易的经验教训
这些经验已融入代码和 `SKILL.md` 中,以免再次发生:
- **UI 导入很宽松;REST 导入很严格。** 一个 block schema 可能通过了 SOAR UI 导入,但
在 `/rest/import_playbook` 上仍然会报 `400` 错误。始终通过真实的 MCP 导入进行验证,而不是依赖 UI。(当初猜测的
`set_severity` schema 就是这样被发现的。)
- **`scm:"local"` 会解析为只读的 `community` repo → 导致 403。** 应传入一个明确的**可写**
repo id(例如 `4`;通过 `GET /rest/scm` 发现有效的 id)。
- **`set_severity`** 的 `choices` 字段是**字符串** `"notableSeverity"` (一个具名选项集合),而
不是列表,并且 `advanced` 和 utility 都带有 `refreshNotableData: true`。
- **functionName 规则:** `code` block 必须是 `code_`;类型化 block 必须是
`_` (后缀 == functionId);每个类型化 node 都需要一个 `functionId`。
- **Notes / set-severity 是原生的 `utility` block**,而不是代码块。
- **`prompt` 是线性的** —— 它从不进行分支;下游的 `decision` 读取
`:action_result.summary.responses.0`。
- **绝不要在 macOS 上使用 `tar czf`** —— 它会注入 AppleDouble `._*` 成员,破坏 SOAR 的 UTF-8 读取;
始终通过 `pack_playbook` (Python `tarfile`) 打包。
- **发现,而不是猜测:** 恶意的 datapath 因 connector 而异 (VirusTotal v3 使用
`…last_analysis_stats.malicious`,而不是 `…summary.malicious`) —— 通过 `get_action_schema` 解析它。
## 依赖项(MCP server)
发现/导入/自测使用扩展版的
[`abuis78/soar_mcp_server`](https://github.com/abuis78/soar_mcp_server) 中的工具:`list_apps`、`list_assets`、
`get_action_schema`、`export_playbook`、`import_playbook`、`create_container`,以及分析师工具
`create_artifact`、`run_playbook`、`get_playbook_run`、`get_case`。写工具是受限的
(默认禁用;`create_container` 还需要 `enable_test_harness`)。规范:
[`docs/SOAR-MCP-Playbook-Tools-Instruction.md`](docs/SOAR-MCP-Playbook-Tools-Instruction.md)。
## 状态与未来工作
- ✅ 所有 block 类型均已构建,完成了离线测试 (47 个测试),并进行了实时 REST 验证。
- ✅ 完整的自动化闭环已验证 (NL → 发现 → 构建 → 导入 → 运行 → 断言)。
- 未来:通过发现机制从名称解析子 playbook 的 `repo_id`;扩展调色板 (task/pin/api
实用程序);更丰富的 prompt 响应类型 (目前仅验证了 `yes/no`)。参见
[`SKILL-EXTENSION-NEEDS.md`](SKILL-EXTENSION-NEEDS.md)。
*使用 [Claude Codehttps://claude.com/claude-code) 构建。配套的 MCP server:
[abuis78/soar_mcp_server](https://github.com/abuis78/soar_mcp_server)。*
标签:AI辅助编程, Claude, CVE检测, SOAR, 安全运营, 扫描框架, 自动化剧本, 逆向工具