cgfixit/Veeam-HealthCheck-Simplifier
GitHub: cgfixit/Veeam-HealthCheck-Simplifier
该项目是一个自动化分析 Veeam 备份系统健康检查数据的工具,能够发现合规差距并生成安全的 PowerShell 修复脚本与工单数据。
Stars: 0 | Forks: 0
# Veeam Health Check Simplifier
**一个以安全为核心的 VBR pipeline,它接收来自 Veeam Backup & Replication (VBR) 服务器的 [Veeam Health Check](https://vee.am/vhc2) 导出数据,分析其中的合规差距,并生成安全、可审查的修复 artifact。**
## 什么是 Veeam Health Check?
[Veeam Health Check (VHC)](https://vee.am/vhc2) 是一个基于 PowerShell 的诊断脚本,可在 Windows 上针对 Veeam Backup & Replication 服务器运行。它会导出涵盖以下内容的 CSV 和 JSON 文件:
- **Jobs** — 备份作业配置(保留策略、加密、计划)
- **Sessions** — 近期作业运行结果(成功、失败、警告)
- **安全合规** — 最佳实践状态(MFA、RDP、加密、不可变性)
- **Repositories** — 备份存储目标及不可变性支持
- **恶意软件事件** — inline 扫描、YARA 规则和熵检测结果
本项目获取这些原始导出文件,并将其转化为可操作的修复指南 —— 无需人工审查电子表格。
### 支持的 VBR 版本
| VBR 版本 | Build | Windows Server | 状态 |
|---|---|---|---|
| v12.3.2 | 12.3.2.4643 | 2016, 2019, 2022, 2025 | 模拟 VHC fixture 覆盖 |
| v13 | 13.0.x fixture 目标 | 2019, 2022, 2025 | 模拟 VHC fixture 覆盖 |
## 工作原理
```
┌─────────────────────────────────┐
│ Windows Server with VBR │
│ Run https://vee.am/vhc2 │
│ → Exports CSV/JSON files │
└───────────────┬─────────────────┘
│
▼
┌─────────────────────────────────┐
│ vhc_simplifier.py │
│ │
│ 1. Load exports (CSV or JSON) │
│ 2. Analyze across 5 domains │
│ 3. Enrich with remediation cmds │
│ 4. Generate artifacts │
│ 5. (Optional) Push to SF/Slack │
└───────────────┬─────────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
remediation_ fixit.ps1 tickets.json
summary.md (safe -WhatIf) (ITSM-ready)
```
### 分析 Pipeline
1. **加载** — `_safe_load_csv()` / `_safe_load_json()` 支持 UTF-8 BOM 剥离、面向 Windows 的编码回退、损坏解码防护和空文件防护
2. **分析** — 故障隔离的 analyzers(`_run_analyzer()` wrapper 捕获每个 analyzer 的异常,绝不会中止运行):
- `analyze_jobs()` — 保留策略、加密、计划差距
- `analyze_sessions()` — 近期的失败和警告
- `analyze_security()` — 最佳实践合规状态
- `analyze_repositories()` — 不可变性支持差距
- `analyze_malware()` — 感染/可疑的扫描结果
3. **丰富** — `enrich_findings()` 将每个发现与带有 KB 文章链接的 PowerShell 修复命令进行模式匹配,并应用 `_ps_quote()` 注入防护
4. **写入** — `_write_artifact()` wrapper 隔离每个文件的 IO 错误:
- `remediation_summary.md` — 包含严重程度、PS 代码片段和 KB 链接的易读报告
- `fixit.ps1` — 可执行的修复脚本(所有 mutating verb 都包含 `-WhatIf`)
- `tickets.json` — 兼容 ITSM 的 payload(仅限高/中等程度的发现)
5. **集成**(可选) — 将发现作为 Task 推送到 Salesforce,或将摘要发布到 Slack
## 功能
- **多格式输入** — CSV(默认,来自 [vee.am/vhc2](https://vee.am/vhc2))或 JSON(VBR REST API 导出)
- **演示模式** — 使用内嵌的真实样本数据即时运行;无需输入文件
- **安全的 PowerShell 输出** — 所有 mutating 命令(`Set-`、`New-`、`Remove-` 等)默认包含 `-WhatIf`
- **防止 PS 注入** — 带有控制字符的对象名称会被拒绝,不会被插值
- **Salesforce 集成** — 为高/中等程度的发现在 Account 记录上创建 Task
- **Slack 通知** — 将严重程度摘要发送到传入的 webhook
- **优雅降级** — 缺少输入文件会被记录但绝不是致命的;部分运行会继续;单个 analyzer 失败会被记录并跳过,而不会中止运行
- **稳健的编码处理** — 容忍 UTF-8 BOM(通常来自 Windows PowerShell `Export-Csv`)、UTF-16 变体和 Windows 代码页回退,同时拒绝损坏的 NUL 解码文件
- **代码中无机密** — Salesforce 凭证仅从环境变量中解析
## 生成的 Artifact
| 文件 | 描述 |
|---|---|
| `remediation_summary.md` | 包含 PowerShell 代码片段和 KB 链接的易读发现 |
| `fixit.ps1` | 安全的预览修复脚本(所有 mutating 命令均带 `-WhatIf`) |
| `tickets.json` | 兼容 ITSM 的 JSON payload(仅限高/中等程度的发现) |
## 要求
- Python 3.12+(已在 3.12 和 3.13 上测试)
- `pandas`(核心依赖)
- `simple-salesforce` *(可选 — 仅用于 `--sf-account-id`)*
- `httpx` *(可选 — 如果缺失,Slack 回退将使用标准库 `urllib`)*
- `pytest`, `pytest-cov` *(仅限开发/测试)*
```
pip install -r requirements.txt
```
## 快速开始
```
# Demo 模式(无需文件 — 使用内置示例数据)
python vhc_simplifier.py --demo
# 从 VBR 服务器导出真实 CSV(首先在 Windows 上运行 vee.am/vhc2)
python vhc_simplifier.py --input-dir ./vhc-exports --output-dir ./results
# JSON / VBR REST API 导出
python vhc_simplifier.py --input-dir ./vhc-json --input-format json
# 带 Salesforce Task 创建
export SF_USERNAME=user@domain.com
export SF_PASSWORD=yourpassword
export SF_TOKEN=yoursecuritytoken
python vhc_simplifier.py --demo --sf-account-id 001XXXXXXXXXXXX
# 带 Slack 通知
python vhc_simplifier.py --input-dir ./vhc-exports \
--slack-webhook https://hooks.slack.com/services/T00/B00/xxx
# Quiet 模式(无 console 输出,仅生成 artifacts)
python vhc_simplifier.py --input-dir ./vhc-exports --quiet
# 跳过 artifact 写入(仅分析)
python vhc_simplifier.py --input-dir ./vhc-exports --no-artifacts
```
## 在 Docker 中运行
```
# 构建 image
docker build -t vhc-simplifier .
# 运行一次(Demo 模式,与 CI smoke test 相同)
docker run --rm vhc-simplifier --demo --quiet --no-artifacts
# 针对真实导出运行一次
docker run --rm \
-v $(pwd)/vhc-exports:/app/input:ro \
-v $(pwd)/output:/app/output \
vhc-simplifier --input-dir /app/input --output-dir /app/output
```
对于周期性运行,请设置 `CRON_SCHEDULE` 环境变量(标准的 5 字段 cron 语法),
容器将在 `busybox crond` 下保持在前台运行,并在每次计划触发时
使用您传递的任何参数重新调用 CLI:
```
docker run -d --name vhc-simplifier \
-e CRON_SCHEDULE="0 6 * * *" \
-v $(pwd)/vhc-exports:/app/input:ro \
-v $(pwd)/output:/app/output \
vhc-simplifier --input-dir /app/input --output-dir /app/output
```
容器始终以非 root 用户 `vhc` 的身份运行,包括 cron 进程 —— 镜像内部没有
root cron daemon。
## CLI 参考
| 标志 | 默认值 | 描述 |
|---|---|---|
| `--input-dir` | `.` | 包含 VHC 导出文件的目录 |
| `--output-dir` | `.` | 用于存放生成 artifact 的目录 |
| `--input-format` | `csv` | 输入格式:`csv` 或 `json` |
| `--demo` | off | 使用内嵌的样本数据(无需文件) |
| `--no-artifacts` | off | 跳过写入 `.md`/`.ps1`/`.json` 文件 |
| `--quiet` | off | 禁止控制台报告输出 |
| `--verbose` | off | 启用详细/调试日志记录 |
| `--sf-account-id` | — | 用于创建 Task 的 Salesforce Account ID |
| `--sf-username` | — | SF 用户名(推荐使用 `SF_USERNAME` 环境变量) |
| `--sf-password` | — | SF 密码(推荐使用 `SF_PASSWORD` 环境变量) |
| `--sf-token` | — | SF 安全令牌(推荐使用 `SF_TOKEN` 环境变量) |
| `--slack-webhook` | — | Slack 传入 webhook URL |
## 预期输入文件
这些文件是通过在安装了 VBR 的 Windows Server 上运行 [Veeam Health Check 脚本](https://vee.am/vhc2) 生成的:
| 数据 | CSV 文件名 | JSON 文件名 |
|---|---|---|
| Jobs | `localhost_Jobs.csv` | `localhost_Jobs.json` |
| Sessions | `VeeamSessionReport.csv` | `VeeamSessionReport.json` |
| Security | `localhost_SecurityCompliance.csv` | `localhost_SecurityCompliance.json` |
| Repositories | `localhost_Repositories.csv` | `localhost_Repositories.json` |
| Malware | `localhostmalware_events.csv` | `localhostmalware_events.json` |
所有文件均为可选 —— 缺失的文件将被记录并跳过,不会导致中止。
## 集成
### Salesforce
为高和中等严重程度的发现在 Salesforce Account 记录上创建 Task。需要 `simple-salesforce` 并通过环境变量提供凭证:
```
export SF_USERNAME=user@domain.com
export SF_PASSWORD=yourpassword
export SF_TOKEN=yoursecuritytoken
python vhc_simplifier.py --demo --sf-account-id 001XXXXXXXXXXXX
```
### Slack
将严重程度摘要发送到 Slack 传入 webhook。会验证 webhook URL 是否使用 HTTPS 并指向 `hooks.slack.com` 或 `hooks.slack-gov.com`:
```
python vhc_simplifier.py --demo \
--slack-webhook https://hooks.slack.com/services/T00/B00/xxx
```
如果可用则使用 `httpx`,否则回退到标准库 `urllib`。
## Docker Compose
提供了一个 `docker-compose.yml`,用于在容器中构建和运行 CLI,而无需在本地安装 Python 或依赖项。
```
mkdir -p vhc-exports output
# 将您的 VHC 导出文件复制到 ./vhc-exports
docker compose up --build
```
这会将 `./vhc-exports` 以只读方式挂载到 `/app/input`,并将 `./output` 以读写方式挂载到 `/app/output`,然后运行 `vhc_simplifier.py --input-dir /app/input --output-dir /app/output --quiet`。如需使用其他标志(例如 Salesforce 或 Slack 集成),请覆盖默认命令:
```
docker compose run --rm vhc-simplifier \
--input-dir /app/input --output-dir /app/output \
--sf-account-id 001XXXXXXXXXXXX \
--slack-webhook https://hooks.slack.com/services/T00/B00/xxx
```
Salesforce 凭证(`SF_USERNAME`、`SF_PASSWORD`、`SF_TOKEN`)从宿主环境或 `.env` 文件中传递 —— 切勿将它们固化到镜像中。`./vhc-exports` 和 `./output` 都不应该被提交;两者均已包含在 `.gitignore` 中。
## 测试
测试套件涵盖了 6 个文件中的 219 个测试,代码覆盖率达到 90%+:
| 测试文件 | 测试 | 覆盖范围 |
|---|---|---|
| `test_vhc_simplifier.py` | 核心 helper、analyzer、loader、丰富功能、artifact writer、集成运行 |
| `test_coverage_gaps.py` | 边缘情况:NaN 处理、空 DataFrame、编码、类型强制转换 |
| `test_vbr_server_simulation.py` | VBR v12.3.2 和 v13 mock server 模拟及真实的导出数据 |
| `test_windows_server_env.py` | Windows 路径、编码(BOM、UTF-16)、PowerShell 注入、服务器版本矩阵 |
| `test_mock_veeam_environment.py` | 带有文件级故障注入的完整 mock VBR 环境 |
| `conftest.py` | 包含真实 VBR v12 和 v13 CSV/JSON 导出数据的共享 fixture |
```
# 运行所有测试
python -m pytest tests/ -v
# 运行并生成覆盖率报告
python -m pytest tests/ -v --cov=vhc_simplifier --cov-report=term-missing
# 仅运行 VBR 服务器模拟测试
python -m pytest tests/test_vbr_server_simulation.py -v
```
## CI/CD Workflow
六个 GitHub Actions workflow 会在每次向 `main` 分支进行 push 和 pull request 时运行:
| Workflow | 文件 | 用途 |
|---|---|---|
| **CI** | `ci.yml` | Lint + 测试矩阵(在 ubuntu + windows 上的 Python 3.12/3.13),80% 覆盖率阈值 |
| **Ruff** | `ruff.yml` | Python lint 和格式检查 |
| **Gitleaks** | `gitleaks.yml` | 机密扫描(push、PR、每周) |
| **DevSkim** | `devskim.yml` | 微软安全反模式检测(push、PR、每周) |
| **CodeQL** | `codeql.yml` | GitHub 静态分析(push、PR、每周) |
| **Dependency Review** | `dependency-review.yml` | PR 上的供应链漏洞检查 |
| **Trivy** | `trivy.yml` | 容器/依赖项漏洞扫描(文件系统 + Docker 镜像),SARIF → GitHub 代码扫描(push、PR、每周) |
## 部署
提供两种部署选项:
- **Docker** — 通过包含的 `Dockerfile` 构建并运行。
- **宿主机原生 (systemd)** — 面向不需要 Docker 的运维人员,`deploy/`
提供了一个 `oneshot` systemd 服务、一个每日的 calendar timer 以及
一个用于日志输出的 `logrotate` 配置。有关安装说明,请参阅 [`deploy/README.md`](deploy/README.md)。
## 架构
```
Input (CSV / JSON / --demo)
|
v
_safe_load_*() <- adapter layer (BOM stripping, encoding fallback)
|
v
_run_analyzer() <- fault isolation wrapper (records errors, never aborts)
|
v
analyze_*() <- pure functions, domain-scoped (jobs, sessions, security, repos, malware)
|
v
enrich_findings() <- pattern-matched remediation + PS injection guard (_ps_quote)
|
|---> _write_artifact() <- IO error isolation wrapper
| |---> write_markdown()
| |---> write_powershell_script()
| `---> write_ticket_payload()
|---> _push_to_salesforce() (optional)
`---> _post_slack_summary() (optional)
```
## 退出代码
| 代码 | 含义 |
|---|---|
| `0` | 成功 |
| `1` | 未处理的异常 |
| `2` | 发生处理错误(检查 stderr / 日志) |
## 安全说明
- **切勿提交凭证。** 使用环境变量(`SF_USERNAME`、`SF_PASSWORD`、`SF_TOKEN`)或 secrets manager。
- **在移除 `-WhatIf` 之前请审查其输出。** 首先在非生产环境中验证每个命令。
- **防止注入。** 带有 ASCII 控制字符(`0x00-0x1F`、`0x7F`)的对象名称将被完全拒绝,不会进入 PS 命令生成阶段。
- **Slack webhook 验证。** 仅接受 `https://hooks.slack.com/...` 和 `https://hooks.slack-gov.com/...` URL。
- **服务账号与 MFA。** 此工具使用的自动化账号(Salesforce、Slack 以及任何脚本化的 VBR REST API 访问)无法完成交互式 MFA 挑战 —— 有关安全界定非交互式凭证的指南,请参阅 [SECURITY.md](SECURITY.md#service-account--mfa-considerations)。
请参阅 [LICENSE.md](LICENSE.md)、[CONTRIBUTORS.md](CONTRIBUTORS.md) 和 [SECURITY.md](
标签:AI合规, IPv6, PowerShell, Veeam, 数据备份, 请求拦截, 运维, 逆向工具