sanghakbae/vuln-mgmt-system
GitHub: sanghakbae/vuln-mgmt-system
一套企业级安全运营漏洞管理系统,提供从资产登记到漏洞整改报告的全流程闭环管理与审计追踪。
Stars: 0 | Forks: 0
# 漏洞管理系统
这是一个在一个 Web 应用中处理漏洞管理全流程的内部运营工具。
当前代码库包含 React + Vite 前端和 Node.js + PostgreSQL 后端,实际运营数据基于 PostgreSQL RDS 的 `vuln_management` 数据库。
当前结构:
- 前端: React 18 + Vite 5
- 后端: Express + `pg`
- 数据库: PostgreSQL RDS
- 开发认证: 基于本地 session 的登录
- 运营数据迁移: 已完成从原有 Supabase PostgreSQL 到目标 RDS 的迁移
前端保持了原有的 `supabase.from(...).select(...)` 调用模式,但在内部通过本地适配器连接到了 `/api` 后端。
部署地址:
- `https://security.muhayu.com/`
代码库:
- `https://github.com/muhayu/Security-portal`
## 1. 主要功能
- 基于本地 session 的登录
- 信息资产注册、修改、Excel Import/Export
- 按类型管理检查标准
- 选定并确认检查目标
- 注册检查结果及导入脚本结果
- 漏洞整改状态管理
- 生成并预览结果报告
- 认证与安全设置管理
- 访问权限管理
- 查看审计日志 (Security Audit Logs)
- 管理员查看 DB 连接信息
- 管理员只读 SQL 查询功能
- 工具菜单中的 `PC OFF`
- 通过 `/pc-monitoring` 在安全门户内显示仪表板
- 提供 `/agent` 公开安装页面
- 在 `环境设置 > 用户管理 > 服务权限` 中启用/禁用
- 默认权限仅对 superadmin 启用
## 2. 流程
当前应用按照以下顺序进行使用设计。
1. 信息资产管理
2. 按类型检查标准
3. 检查目标管理
4. 注册检查结果
5. 漏洞管理
6. 报告管理
每个步骤必须在前一个步骤确认后才能激活。
示例:
- 信息资产确认后激活 `按类型检查标准`
- 按类型检查标准确认后激活 `检查目标管理`
- 检查目标确认后激活 `注册检查结果`
- 检查结果确认后激活 `漏洞管理`
- 漏洞确认后激活 `报告管理`
确认状态被设计为使用 DB 的共享状态,而不是浏览器的本地状态,因此在刷新或更改浏览器后也会保持。
## 3. 技术栈
- Frontend: React 18, Vite 5
- Styling: Tailwind CSS
- Backend: Node.js, Express
- Database: PostgreSQL, Amazon RDS
- DB Client: `pg`
- Import/Export: `xlsx`, `papaparse`
- Container: Docker
- Legacy Reference: 保留 Supabase schema/data migration scripts
## 4. 项目结构
```
.
├─ server/
│ ├─ config.js
│ ├─ db.js
│ └─ index.js
├─ database/
│ ├─ schema.sql
│ └─ *.sql
├─ src/
│ ├─ layout/
│ ├─ pages/
│ │ ├─ LoginPage.jsx
│ │ ├─ DashboardPage.jsx
│ │ ├─ AssetsPage.jsx
│ │ ├─ ChecklistPage.jsx
│ │ ├─ TargetRegistrationPage.jsx
│ │ ├─ InspectionPage.jsx
│ │ ├─ VulnerabilitiesPage.jsx
│ │ ├─ ReportPage.jsx
│ │ ├─ SecurityPage.jsx
│ │ ├─ AccessControlPage.jsx
│ │ └─ AuditPage.jsx
│ ├─ constants/
│ ├─ lib/
│ ├─ utils/
│ └─ App.jsx
├─ scripts/
│ ├─ migrate-postgres-data.mjs
│ ├─ run-sql-file.mjs
│ └─ update_check_items_copy.mjs
├─ supabase/
│ ├─ assets.sql
│ ├─ workflow_confirmations.sql
│ └─ migrations/
├─ sub11_pcmon/
│ ├─ src/
│ ├─ public/
│ └─ agent/
├─ .github/workflows/
│ └─ deploy.yml
├─ Dockerfile
└─ vite.config.js
```
主要目录说明:
- `server/`: Express API 服务器,DB 连接,管理员查询 API
- `database/`: 目标 PostgreSQL 初始 schema 和 seed SQL
- `scripts/`: SQL 执行及原 DB -> 目标 DB 数据迁移脚本
- `src/lib/supabase.js`: 将前端原有的 Supabase 调用模式连接到 `/api` 后端的适配器
- `src/pages/SecurityPage.jsx`: 安全设置,DB 连接信息查询,只读 SQL 查询 UI
- `sub11_pcmon/`: PC OFF 仪表板及 macOS/Windows agent
## 4.1 PC OFF
`PC OFF` 是集成在安全门户工具菜单中的办公 PC 状态检查功能。
- 门户内部页面: `https://security.muahyu.com/pc-monitoring`
- 公开 agent 安装页面: `https://security.muahyu.com/agent`
- agent 报告 API: `https://security.muahyu.com/agent/api/report`
- 内部监控服务器默认端口: `4500`
- 运营 DB: 安全门户连接的 PostgreSQL DB 中的 `pmon_*` 表
部署到生产环境时,`server/schema.js` 中的运行时 schema 校正会创建 `pmon_machines`, `pmon_events`,
`pmon_ping_targets` 表。不要在本地直接连接运营 DB 进行手动修改。
权限通过 `环境设置 > 用户管理 > 服务权限` 中的 `PC OFF` 项控制。默认值为
除 superadmin 外禁用,工具菜单仅向拥有权限的用户显示。
## 5. 本地运行方法
### 5.1 安装依赖
```
npm install
```
### 5.2 设置环境变量
复制 `.env.example` 创建 `.env` 后,输入 PostgreSQL 连接值。
```
cp .env.example .env
```
`.env`
```
VITE_AUTH_MODE=external
VITE_DEV_API_TARGET=http://localhost:4000
VITE_LOCAL_USER_EMAIL=shbae@muhayu.com
VITE_LOCAL_USER_NAME=shbae
PORT=4000
CORS_ORIGIN=http://localhost:5173
PGHOST=dev-superset-postgresql.c64ycexnhzbb.ap-northeast-2.rds.amazonaws.com
PGPORT=5432
PGDATABASE=vuln_management
PGUSER=shbae
PGPASSWORD=your-db-password
```
说明:
- `VITE_AUTH_MODE=external`: 默认值。使用 Google OAuth 按账户登录
- `VITE_AUTH_MODE=local`: 仅在开发环境中使用固定的本地 session 登录
- `VITE_LOCAL_USER_EMAIL`, `VITE_LOCAL_USER_NAME`: 本地登录账户默认值
- `PG*`: Express 后端实际要连接的目标 PostgreSQL 信息
### 5.3 初始化 DB schema
```
npm run db:schema
```
### 5.4 运行开发服务器
```
npm run dev
```
默认地址:
- 前端: `http://localhost:5173/`
- 后端 API: `http://localhost:4000/api/health`
健康检查示例:
```
{"ok":true,"databaseConnected":true,"database":"vuln_management"}
```
### 5.5 生产构建
```
npm run build
```
### 5.6 生产运行
```
npm run start
```
## 6. PostgreSQL 迁移
从原有 Supabase PostgreSQL 或其他 PostgreSQL 移动数据时,需将源/目标 DB 连接信息放入环境变量中执行。
```
SOURCE_DATABASE_URL=postgresql://source-user:source-password@source-host:5432/postgres \
TARGET_DATABASE_URL=postgresql://target-user:target-password@target-host:5432/postgres \
npm run db:migrate-data
```
迁移目标表:
- `assets`
- `users`
- `security_settings`
- `security_audit_logs`
- `workflow_confirmations`
- `check_items`
- `inspection_targets`
- `inspection_results`
- `vulnerabilities`
- `reports`
目前已迁移至目标 DB 的标准记录数:
- `assets`: 382
- `users`: 10
- `security_settings`: 1
- `security_audit_logs`: 356
- `workflow_confirmations`: 5
- `check_items`: 82
- `inspection_targets`: 2
- `inspection_results`: 9
- `vulnerabilities`: 2
- `reports`: 6
迁移脚本工作原理:
- 查询源表全部数据
- 仅以目标表实际列为准进行 insert/upsert
- 基于 `id`, `asset_code`, `step_key` 标准处理冲突
- 即使原/目标之间存在列差异,也仅反映公共列
## 7. Docker 部署
当前的 Dockerfile 将 Vite 构建产物和 Node.js 后端在同一个容器中运行。
```
docker build -t vuln-mgmt-system .
docker run --rm -p 4000:4000 --env-file .env vuln-mgmt-system
```
容器启动后:
- 应用/静态文件 + API: `http://localhost:4000`
- 状态检查: `http://localhost:4000/api/health`
生产部署流程:
1. 同步 `main` 分支最新代码
2. `docker build -t vuln-mgmt-system .`
3. 在目标服务器中注入 `.env`
4. 通过 `docker run` 或在编排环境中启动容器
5. 通过 `/api/health` 检查 DB 连接状态
GitHub 安全监控可以在 `环境设置 > GitHub 安全设置` 中输入 GitHub API key 并保存到 DB。
如果有已保存的 DB 设置,服务器会优先使用该 token,只有在没有时才将生产 `.env` 中的
`GITHUB_SECURITY_TOKEN` 作为 fallback 使用。生产容器中没有本地的 `gh auth token`,
因此必须需要 DB 设置或环境变量其中之一。
```
GITHUB_SECURITY_TOKEN=ghp_your-read-only-github-token
GITHUB_SECURITY_ORG=muhayu
GITHUB_SECURITY_USE_GH_CLI=false
```
token 仅按只读用途发放,以 Classic PAT 为标准授予 `repo`, `read:org`, `security_events`
权限。如果还需要查询组织 Audit log,则必须添加符合 GitHub 组织/企业策略的
Audit log 查询权限。不在此门户中启用 Push protection。
GitHub 发行的 token 原文仅在创建后可查看一次,因此如果丢失,需重新发放
并在门户的 `环境设置 > GitHub 安全设置` 页面重新保存。
### 7.1 uploads 持久化
证据文件保存在服务器本地的 `uploads/` 目录。
各服务的子文件夹分开使用,如 `uploads/rms_evidence`, `uploads/itgc_evidence`。
为了在重新部署容器后依然保持,必须将宿主目录挂载为 volume。
推荐运行示例:
```
docker run --rm -p 4000:4000 --env-file .env -v "$(pwd)/uploads:/app/uploads" vuln-mgmt-system
```
如果使用 Docker Compose,可以按如下固定。
```
docker compose up -d --build
```
此代码库包含了 [`docker-compose.yml`](./docker-compose.yml),`./uploads` 将连接到容器的 `/app/uploads`。
在 Kubernetes/Pod 部署中,同样必须将 `/app/uploads` 挂载到 PVC,
才能在重新部署后保留证据文件。示例请参见 [`k8s/vuln-mgmt-system.yaml`](./k8s/vuln-mgmt-system.yaml)。
### 7.2 uploads 备份/恢复
备份:
```
./scripts/backup-uploads.sh
```
恢复:
```
./scripts/restore-uploads.sh backups/uploads_YYYY-MM-DD_HHMMSS.tar.gz
```
如果需要,可以更改备份位置。
```
UPLOADS_DIR=./uploads BACKUP_DIR=./backups ./scripts/backup-uploads.sh
```
推荐运营原则:
- 部署服务器的 `uploads/` 必须作为持久卷保留
- DB 备份与 `uploads/` 备份分离
- 在部署前后确认 `uploads/` 目录的存在
## 8. 认证及安全设置页面
在 `认证及安全设置` 页面可以处理以下内容。
- 基于 `security_settings` 表查询/修改允许的域名、session 超时、是否使用 OAuth
- 查询当前后端正在连接的 DB host/port/database/user
- 执行只读 SQL
SQL 查询限制:
- `SELECT`
- `WITH`
- `EXPLAIN`
不允许:
- `INSERT`
- `UPDATE`
- `DELETE`
- 多重 statement
管理员查询 API:
- `GET /api/admin/database-info`
- `POST /api/admin/query`
## 9. SonarQube Quality Gate 运营标准
全公司默认的 Quality Gate 不直接修改 SonarQube 的 Built-in `Sonar way`,而是将副本 `Code Quality Gate` 指定为 `Default` 使用。因为 `Sonar way` 是 Built-in 策略,所以不直接修改。
目前推荐条件基于 `On New Code`。此设置旨在不将现有旧代码全部一次性作为失败对象,而是管理新增或更改代码的质量。
推荐条件:
```
Duplicated Lines (%) is greater than 10.0%
Maintainability Rating is worse than A
Reliability Rating is worse than A
Security Rating is worse than A
```
各条件含义:
- `Duplicated Lines (%) > 10.0%`: 如果新代码的重复率超过 10% 则失败。由于默认值 3% 对于前端/仪表板型项目可能过于严苛,因此将标准定为 10%。
- `Maintainability Rating worse than A`: 如果新代码中复杂度、过度嵌套、可维护性 code smell 达到一定水平以上则失败。
- `Reliability Rating worse than A`: 如果新代码中存在可能有 bug 的问题则失败。
- `Security Rating worse than A`: 如果新代码中存在被分类为漏洞的问题则失败。
目前排除的条件:
- `Security Hotspots Reviewed < 100%`: 如果没有安全审查负责人或定期审查流程,未审查的 hotspot 会导致持续失败。在初期运营中从 Quality Gate 中排除,并将 High priority hotspot 作为参考指标管理。
- `Coverage < 80%`: 如果测试覆盖率报告未上传至 SonarQube,则会被评估为 0%,可能因设置问题而非质量问题导致失败。在覆盖率收集体系准备好后再次应用。
- `New code has 0 issues`: 只要有一个 code smell 就会导致整个 Gate 失败,因此作为初期运营标准过于严苛。以 Rating 条件替代。
注意事项:
- SonarQube 页面中的 `Review and update` 是恢复为 Sonar 推荐默认条件的操作,因此在维持上述策略时请勿点击。
- 如果将 `Code Quality Gate` 指定为 `Default`,则会对未连接单独 Gate 的项目及新项目默认应用。
- Quality Gate 并非由 `git push` 本身执行,而是在推送后运行 CI/CD 或手动 `sonar-scanner` 分析时进行评估。
## 10. 关于原有 Supabase 的参考
原有应用编写为直接连接 Supabase 的结构,以下内容仅供过去的运营参考。切换到 RDS 后,基于后端整理认证和数据访问才是正确的。
### 10.1 必需环境变量
- `VITE_SUPABASE_URL`
- `VITE_SUPABASE_ANON_KEY`
### 10.2 执行 SQL
必须在 Supabase SQL Editor 中执行以下文件。
1. `supabase/assets.sql`
2. `supabase/workflow_confirmations.sql`
#### `supabase/assets.sql`
创建信息资产表的基本结构。
主要列:
- `asset_code`
- `asset_type`
- `hostname`
- `ip_address`
- `os_version`
- `related_service`
- `purpose`
- `location`
- `department`
- `owner_name`
- `manager_name`
- `confidentiality`
- `integrity`
- `availability`
- `criticality_score`
- `criticality_grade`
- `status#### `supabase/workflow_confirmations.sql`
共享保存各步骤的确认状态。
管理目标步骤:
- `assets`
- `checklist`
- `inspection`
- `inspectionResult`
- `vuln`
如果没有此表:
- 即使看起来按下了确认按钮
- 每个用户看到的状态可能不同
- 刷新后可能看起来已被解除。
### 10.3 权限及策略
在实际运营中,至少需要以下内容。
- 允许对 `assets` 读/写
- 允许对 `workflow_confirmations` 读/写
- 允许对 `users` 读/更新
- 允许对 `security_audit_logs` 进行 insert
特别是如果 `users` 表的策略有误,在 Google OAuth 登录后可能会发生以下错误。
```
Database error saving new user
```
### 10.4 域名阻断 trigger 注意事项
过去由于留在 `auth.users` 中的 `check_domain_trigger`,曾出现在 Gmail 登录时阻止新用户保存的案例。
如果 OAuth 成功,但在登录后立即反复出现以下错误,则应怀疑 DB trigger 的问题。
```
Database error saving new user
```
## 11. Google OAuth 设置
### 11.1 应用代码行为
登录界面在 [src/pages/LoginPage.jsx](/Users/shbae-pc/Tools/vuln-mgmt-system/src/pages/LoginPage.jsx) 中使用 Google OAuth。
当前行为:
- `prompt: 'select_account'`
- `redirectTo` 使用包含当前部署路径的 URL
- 允许账户在应用内部基于 `security_settings.allowed_domains` 进行验证
### 11.2 Google Cloud 设置
OAuth client 必须满足以下条件。
- 应用类型: `Web application`
- 授权重定向 URI:
```
https://gfybyxbrmkwbzuyhyqiv.supabase.co/auth/v1/callback
```
### 11.3 OAuth 同意屏幕
- 用户类型: `External`
- 在测试阶段,必须将外部 Gmail 账户添加到 `Test users`
- 公开运营时,应切换至应用发布状态
### 11.4 Supabase Auth URL 设置
#### 基于本地开发
`Site URL`
```
http://localhost:5173/
```
`Redirect URLs`
```
http://localhost:5173/
```
#### 基于 GitHub Pages 部署
`Site URL`
```
https://sanghakbae.github.io/vuln-mgmt-system/
```
`Redirect URLs`
```
https://sanghakbae.github.io/vuln-mgmt-system/
http://localhost:5173/
```
注意事项:
- `https://gfybyxbrmkwbzuyhyqiv.supabase.co/auth/v1/callback` 不是要放入 Supabase URL 设置中的值
- 此值只能注册在 Google Cloud 的授权重定向 URI 中
## 12. GitHub Pages 部署
### 12.1 当前部署方式
使用 GitHub Actions + GitHub Pages。
相关文件:
- `.github/workflows/deploy.yml`
- `vite.config.js`
### 12.2 Vite base 路径
此代码库部署在 GitHub Pages 子路径下,因此在 `vite.config.js` 中进行了以下设置。
```
base: '/vuln-mgmt-system/'
```
### 12.3 GitHub Actions Secret
必须在代码库的 `Settings > Secrets and variables > Actions` 中注册以下两项。
1. `VITE_SUPABASE_URL`
2. `VITE_SUPABASE_ANON_KEY`
示例:
`VITE_SUPABASE_URL`
```
https://gfybyxbrmkwbzuyhyqiv.supabase.co
```
`VITE_SUPABASE_ANON_KEY`
```
Supabase anon key 전체 값
```
### 12.4 GitHub Pages 设置
在代码库的 `Settings > Pages` 中:
- Source: `GitHub Actions`
### 12.5 部署触发
在 `main` 分支 push 时自动部署。
```
git push origin main
```
### 12.6 部署确认
部署 URL:
```
https://sanghakbae.github.io/vuln-mgmt-system/
```
## 13. 菜单说明
### 13.1 Dashboard
- 全部资产数
- 检查目标数
- 漏洞数量
- 最近检查结果
- 最近整改情况
- 最近报告生成历史
### 13.2 信息资产管理
- 资产注册
- 资产编辑
- Excel Import/Export
- 搜索/筛选
- 信息资产确认
特征:
- 根据 CIA (机密性/完整性/可用性) 自动计算重要度
- 点击资产时在行下方展开编辑
- 注册采用弹窗方式
- 为加快初始渲染速度,使用缓存 + 后台重新查询
### 13.3 按类型检查标准
- 注册检查项
- 修改检查项
- 管理危险度/检查方式/是否使用
- 确认后激活下一步
### 13.4 检查目标管理
- 从信息资产列表中选定检查目标
- 基于过滤的查询
- 目标确认
### 13.5 注册检查结果
- 输入各项判定
- 管理状态/结果/整改状态
- 导入脚本结果
- 结果确认
### 13.6 漏洞管理
- 按漏洞管理整改状态
- 查看详细情况、判定依据、整改内容
- 漏洞确认
### 13.7 报告管理
- 生成报告
- HTML/PDF 输出
- 结果报告预览
### 13.8 认证及安全设置
- session 超时
- 是否使用 Google OAuth
- 允许域名设置
### 13.9 访问权限管理
- 查看用户角色
- 更改权限
### 13.10 审计日志
- 查看安全相关更改历史
- 查看详细日志
## 14. 数据 Import / Export
### 14.1 信息资产 Import
信息资产管理支持基于 Excel 的 Import。
处理规则:
- 根据 sheet 名称区分资产类型
- 如果有 `asset_code` 则 upsert
- 如果没有 `asset_code` 则 insert
- `status` 默认为 `운영`
- `criticality_score`, `criticality_grade` 使用基于 CIA 的计算值
映射示例:
- `SERVER sheet` → `SERVER`
- `DATABASE sheet` → `DATABASE`
- `WEB_APP sheet` → `WEB_APP`
- `WAS sheet` → `WAS`
- `NETWORK sheet` → `NETWORK`
- `SECURITY sheet` → `SECURITY`
- `ETC sheet` → `ETC`
### 14.2 信息资产 Export
可以将当前列表导出为 Excel。
## 15. session 及认证行为
### 15.1 session 超时
在 [src/App.jsx](/Users/shbae-pc/Tools/vuln-mgmt-system/src/App.jsx) 中管理空闲 session 计时器。
活动检测事件:
- `mousemove`
- `mousedown`
- `keydown`
- `scroll`
- `touchstart`
- `click`
如果在设定时间内没有用户活动:
- 记录审计日志
- 通知 session 过期
- 强制登出
### 15.2 登出
登出使用 `supabase.auth.signOut({ scope: 'global' })`。
### 15.3 用户同步
登录后立即:
- 查询 `security_settings`
- 验证允许的域名
- 对 `users` 表进行 upsert
- 应用当前用户角色
## 16. 性能相关备忘
最近反映的内容:
- Dashboard 摘要缓存
- 信息资产管理 `localStorage` 缓存
- 登录后立即对资产列表进行 warmup
- 缩减部分繁重的 `select('*')`
- 消除重复查询
注意事项:
- Dashboard 主要使用摘要查询,因此速度较快
- 信息资产列表由于需要读取实际的行数据,因此可能相对较慢
- 目前采用先显示缓存再用最新值更新的结构
## 17. 常见问题及原因
### 17.1 Google 登录后返回登录页面
主要原因:
- Supabase `Site URL` / `Redirect URLs` 设置错误
- 缺少 GitHub Pages 路径 (`/vuln-mgmt-system/`)
- OAuth 同意屏幕测试用户设置问题
### 17.2 `Database error saving new user`
主要原因:
- `users` 表策略问题
- 附加到 `auth.users` 的自定义 trigger 失败
- 过去 `check_domain_trigger` 冲突
### 17.3 部署后白屏
主要原因:
- 未设置 GitHub Actions Secret
- 缺少 `VITE_SUPABASE_URL`, `VITE_SUPABASE_ANON_KEY`
- Pages 部署未完成
### 17.4 GitHub Pages 404
主要原因:
- 在 `Settings > Pages` 中未设置 `GitHub Actions`
- Actions 部署失败
## 18. 运营检查清单
部署前检查:
- 确认 `.env` 值是否指向正确的 Supabase 项目
- 执行 `supabase/assets.sql`
- 执行 `supabase/workflow_confirmations.sql`
- 注册 GitHub Secrets
- 将 Supabase Auth URL 设置为部署地址
- 确认 Google OAuth Redirect URI
- 将 GitHub Pages Source 设置为 `GitHub Actions`
部署后检查:
- 登录是否成功
- 是否能查看信息资产列表
- 确认状态是否已共享反映
- 是否生成报告
- 是否记录审计日志
## 19. 开发备忘
- 部署 base 路径为 `/vuln-mgmt-system/`
- 本地测试为 `http://localhost:5173/`
- 部署和本地可能会查看同一个 Supabase 项目,因此必须注意是否分离运营/开发
- `scripts/update_check_items_copy.mjs` 是用于整理检查项说明/判定标准/整改方案的脚本
## 20. 运行命令摘要
```
npm install
cp .env.example .env
npm run dev
```
```
npm run build
```
```
git push origin main
```
标签:GNU通用公共许可证, GPT, GRC, MITM代理, Node.js, PostgreSQL, React, Syscalls, 测试用例, 漏洞管理, 自定义脚本, 请求拦截