🚨 Incident Responder
Automated IR Playbook Engine
A SOAR-style CLI tool that executes YAML-defined response playbooks when security alerts fire — enrich IPs, block with iptables, log cases, and generate IR reports.
🔗 Pairs with LogSentinel — Detect → Respond → Report
## 📋 概述
Incident Responder 弥合了**检测**与**响应**之间的差距。当安全告警触发时(来自 LogSentinel 或任何 SIEM),Incident Responder 会将其与 YAML 定义的剧本进行匹配,并执行自动化响应动作 —— 通过 AbuseIPDB/VirusTotal 充实 IP 信息,使用 iptables 封锁它,发送基于文件的通知,并将所有内容记录到带有完整审计追踪的 SQLite 数据库中。
**为什么选择这个项目?** 自动化事件响应 (SOAR) 是 SOC 岗位中最抢手的技能之一。该项目展示了构建剧本驱动自动化、集成威胁情报 API、与系统防火墙交互以及维护事件案例管理的实用能力。
### 作品集矩阵
| 工具 | 角色 | 功能描述 |
|------|------|-------------|
| **LogSentinel** | 🔍 检测 | 解析日志,检测威胁,关联告警 |
| **Incident Responder** | 🚨 响应 | 充实 IP,封锁攻击者,通知,记录案例 |
## ✨ 功能特性
| 特性 | 描述 |
|---------|-------------|
| **YAML 剧本** | 使用简单的 YAML 定义响应工作流 —— 触发器、动作、参数 |
| **5 种动作类型** | `firewall_block`、`enrich_ip`、`notify`、`webhook`、`log_case` —— 可扩展架构 |
| **Webhook 通知** | Slack 和 Discord webhook,支持环境变量或按剧本进行 URL 覆盖,以及模板变量 |
| **IP 充实** | 查询 AbuseIPDB + VirusTotal API,自动进行 1 小时缓存 |
| **防火墙封锁** | iptables IP 封锁,带有 dry-run 模式(默认安全)+ `--execute` 标志 |
| **通配符触发器** | 在 `trigger_rule_ids` 中使用 `"*"` 匹配任何告警规则 —— 全局捕获剧本 |
| **模板变量** | `{{alert.source_ip}}`、`{{alert.rule_id}}` —— 动态消息/案例模板 |
| **LogSentinel 集成** | 原生读取 `{"alerts": [...]}` 报告格式 —— 将检测管道连接至响应 |
| **SQLite 数据库** | 持久化事件追踪,带有完整的动作审计追踪 |
| **HTML 报告** | 深色主题的事件报告,包含严重性徽章和动作时间线 |
| **JSON 导出** | 结构化的事件数据,用于 SIEM 集成和程序化使用 |
| **5 个 CLI 命令** | `run`、`list-playbooks`、`list-incidents`、`incident`、`stats` |
| **3 个内置剧本** | SSH 暴力破解封锁、端口扫描封锁、全高危通知 |
## 🚀 快速开始
### 安装
```
# 克隆 repository
git clone https://github.com/Yash-Patil-1/IncidentResponder.git
cd IncidentResponder
# 创建 virtual environment(推荐)
python3 -m venv .venv
source .venv/bin/activate
# 安装 Incident Responder
pip install -e .
```
### 基本用法
```
# 使用示例 alert 运行
incident-responder run Sample_alerts/ssh_brute_alert.json
# 列出可用的 playbooks
incident-responder list-playbooks
# 列出追踪的 incidents
incident-responder list-incidents
# 查看 incident 详情
incident-responder incident 1
```
### 与 LogSentinel 集成
```
# 生成 LogSentinel 报告
logsentinel --sample --format json
# 将 alerts 直接 pipe 到 Incident Responder
incident-responder run --from-logsentinel reports/logsentinel_report_*.json --verbose
```
### 执行模式(iptables 需要 sudo 权限)
```
# Dry-run(默认)— 显示将会发生的操作
incident-responder run Sample_alerts/ssh_brute_alert.json
# Execute 模式 — 实际封禁该 IP
incident-responder run Sample_alerts/ssh_brute_alert.json --execute
```
### 示例输出
```
$ incident-responder run Sample_alerts/ssh_brute_alert.json --verbose
[+] Alert: [High] SSH Brute Force Detected (DET-001)
[+] Source IP: 192.168.1.100
[+] Mode: DRY-RUN
[+] Matching playbooks: block_ssh_brute_force, notify_high_severity_alert
============================================================
Incident #1: SSH Brute Force Detected
============================================================
Playbook: block_ssh_brute_force
Status: open
Alert: [High] DET-001 - 192.168.1.100
============================================================
Step 1: [✓] enrich_ip
No enrichment providers configured (set ABUSEIPDB_API_KEY, VIRUSTOTAL_API_KEY)
Step 2: [✓] firewall_block
[DRY-RUN] Would block 192.168.1.100 via iptables chain INPUT (Blocked by IncidentResponder - SSH brute force)
Step 3: [✓] notify
Notification written to /home/user/.incident_responder/notifications.log
Step 4: [✓] log_case
Case logged: SSH brute force from 192.168.1.100 - blocked via iptables
Step 5: [✓] enrich_ip
No enrichment providers configured (set ABUSEIPDB_API_KEY, VIRUSTOTAL_API_KEY)
Step 6: [✓] notify
Notification written to /home/user/.incident_responder/notifications.log
Step 7: [✓] log_case
Case logged: High severity alert DET-001 from 192.168.1.100 - investigation needed
[+] HTML report: reports/ir_incident_1_20260523_113948.html
```
## 📖 剧本格式
剧本是存储在 `config/playbooks/` 中的 YAML 文件。每个剧本定义了触发条件和一系列自动化动作。
```
name: block_ssh_brute_force
description: Block IP address detected performing SSH brute force attacks
trigger_rule_ids:
- DET-001
- SSH_BRUTE_FORCE
min_severity: medium
actions:
- type: enrich_ip
params:
providers: [abuseipdb, virustotal]
- type: firewall_block
params:
chain: INPUT
comment: "Blocked by IncidentResponder - SSH brute force"
- type: notify
params:
message: "Blocked {{alert.source_ip}} for SSH brute force ({{alert.count}} attempts)"
- type: log_case
params:
summary: "SSH brute force from {{alert.source_ip}} - blocked via iptables"
```
### 触发规则
| 字段 | 描述 | 示例 |
|-------|-------------|---------|
| `trigger_rule_ids` | 激活此剧本的告警规则 ID | `["DET-001", "SSH_BRUTE_FORCE"]` |
| `min_severity` | 所需的最低告警严重性 | `low`, `medium`, `high`, `critical` |
| 通配符 `"*"` | 匹配任何规则 ID | `["*"]` —— 与 `min_severity: high` 配合使用以实现全局捕获 |
### 动作类型
| 动作 | 描述 | 关键参数 |
|--------|-------------|------------|
| `firewall_block` | 通过 iptables 封锁 IP(默认为 dry-run) | `ip`, `chain`, `comment` |
| `webhook` | 通过 webhook 发送 Slack / Discord 通知 | `type` (slack/discord), `message`, `url` (可选覆盖) |
| `enrich_ip` | 查询 AbuseIPDB + VirusTotal 获取 IP 信誉 | `ip`, `providers` |
| `notify` | 将结构化通知写入 JSONL 日志文件 | `message`, `channel` |
| `log_case` | 在 SQLite 数据库中记录案例摘要 | `summary` |
### 模板变量
所有动作参数均支持 `{{alert.field}}` 替换:
| 变量 | 来源 | 示例 |
|----------|--------|---------|
| `{{alert.rule_id}}` | 告警规则 ID | `DET-001` |
| `{{alert.title}}` | 告警标题 | `SSH Brute Force Detected` |
| `{{alert.severity}}` | 严重性级别 | `High` |
| `{{alert.source_ip}}` | 攻击者 IP | `192.168.1.100` |
| `{{alert.count}}` | 事件计数 | `15` |
| `{{alert.mitre_technique}}` | MITRE ATT&CK ID | `T1110 - Brute Force` |
## 🛠️ CLI 参考
```
usage: incident-responder [-h] [--version] {run,list-playbooks,list-incidents,incident,stats} ...
```
### 命令
#### `run` —— 针对告警执行剧本
```
incident-responder run [alert_file] [options]
Positional Arguments:
alert_file Path to alert JSON file (optional — interactive mode if omitted)
Options:
--from-logsentinel PATH Load alert from LogSentinel report JSON
--execute Actually execute actions (default: dry-run)
--verbose, -v Show detailed progress
--output-dir, -o DIR Report output directory (default: ./reports)
--format, -f {html,json} Report format (default: html)
--playbooks-dir PATH Path to custom playbooks directory
```
#### `list-playbooks` —— 显示所有已加载的剧本
```
incident-responder list-playbooks [--playbooks-dir PATH]
```
#### `list-incidents` —— 显示追踪的事件
```
incident-responder list-incidents [--status {open,closed}]
```
#### `incident` —— 查看或管理事件
```
incident-responder incident
[close]
```
#### `stats` —— 显示数据库统计信息
```
incident-responder stats
```
### 用法示例
```
# 使用独立 alert JSON 运行
incident-responder run Sample_alerts/ssh_brute_alert.json
# 从 LogSentinel 报告运行
incident-responder run --from-logsentinel logsentinel_report.json -v
# Execute 模式(实际封禁该 IP)
sudo incident-responder run alert.json --execute
# 查看 incident 详情
incident-responder incident 1
# 调查结束后关闭 incident
incident-responder incident 1 close
# 生成 JSON 报告而不是 HTML
incident-responder run alert.json --format json
# 使用自定义 playbooks
incident-responder run alert.json --playbooks-dir ./my-playbooks
# 显示 database 统计信息
incident-responder stats
# 检查版本
incident-responder --version
```
## 📁 项目结构
```
IncidentResponder/
├── pyproject.toml # Package configuration (console_scripts entry)
├── requirements.txt # Python dependencies
├── README.md # This file
├── PRD.md # Product requirements document
│
├── src/
│ ├── __init__.py # Package init (version: 1.0.0)
│ ├── models.py # Alert, Playbook, ActionResult, Incident dataclasses
│ ├── engine.py # PlaybookEngine — loader, matcher, executor
│ ├── database.py # SQLite database (WAL mode, incidents + actions tables)
│ ├── main.py # CLI entry point (5 commands)
│ ├── reporter.py # IncidentReporter — HTML and JSON reports
│ ├── actions/
│ │ ├── __init__.py # ActionRegistry — maps types to handlers
│ │ ├── firewall.py # iptables block (dry-run / execute)
│ │ ├── enrich.py # AbuseIPDB + VirusTotal with 1-hour cache
│ │ ├── webhook.py # Slack & Discord webhook notifications
│ │ ├── notify.py # File-based JSONL notifications
│ │ └── log_case.py # Case logging to SQLite
│ ├── utils.py # Shared template rendering utility
│ └── templates/
│ └── report.html # Jinja2 HTML report template
│
├── config/
│ └── playbooks/
│ ├── block_ssh_brute.yaml # SSH brute force → enrich + block + notify
│ ├── block_port_scan.yaml # Port scan → enrich + block + notify
│ └── notify_high_alert.yaml # Catch-all high+ severity → enrich + notify
│
├── Sample_alerts/
│ ├── ssh_brute_alert.json # DET-001: SSH brute force (LogSentinel-compatible)
│ └── port_scan_alert.json # DET-005: Port scan (standalone format)
│
├── tests/
│ ├── test_engine.py # 13 tests — playbook matching, execution, persistence
│ ├── test_actions.py # 12 tests — firewall, notify, log_case, registry
│ └── test_database.py # 12 tests — CRUD, filtering, stats, edge cases
│
├── reports/ # Generated incident reports
└── venv/ # Virtual environment (local)
```
## 🔧 API & Webhook 配置
### 威胁情报 API(充实)
要启用 IP 充实,请设置以下环境变量:
```
# AbuseIPDB(免费版:1,000 次检查/天)
export ABUSEIPDB_API_KEY="your_key_here"
# VirusTotal(免费版:500 次请求/天)
export VIRUSTOTAL_API_KEY="your_key_here"
```
如果没有 API 密钥,充实步骤将被优雅跳过并显示明确的提示信息。
### Webhook URL(通知)
要启用 Slack 和 Discord 通知,请设置以下环境变量:
```
# Slack incoming webhook
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T00/B00/xxxxx"
# Discord webhook
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/123456/abcdef"
```
每个剧本也可以在其动作参数中指定自定义的 webhook URL(覆盖环境变量)。
如果没有这些变量,webhook 步骤将被优雅跳过并显示明确的提示信息。
## 🧪 运行测试
```
# 安装 dev dependencies
pip install -e ".[dev]"
# 运行所有测试
python -m pytest tests/ -v
# 运行 coverage
python -m pytest tests/ --cov=src --cov-report=term
```
**当前测试结果:56/56 通过**(模块覆盖率为 46% —— 依赖网络的代码和 CLI 代码不包含在单元测试中)
## 🔌 LogSentinel 集成
Incident Responder 旨在与 [LogSentinel](https://github.com/Yash-Patil-1/LogSentinel) 无缝配合使用:
```
# Step 1:使用 LogSentinel 进行检测
logsentinel sample_logs/auth.log --format json --verbose
# Step 2:使用 Incident Responder 进行响应
incident-responder run --from-logsentinel reports/logsentinel_report_*.json --verbose
```
`--from-logsentinel` 标志会自动解析 LogSentinel 的 `{"alerts": [...]}` 报告格式。
## 🗺️ 架构
```
┌──────────────┐
│ Alert JSON │
│ (standalone │
│ or LS fmt) │
└──────┬───────┘
│
┌──────▼───────┐
│ Playbook │
│ Engine │
│ │
│ 1. Load │
│ playbooks │
│ 2. Match │
│ alert │
│ 3. Create │
│ incident │
└──────┬───────┘
│
┌────────────┼────────────┬───────────┐
│ │ │ │
┌──────▼───┐ ┌─────▼────┐ ┌─────▼────┐ ┌────▼──────┐
│ Firewall │ │ Enrich │ │ Webhook │ │ Notify │
│ Block │ │ IP (VT + │ │ (Slack / │ │ (File │
│ (iptables│ │ AbuseDB) │ │ Discord) │ │ JSONL) │
└──────┬───┘ └─────┬────┘ └─────┬────┘ └─────┬─────┘
│ │ │ │
└────────────┼────────────┼────────────┘
│
┌──────▼───────┐
│ SQLite DB │
│ (Incidents │
│ + Actions) │
└──────┬───────┘
│
┌──────▼───────┐
│ Reporter │
│ HTML / JSON │
└──────────────┘
```
### 数据流
1. **摄取 (Ingest)** —— 告警通过 JSON 文件、LogSentinel 报告或手动输入到达
2. **匹配 (Match)** —— PlaybookEngine 将告警与已加载的剧本进行比较(`trigger_rule_ids` + `min_severity`)
3. **事件 (Incident)** —— 在 SQLite 数据库中创建新的事件记录
4. **执行 (Execute)** —— 每个匹配剧本的动作按顺序运行
5. **记录 (Log)** —— 每个动作结果都记录在数据库中,并带有完整的审计追踪
6. **报告 (Report)** —— 生成 HTML 或 JSON 报告,以供人工审查或 SIEM 摄取
## 📝 许可证
本项目采用 MIT 许可证授权。
## 👨💻 作者
**Yash Patil** —— 网络安全分析师 | SOC 运营与事件响应
- 📧 yashpatil7714@gmail.com
- 🔗 [LinkedIn](https://www.linkedin.com/in/yash-patil-997357330)
- 🐙 [GitHub](https://github.com/Yash-Patil-1)
使用 Python、PyYAML、SQLite 构建,并对自动化防御深表赞赏。
属于 检测 → 响应 → 搜寻 SOC 工具集的一部分。