semayellow/vuln-commander
GitHub: semayellow/vuln-commander
一个开源的 DevSecOps 应用安全平台,通过统一聚合多种扫描器的结果来实现集中式的跨仓库漏洞管理与数据分析。
Stars: 0 | Forks: 0
# Vuln Commander
Vuln Commander 是一个开源的应用程序安全平台。它将来自 DevSecOps 扫描器和服务连接器的扫描结果聚合到一个统一的数据库中,对外提供 REST API,提供用于漏洞管理的 Web UI,并内置了用于数据分析的 Grafana 仪表板。
## 目录
1. [平台概述](#1-platform-overview)
2. [Web UI](#2-web-ui)
3. [Grafana 仪表板](#3-grafana-dashboards)
4. [技术栈](#4-technology-stack)
5. [架构与数据模型](#5-architecture-and-data-model)
6. [SDK](#6-sdk)
7. [全新安装与运行](#7-clean-install-and-run)
## 1. 平台概述
平台提供了跨代码仓库的集中式漏洞跟踪:
- **GitHub 服务连接器** — 注册项目(仓库)、默认分支元数据以及最新的提交。
- **DevSecOps 连接器** — 定期克隆项目、运行扫描器并通过 API 同步扫描结果:
- **GSS** (密钥) — [Nosey Parker](https://github.com/praetorian-inc/noseyparker)
- **IAC** — [KICS](https://github.com/Checkmarx/kics)
- **SCA 漏洞** / **SCA 许可证** — [Trivy](https://github.com/aquasecurity/trivy)
- **API** — 存储项目、漏洞和扫描历史记录;为用户和连接器提供 JWT 身份验证;基于角色的访问控制。
- **Web UI** — 深色主题的浏览器界面(Lunaris 设计),用于仪表板、项目注册表、连接器监控和漏洞分类筛查。
- **仪表板** — Grafana 读取聚合的 PostgreSQL 视图(总体统计和按扫描器细分的统计)。
### 核心功能
| 领域 | 描述 |
|------|-------------|
| 项目 | 仓库注册、团队 (`ti` / `sandbox`)、状态 (`active` / `archived`) |
| 漏洞 | 批量创建/更新/关闭;生命周期:`new` → `closed` / `reopened` |
| 连接器 | 具有 `service` 或 `devsecops` 权限范围的账户;按项目划分的扫描历史记录 |
| 用户 | 角色 `user` / `admin`;访问 + 刷新 JWT |
| 可观测性 | Graylog (GELF UDP) 中的连接器日志,Grafana 中的指标 |
## 2. Web UI
平台在 `/api/v1/` 路径下提供了一个服务端渲染的 Web 界面。所有页面共享一个通用外壳:侧边栏导航、带有注销功能的用户资料,以及深色的 Lunaris 主题(JetBrains Mono + Inter,橙色点缀)。
身份验证使用 **HTTP-only cookie**(`vc_access_token`, `vc_refresh_token`)。登录后,当您浏览时,会话会自动续期。Web 会话有效期:**access token 15 分钟**,**refresh token 30 分钟**。连接器通过 Bearer JWT 访问 API 的机制保持不变(5 / 30 分钟)。
### 登录
打开 `/api/v1/auth/` 并使用平台用户的电子邮件和密码登录。登录后,您将被重定向到主页(或您最初请求的页面)。

### 主页
**URL:** `/api/v1/`
包含平台实时指标(未解决的漏洞、活跃项目、连接器、今日扫描次数)的仪表板,并提供指向 pgAdmin、Grafana 和 Graylog 的快捷链接。

### 项目
**URL:** `/api/v1/projects`
所有受跟踪仓库的注册表。该表格支持搜索、分页和可配置的每页条数。每一行显示团队、状态、最后提交时间戳、未解决漏洞数量,以及用于打开该项目漏洞管理的 **Open** 操作。

### 连接器
**URL:** `/api/v1/connectors`
监控扫描器和服务集成:连接器名称、范围 (`service` / `devsecops`)、运行时状态 (`Running`, `Waiting`, `Error`, `Inactive`) 以及最后运行时间。表格每分钟自动刷新一次;页脚显示 **Last updated** 以及获取最新数据的时间戳。

### 漏洞管理
**URL:** `/api/v1/vuln/manage/{project_name}`
按项目划分的筛查视图。支持按状态和严重程度进行过滤,按创建/关闭日期进行排序,选择多行进行批量操作,以及打开单个扫描结果。分页和每页条数与整个 UI 中使用的共享数据表格控件相匹配。

### 漏洞详情
**URL:** `/api/v1/vuln/details/{vuln_id}`
单个扫描结果的视图,包含严重程度、状态、文件位置、代码片段、元数据(提交、规则、分支),以及在同一项目中的相关漏洞之间进行导航。操作:标记为误报、创建任务(开发中)。

### UI 路由摘要
| 页面 | URL |
|------|-----|
| 登录 | `/api/v1/auth/` |
| 主页 | `/api/v1/` |
| 项目 | `/api/v1/projects` |
| 连接器 | `/api/v1/connectors` |
| 漏洞(项目) | `/api/v1/vuln/manage/{project_name}` |
| 漏洞详情 | `/api/v1/vuln/details/{vuln_id}` |
## 3. Grafana 仪表板
Grafana 在聚合的 PostgreSQL 视图之上提供分析功能。**vuln-commander dashboard** 会根据 `grafana/main_dashboard.json` 自动配置,并从 `Vuln Commander Postgres` 数据源读取数据。
**URL:** http://localhost:3000(凭据:来自 `.env` 的 `GF_SECURITY_ADMIN_USER` / `GF_SECURITY_ADMIN_PASSWORD`)
您也可以从 **主页** 的快捷操作中打开 Grafana(`/api/v1/` → **Open Grafana**)。
### 过滤器
仪表板公开了模板变量,用于在整个报表中对数据进行切片:
| 变量 | 描述 |
|----------|-------------|
| `project_name` | 按仓库 / 项目过滤 |
| `control_type` | 按扫描器过滤 (`gss`, `iac`, `sca_vuln`, `sca_license`) |
| `severity` | 按发现结果严重程度过滤 |
| `team` | 按项目团队过滤 (`ti`, `sandbox`) |
### 主仪表板
按项目划分的摘要表:按严重程度统计的漏洞数量(`info` → `critical`)、最后提交时间,以及指向项目仓库和漏洞管理 UI 的链接。

### 常规统计
高级细分:按严重程度、状态、扫描器类型统计的漏洞,以及结合了扫描器和严重程度的条形图。使用此部分可以查看整个组合的趋势并确定筛查优先级。

### IAC 和 SCA 统计信息
特定于扫描器的分析:
- **IAC** — 按云/平台(Terraform, Kubernetes, CloudFormation 等)和 CWE 统计的扫描结果。
- **SCA** — 跨扫描项目出现漏洞次数最多的热门软件包。

### 按扫描器划分的漏洞详情
用于查看单个扫描结果的穿透式下钻表格:
| 面板 | 内容 |
|-------|---------|
| GSS 漏洞详情 | 密钥扫描结果:严重程度、状态、文件路径 |
| IAC 漏洞详情 | 配置错误规则和 CWE 引用 |
| SCA 许可证详情 | 许可证标识符及 SPDX 链接 |
| SCA 漏洞详情 | CVE 标题和描述 |

### 数据源
面板查询在 API 迁移期间创建的 SQL 视图 (`api/migrations/views_generation_spec`):
- `vc_view_general_vulnerabilities_statistic` — 项目摘要
- `vc_view_project_vulnerabilities_statistic` — 按项目划分的详情
- `vc_view_gss_vulnerabilities_statistic`, `vc_view_iac_*`, `vc_view_sca_*` — 按扫描器划分的细分
## 4. 技术栈
### 后端与数据
| 组件 | 技术 |
|-----------|------------|
| API | Python 3.12, FastAPI, Uvicorn, Gunicorn |
| ORM / 迁移 | SQLAlchemy 2, Alembic, asyncpg |
| Schema 校验 | Pydantic v2 |
| 数据库 | PostgreSQL (Bitnami image) |
| 身份验证 | JWT (PyJWT), bcrypt |
| UI 模板 | Jinja2, Lunaris CSS (`api/src/static/css/lunaris.css`) |
### 连接器与 SDK
| 组件 | 技术 |
|-----------|------------|
| HTTP 客户端 | aiohttp |
| 调度器 | cron-converter (`Scheduler`) |
| Git 操作 | GitPython |
| 日志记录 | loguru, pygelf → Graylog |
| 依赖管理 | [uv](https://github.com/astral-sh/uv) |
| 共享 Schema | `shared/` 包 (`vuln-commander-shared`) |
### 基础设施 (Docker Compose)
| 服务 | 用途 | 主机端口 |
|---------|---------|-----------|
| `api` | REST API + 静态资源 | 8000 |
| `db` | PostgreSQL | 5432 |
| `db-ui` | pgAdmin | 8080 |
| `github`, `gss`, `iac`, `sca-license`, `sca-vuln` | 连接器 | — |
| `graylog` + `graylog-datanode` + `graylog-mongodb` | 集中式日志 | 9000 (UI) |
| `grafana` | 仪表板 | 3000 |
### 外部扫描器(打包在连接器镜像中)
- Nosey Parker (GSS)
- KICS (IAC)
- Trivy (SCA)
## 5. 架构与数据模型
### 架构图
```
flowchart LR
subgraph connectors [Connectors]
GH[GitHub service]
GSS[GSS]
IAC[IAC]
SCA_V[SCA Vuln]
SCA_L[SCA License]
end
SDK[Vuln Commander SDK]
API[FastAPI API]
PG[(PostgreSQL)]
GL[Graylog]
GF[Grafana]
GH --> SDK
GSS --> SDK
IAC --> SDK
SCA_V --> SDK
SCA_L --> SDK
SDK -->|JWT REST| API
API --> PG
connectors -->|GELF| GL
GF -->|SQL views| PG
```
### 仓库布局
```
vuln-commander/
├── api/ # REST API, Alembic migrations, UI templates
├── sdk/ # Client library for connectors
├── shared/ # Shared Pydantic schemas and enums
├── connectors/
│ ├── connectors_spec.yml # Connector registry for DB bootstrap
│ ├── service/github/ # Service connector
│ └── devsecops/ # GSS, IAC, SCA-*
├── grafana/ # Provisioning and dashboards
├── static/ # Docs assets, SQL for views
└── docker-compose.yml
```
### 数据流
1. **GitHub** 根据计划定期读取仓库 URL 列表并调用 `POST /api/v1/projects` — 项目和提交记录将被存入数据库。
2. **DevSecOps 连接器** 调用 `GET /api/v1/projects/{connector_type}`,克隆仓库并运行扫描器。
3. SDK 执行 **漏洞同步** (`process_vulns`):创建新发现的漏洞,关闭已消失的漏洞,并在再次检测到之前已关闭的漏洞时将其重新打开。
4. 扫描完成后,通过 `POST /api/v1/connectors/history` 记录 **历史记录**(严重程度计数器)。
5. Grafana 根据 SQL 视图 (`vc_view_*`) 生成报告。
### REST API (`/api/v1`)
| 前缀 | 用途 | 调用方 |
|--------|---------|-----------|
| `/auth` | 签发和刷新 JWT | 用户、连接器 |
| `/users` | 用户管理 | 管理员 |
| `/projects` | 项目 CRUD / 扫描器项目列表 | GitHub (`service`)、连接器 (`devsecops`) |
| `/vuln` | 批量漏洞操作、HTML UI 页面 | DevSecOps 连接器、浏览器 |
| `/connectors` | 连接器管理、扫描历史记录、UI 数据 API | 管理员、DevSecOps、浏览器 |
访问控制基于 **JWT scope**:`user`(admin/user 角色)、`connector`(scope 为 `service` / `devsecops`)。
### PostgreSQL 表
| 表名 | 用途 |
|-------|---------|
| `vc_project` | 项目:名称、团队、克隆 URL、分支、状态 |
| `vc_commit` | 项目的最新已知提交 |
| `vc_user` | 平台用户 |
| `vc_connector` | 连接器账号 |
| `vc_refresh_token` | 刷新 token(用户或连接器) |
| `vc_vuln` | 漏洞(唯一的 `hash`) |
| `vc_connector_scan_history` | 扫描后的严重程度快照 |
### 枚举
- **UserTeam**: `ti`, `sandbox`
- **UserRole**: `user`, `admin`
- **ProjectStatus**: `active`, `archived`
- **ConnectorScope**: `service`, `devsecops`
- **ConnectorType**: `iac`, `gss`, `sca_license`, `sca_vuln`, `github`
- **VulnSeverity**: `info`, `low`, `medium`, `high`, `critical`
-VulnStatus**: `new`, `awaiting_review`, `closed`, `false_positive`, `reopened`
### 漏洞哈希
扫描结果的唯一性由以下字段的 MD5 值定义:
`project_id`, `connector_type`, `severity`, `filepath`, `line`, `custom_fields` (JSON)。
相同的公式应用于 `shared/schemas/vuln.py` 和 `sdk.src.utils.helpers.generate_vuln_hash` 中。
### SQL 视图 (Grafana)
在迁移期间从 `api/migrations/views_generation_spec` 创建:
- `vc_view_general_vulnerabilities_statistic` — 项目摘要
- `vc_view_project_vulnerabilities_statistic` — 按项目划分的详情
- `vc_view_gss_vulnerabilities_statistic`, `vc_view_iac_*`, `vc_view_sca_*` — 按扫描器划分的细分
### 连接器注册表
文件 `connectors/connectors_spec.yml` 定义了在 API 启动时用于 **一次性注册** 的连接器(参见 `api/docker-entrypoint.sh`):
```
- name: github
env: GITHUB # → CONNECTOR_GITHUB_UUID / CONNECTOR_GITHUB_PASSWORD
scope: service
type: github
```
## 6. SDK
用于构建连接器的 Python 库:与 API 通信的 HTTP 客户端、漏洞同步、cron 调度器和 Graylog 日志记录。
**完整的类和方法参考:** [sdk/README.md](sdk/README.md)
快速示例:
```
from sdk import Scheduler, VulnCommanderSDK
from shared.schemas.constants import ConnectorType
async def main():
scheduler = Scheduler("0 12 */1 * *") # cron
for _ in scheduler:
async with VulnCommanderSDK(connector_id, connector_password) as sdk:
projects = await sdk.get_projects(ConnectorType.gss)
# ... scan ...
await sdk.process_vulns(actual_vulns, project.vulns)
```
在 Docker 网络内部,默认的 API URL 为 `http://api:8000/api/v1` (`sdk/src/utils/config.py`)。
## 7. 全新安装与运行
### 环境要求
- Docker 和 Docker Compose v2
- ~8 GB 可用内存(Graylog + PostgreSQL + 连接器)
- 需要互联网访问权限以下载/构建镜像
### 步骤 1. 克隆与环境变量
```
git clone vuln-commander
cd vuln-commander
cp .env.example .env
```
编辑 `.env`:
- PostgreSQL, pgAdmin, Grafana 和 Graylog 的密码(`GRAYLOG_PASSWORD_SECRET` ≥ 16 个字符)
- `GRAYLOG_ROOT_PASSWORD_SHA2` — Graylog 管理员密码的 SHA-256 十六进制值
- `ADMIN_*` — API 管理员账号(仅在数据库中尚无用户时创建)
- `CONNECTOR_*_UUID` 和 `CONNECTOR_*_PASSWORD` — 必须与每个连接器的 `.env` 中的 `CONNECTOR_ID` / `CONNECTOR_PASSWORD` 相匹配
### 步骤 2. 连接器配置
在 `docker-compose.yml` 中为每个服务创建一个 `.env` 文件(不提交到代码仓库中):
**`connectors/service/github/.env`**
```
CONNECTOR_ID=
CONNECTOR_PASSWORD=
CRON_SCHEDULE=0 12 */1 * *
PARALLEL_TASKS_COUNT=2
GRAYLOG_UDP_PORT=12201
```
**`connectors/devsecops/gss/.env`**(`iac`, `sca-license`, `sca-vuln` 使用相同的模式,并使用与 `.env` 匹配的 UUID):
```
CONNECTOR_ID=
CONNECTOR_PASSWORD=
CRON_SCHEDULE=0 12 */1 * *
PARALLEL_TASKS_COUNT=2
VULNS_REQUEST_BATCH_SIZE=100
GRAYLOG_UDP_PORT=12201
```
### 步骤 3. GitHub 仓库列表
```
mkdir -p connectors/service/github
cat > connectors/service/github/projects.txt <<'EOF'
https://github.com/org/example-repo.git
EOF
```
每行一个克隆 URL。该文件已列入 `.gitignore`。
### 步骤 4. 启动技术栈
```
docker compose up -d --build
```
在 `api` 首次启动时:
1. 等待 PostgreSQL 准备就绪
2. 运行 `alembic upgrade head`
3. 创建管理员用户(如果数据库为空)以及来自 `connectors_spec.yml` 的连接器
完整的数据库初始化可能需要 1-2 分钟(PostgreSQL 健康检查的 `start_period` 最多为 120 秒)。
### 步骤 5. 验证
| 服务 | URL | 备注 |
|---------|-----|-------|
| **Web UI(主页)** | http://localhost:8000/api/v1/ | 需要登录;指标和快捷链接 |
| **登录** | http://localhost:8000/api/v1/auth/ | 平台用户邮箱 + 密码 |
| **项目** | http://localhost:8000/api/v1/projects | 项目注册表和漏洞入口点 |
| **连接器** | http://localhost:8000/api/v1/connectors | 实时连接器状态(每 60 秒自动刷新) |
| API / OpenAPI | http://localhost:8000/docs | Swagger UI |
| pgAdmin | http://localhost:8080 | 凭据来自 `.env` |
| Grafana | http://localhost:3000 | 预配置的 **vuln-commander dashboard**;`GF_SECURITY_ADMIN_*` |
| Graylog | http://localhost:9000 | Root 密码来自 `.env` 中的 SHA2 |
| 漏洞管理 | http://localhost:8000/api/v1/vuln/manage/{project_name} | 数据就绪后,可从“项目”表格中打开 |
针对连接器和脚本的 API 身份验证:使用 Basic Auth 调用 `POST /api/v1/auth/`(使用 `CONNECTOR_ID` + 连接器密码;如果是通过编程方式访问,则使用用户邮箱 + 密码)。
### 步骤 6. 停止并彻底重置
```
# 停止
docker compose down
# 移除 volumes(清理 DB、Graylog、Grafana)
docker compose down -v
```
执行 `down -v` 后,下次执行 `up` 将再次运行迁移并执行引导程序。
### 不使用 Docker 进行本地开发
```
# API(从 repo 根目录运行;PostgreSQL 必须正在运行)
export PYTHONPATH=$(pwd)
export POSTGRESQL_HOST=localhost
# ... 来自 .env 的其余 POSTGRESQL_*
uv sync --project api
uv run --project api alembic -c api/alembic.ini upgrade head
uv run --project api python -m api.src.core.orm.initialisation.session
uv run --project api uvicorn api.src.main:app --reload --host 0.0.0.0 --port 8000
```
在 `sdk/` 目录中运行连接器时,需将 `PYTHONPATH` 指向 monorepo 根目录,并设置 `API_BASE_URL=http://localhost:8000/api/v1`(如有需要,请调整 `sdk/src/utils/config.py` 或将 URL 移至环境变量中)。
## 许可证
参见 [LICENSE](LICENSE)。
标签:DevSecOps, GPT, OpenSource, 上游代理, 测试用例, 漏洞管理, 版权保护, 逆向工具