Files
csm/AUDIT_REPORT.md
iven b5333d8c93 feat: 添加新插件支持及多项功能改进
- 新增磁盘加密、打印审计和剪贴板管控插件支持
- 优化水印插件显示效果,支持中文及更多Unicode字符
- 改进硬件资产收集逻辑,更准确获取磁盘和显卡信息
- 增强API错误处理,添加详细日志记录
- 完善前端界面,新增插件管理页面
- 修复多个UI问题,优化页面过渡效果
- 添加环境变量覆盖配置功能
- 实现插件状态管理API
- 更新文档和变更日志
- 添加安装程序脚本支持
2026-04-10 22:21:05 +08:00

448 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CSM 系统功能审计报告
> **审计日期**: 2026-04-06
> **审计范围**: 全系统 (Protocol + Server + Client + Frontend)
> **审计方法**: 五步审计流程 + 十项通用检查 + 五种差距模式识别
---
## 1. 功能清单与设计意图
### 1.1 核心功能 (10项)
| # | 功能 | 设计目标 | 业务价值 | 完成度 |
|---|------|---------|---------|--------|
| F1 | 设备注册与管理 | 设备身份认证、在线状态追踪 | 资产可见性 | **95%** |
| F2 | 实时状态监控 | CPU/内存/进程/磁盘/网络采集 | 运维告警基础 | **70%** |
| F3 | 硬件/软件资产采集 | 硬件信息+已安装软件清单 | 资产管理 | **90%** |
| F4 | USB设备管控 | 策略化USB设备接入控制 | 数据防泄露 | **85%** |
| F5 | 心跳与HMAC验证 | 连接存活检测+防伪造 | 通信安全 | **95%** |
| F6 | JWT认证与权限 | 登录/刷新/角色鉴权 | 访问控制 | **90%** |
| F7 | WebSocket实时推送 | 设备上下线/告警实时通知 | 运维效率 | **85%** |
| F8 | 告警规则与通知 | 自定义告警+邮件/Webhook | 主动监控 | **80%** |
| F9 | 分组管理 | 设备分组+配置三级作用域 | 批量管理 | **85%** |
| F10 | 管理审计日志 | 管理员操作追溯 | 合规审计 | **80%** |
**综合核心功能完成度: 85.5%**
### 1.2 客户端插件 (9项)
| # | 插件 | 设计目标 | 业务价值 | 完成度 | 关键问题 |
|---|------|---------|---------|--------|---------|
| P1 | 水印 (watermark) | 屏幕叠加用户信息水印 | 拍照溯源 | **90%** | 不上报执行状态 |
| P2 | 上网行为管理 (web_filter) | 通过hosts文件拦截URL | 网络安全 | **70%** | 不上报访问日志 |
| P3 | 使用时长统计 (usage_timer) | 活跃/空闲时间+应用使用量 | 行为分析 | **85%** | - |
| P4 | 软件黑名单 (software_blocker) | 检测并终止违规软件 | 软件合规 | **85%** | - |
| P5 | 弹窗拦截 (popup_blocker) | 按规则关闭弹窗窗口 | 用户体验 | **80%** | 不上报拦截统计 |
| P6 | USB文件审计 (usb_audit) | 监控USB驱动器文件操作 | 数据泄露取证 | **85%** | - |
| P7 | USB设备监控 (usb) | USB设备插拔检测+策略执行 | 设备管控 | **80%** | vendor_id/serial匹配是placeholder |
| P8 | 系统监控 (monitor) | 周期性采集设备状态 | 基础监控 | **70%** | 磁盘/网络指标始终为0 |
| P9 | 磁盘加密 (disk_encryption) | BitLocker状态上报 | 数据保护 | **5%** | 全链路断裂(死代码) |
**综合插件完成度: 72.2%**
### 1.3 未实现功能 (3项)
| # | 功能 | 状态 | 有Migration | 有代码 |
|---|------|------|------------|--------|
| N1 | 打印审计 (print_audit) | 完全缺失 | 有(013) | 无 |
| N2 | 剪贴板控制 (clipboard_control) | 完全缺失 | 有(014) | 无 |
| N3 | 插件远程启禁 (PluginControl) | 半实现 | - | 仅客户端侧 |
---
## 2. 五步审计流程详情
### 2.1 文档对齐 — 代码 vs CLAUDE.md
| 检查项 | 结果 | 详情 |
|--------|------|------|
| 协议MessageType编号范围 | ⚠️ 部分一致 | CLAUDE.md记载 0x9x=加密/打印/剪贴板,实际仅磁盘加密有部分代码(未接入) |
| API路由 kebab-case | ✅ 一致 | 所有路由遵循 kebab-case 命名 |
| 配置推送三级作用域 | ✅ 一致 | `push_to_targets()` 支持 global/group/device |
| 插件模板统一性 | ⚠️ 不完全 | `disk_encryption` 未在 main.rs 声明 `mod` |
| 二进制协议格式 | ✅ 一致 | MAGIC+VERSION+TYPE+LENGTH+PAYLOAD |
| 插件开发必改清单 | ⚠️ 不完全 | disk_encryption 未按清单完整执行 |
### 2.2 数据流追踪
#### 端到端完整的功能链路 (12项)
```
[Client 插件] --MessageType Frame--> [Server process_frame] --DB写入--> [API查询] --HTTP--> [前端页面]
```
| 功能 | 链路完整性 | 断裂点 |
|------|-----------|--------|
| 设备注册 | ✅ 完整 | — |
| 状态上报 | ✅ 完整 | — |
| 硬件资产 | ✅ 完整 | — |
| 软件资产 | ✅ 完整 | — |
| USB事件上报 | ✅ 完整 | — |
| USB策略推送 | ✅ 完整 | — |
| 水印配置 | ✅ 完整 | 无上报反馈 |
| 上网过滤配置 | ⚠️ 配置推送正常 | 客户端不上报拦截日志 |
| 使用时长 | ✅ 完整 | — |
| 软件黑名单 | ✅ 完整 | — |
| 弹窗拦截配置 | ⚠️ 配置推送正常 | 客户端不上报拦截统计 |
| USB文件审计 | ✅ 完整 | — |
| 磁盘加密 | ❌ 全链路断裂 | 见下方详情 |
| 插件远程启禁 | ❌ 无服务端触发 | 见下方详情 |
#### 断裂链路详情
**1. 磁盘加密 — 全链路断裂**
```
Protocol: 无 DiskEncryptionStatusPayload 等类型
Client: disk_encryption/mod.rs 存在但 main.rs 未声明 mod
Server: disk_encryption.rs handler 存在但 plugins/mod.rs 未注册路由
TCP: process_frame 无 DiskEncryptionStatus 处理分支
DB: Migration 012 存在但 main.rs 未 include
前端: 无对应页面/路由
```
**2. PluginEnable/PluginDisable — 无触发源**
```
Protocol: PluginControlPayload 已定义 ✅
Client: handle_plugin_control() 已实现 ✅
Server: 无API端点发送此消息 ❌
Server: push_all_plugin_configs() 未推送插件启禁状态 ❌
```
**3. TaskExecute — 客户端未实现**
```
Protocol: TaskExecutePayload 已定义 ✅
Server: 可发送 (仅在设备删除时发 SelfDestruct) ⚠️
Client: 接收后只 log "not yet implemented" ❌
```
**4. ConfigUpdate — 客户端未实现**
```
Protocol: ConfigUpdateType (UpdateIntervals/TlsCertRotate/SelfDestruct) 已定义 ✅
Client: 接收后只 log不做任何处理 ❌
```
**5. WebAccessLog — 客户端不上报**
```
Protocol: WebAccessLogEntry 已定义 ✅
Server: process_frame 有 WebAccessLog 插入分支 ✅
Server DB: web_access_log 表存在 ✅
Client: web_filter 插件修改 hosts 但不拦截日志 ❌
前端: WebFilter.vue 有访问日志tab但数据永远为空 ❌
```
### 2.3 Dead Code 识别
#### 服务端
| 位置 | 类型 | 说明 |
|------|------|------|
| `api/plugins/disk_encryption.rs` | 未注册路由 | 3个handler函数从未被调用 |
| `device.rs: UsbPolicy/UsbPolicyType/UsbDevicePattern` | 未使用类型 | 被 message.rs 中的 UsbPolicyPayload 替代 |
| `Cargo.toml: include_dir` | 未使用依赖 | 未被任何代码引用 |
| `Migrations 012/013/014` | 未include | main.rs 只include 001-011 |
#### 客户端
| 位置 | 类型 | 说明 |
|------|------|------|
| `disk_encryption/mod.rs` | 未编译模块 | main.rs 无 `mod disk_encryption;` |
| `network/mod.rs.tmp.575580.1775308681874` | 临时文件 | 残留的旧版本文件 |
| `monitor/mod.rs: disk_usage/disk_total_mb/network_*` | TODO占位 | 始终上报0值 |
#### 协议层
| 位置 | 类型 | 说明 |
|------|------|------|
| `AlertAck (0x07)` | 无发送/接收方 | 完全死代码 |
| `WebAccessLogEntry` | 结构体未使用 | 定义但客户端从未发送 |
| `TaskExecutePayload` | 结构体未使用 | 定义但从未有效使用 |
| `ConfigUpdateType` | 枚举未使用 | 定义但客户端不处理 |
| `AssetChange/AssetChangeType` | 类型未使用 | 定义但无发送方 |
#### 前端
| 位置 | 类型 | 说明 |
|------|------|------|
| `package.json: dayjs` | 未使用依赖 | 零引用 |
| `package.json: @vueuse/core` | 未使用依赖 | 零引用 |
| `stores/devices.ts: fetchDeviceHistory` | 未调用方法 | store action无调用方 |
| `stores/devices.ts: DeviceStatusDetail` | 未使用导出 | 仅内部使用 |
### 2.4 接口实现检查
| 接口 | 状态 | 说明 |
|------|------|------|
| Frame 编解码 | ✅ 完整 | new/new_json/encode/decode/decode_payload |
| DeviceRepo DB操作 | ✅ 一致 | 静态方法+pool参数模式 |
| API handler | ✅ 一致 | axum State提取模式 |
| 客户端插件 start() | ⚠️ 不统一 | monitor/asset 无 watch channelwatermark/popup/web_filter 无 data_tx |
### 2.5 端到端验证总结
| 通过 | 警告 | 失败 |
|------|------|------|
| 10 | 2 | 2 |
---
## 3. 十项通用审计检查
| # | 检查项 | 评分 | 详情 |
|---|--------|------|------|
| 1 | 代码存在性 | ⚠️ 7/10 | 磁盘加密代码存在未接入;打印/剪贴板仅有migration |
| 2 | 调用链连通性 | ⚠️ 6/10 | 5条断裂链路磁盘加密、插件控制、WebAccessLog、AssetChange、TaskExecute |
| 3 | 配置参数传递 | ✅ 9/10 | 插件watch channel链路完整API到TCP推送完整 |
| 4 | 降级策略 | ⚠️ 7/10 | 重连有退避TLS可选无本地缓存/离线模式 |
| 5 | 错误处理 | ⚠️ 6/10 | 后端完备前端多处catch {}静默吞错误 |
| 6 | 日志完整性 | ✅ 9/10 | tracing覆盖完整审计日志自动记录 |
| 7 | 性能指标监控 | ⚠️ 5/10 | 磁盘/网络指标为0无APM |
| 8 | 安全控制 | ✅ 9/10 | JWT+HMAC+TLS+限流+审计日志 |
| 9 | 兼容性 | ⚠️ 6/10 | 3套HTTP客户端DDL与API不一致 |
| 10 | 文档代码同步 | ⚠️ 7/10 | CLAUDE.md部分超前(打印/剪贴板) |
**综合评分: 7.1/10**
---
## 4. 五种差距模式
### 模式1: "写了没接" (5项)
| 组件 | 位置 | 断裂点 |
|------|------|--------|
| disk_encryption 客户端 | `client/src/disk_encryption/` | main.rs 无 mod 声明 + protocol 无类型 |
| disk_encryption 服务端 | `server/src/api/plugins/disk_encryption.rs` | plugins/mod.rs 无注册 |
| Migration 012/013/014 | `migrations/` | main.rs 未 include |
| PluginEnable/Disable | protocol message.rs | 服务端无发送API |
| ConfigUpdate | 客户端 network/mod.rs | 客户端只log不处理 |
### 模式2: "接了没传" (4项)
| 组件 | 缺失数据 |
|------|---------|
| Monitor 状态上报 | disk_usage/disk_total_mb/network_rx_rate/network_tx_rate 始终为0 |
| Web Filter 插件 | 不上报 WebAccessLog 拦截记录 |
| Popup Blocker 插件 | 不上报拦截统计 |
| Watermark 插件 | 不上报执行状态 |
### 模式3: "传了没存" (1项)
| 组件 | 问题 |
|------|------|
| WebAccessLog | Server有DB handler但Client从未发送web_access_log表始终为空 |
### 模式4: "存了没用" (4项)
| 组件 | 问题 |
|------|------|
| device_groups 表 | DDL支持层级(parent_id)API只支持扁平分组 |
| plugin_state 表 | migration 010创建无API读写 |
| popup_block_stats 表 | 有查询但无写入,始终为空 |
| AssetChange 事件 | protocol定义但无生成逻辑 |
### 模式5: "双系统不同步" (4项)
| 组件 | 不一致 |
|------|--------|
| Protocol USB类型 | UsbPolicy vs UsbPolicyPayload 两套定义 |
| 前端 HTTP 客户端 | api.ts vs devices.ts vs Devices.vue 三套实现 |
| 插件前端调用 | 2个用api.ts4个用raw fetch手动header |
| Migration vs Binary | 14个SQL文件binary只含11个 |
---
## 5. 问题清单 (按严重级别)
### CRITICAL — 阻塞功能完整性 (3项)
#### C-1: disk_encryption 全链路断裂
**影响**: 磁盘加密功能完全不可用
**涉及文件**:
- `crates/protocol/src/message.rs` — 缺少 `DiskEncryptionStatus` 等MessageType和Payload
- `crates/protocol/src/lib.rs` — 缺少 re-export
- `crates/client/src/main.rs` — 缺少 `mod disk_encryption;`
- `crates/client/src/disk_encryption/mod.rs` — 引用不存在的protocol类型
- `crates/server/src/api/plugins/mod.rs` — 缺少 `pub mod disk_encryption;` 和路由注册
- `crates/server/src/tcp.rs` — 缺少 process_frame 分支
- `crates/server/src/main.rs` — 缺少 `include_str!("../../migrations/012_disk_encryption.sql")`
**修复方案**: 按照 CLAUDE.md 的"新增插件必改文件清单"逐项补全10个文件的修改。
---
#### C-2: PluginEnable/PluginDisable 无服务端触发源
**影响**: 管理员无法通过前端远程启用/禁用客户端插件
**涉及文件**:
- `crates/server/src/api/plugins/mod.rs` — 需新增插件启禁API
- `crates/server/src/tcp.rs` — 需在push_all_plugin_configs中推送plugin_state
- `web/src/views/` — 需新增插件管理页面
**修复方案**:
1.`plugin_state` 表基础上新增 API: `POST /api/plugins/:name/enable`, `POST /api/plugins/:name/disable`
2. API handler 写入 plugin_state 表 + 通过 TCP 发送 PluginEnable/PluginDisable
3. push_all_plugin_configs 中查询 plugin_state 并推送
---
#### C-3: print_audit / clipboard_control 完全缺失
**影响**: 打印审计和剪贴板控制功能完全不可用
**涉及文件**:
- `crates/server/src/main.rs` — 需 include migrations 013/014
- 其余所有文件均需从零创建
**修复方案**: 按 CLAUDE.md 清单逐步实现。优先级低于 C-1可先修复 disk_encryption 作为模板)。
---
### HIGH — 影响数据完整性/用户体验 (8项)
#### H-1: Monitor 磁盘/网络指标始终为0
**文件**: `crates/client/src/monitor/mod.rs:79`
**修复**: 使用 Windows API 或 PowerShell 采集磁盘使用率和网络速率
---
#### H-2: Web Filter 不上报访问日志
**文件**: `crates/client/src/web_filter/mod.rs`
**修复**: 在 hosts 拦截生效后,无法直接通过 hosts 方案检测拦截事件。需改为 DNS 代理或浏览器扩展方案才能真正上报访问日志。
**当前状态**: hosts文件方案的技术限制决定了无法准确检测拦截事件。建议将此标记为"已知限制"而非BUG。
---
#### H-3: Popup Blocker 不上报拦截统计
**文件**: `crates/client/src/popup_blocker/mod.rs`
**修复**: 在关闭弹窗时,通过 data_tx 发送拦截统计消息(需新增 MessageType 或复用现有类型)
---
#### H-4: 前端3套HTTP客户端不统一
**文件**:
- `web/src/lib/api.ts` — 标准客户端(fetch)
- `web/src/stores/devices.ts` — 独立axios实例
- `web/src/views/Devices.vue` — 又一个axios实例
**修复**: 统一使用 api.tsdevices store 和 Devices.vue 改用 api 对象
---
#### H-5: 4个插件视图用raw fetch绕过api.ts
**文件**:
- `web/src/views/plugins/UsageTimer.vue`
- `web/src/views/plugins/SoftwareBlocker.vue`
- `web/src/views/plugins/PopupBlocker.vue`
- `web/src/views/plugins/UsbFileAudit.vue`
**修复**: 将 raw fetch 调用改为 `api.get()`/`api.post()` 等方法
---
#### H-6: 前端多处静默吞错误
**文件与行号**:
- `Layout.vue` — fetchUnreadAlerts catch {}
- `Dashboard.vue` — 数据加载 catch {}
- `DeviceDetail.vue` — 多处 catch {}
- `Settings.vue` — health check catch {}
- `UsbPolicy.vue` — 多处 catch {}
**修复**: 将 catch {} 改为 `ElMessage.error()` 展示错误信息
---
#### H-7: UsbPolicy 两套并行定义
**文件**:
- `crates/protocol/src/device.rs``UsbPolicy`/`UsbPolicyType`/`UsbDevicePattern`
- `crates/protocol/src/message.rs``UsbPolicyPayload`/`UsbDeviceRule`
**修复**: 删除 device.rs 中未使用的 `UsbPolicy` 等类型,统一使用 message.rs 中的定义
---
#### H-8: device_groups 表层级设计与API不一致
**文件**: `migrations/001_init.sql` — parent_id 列
**API**: `crates/server/src/api/groups.rs` — 仅扁平分组
**修复**: 要么移除 parent_id 列,要么实现层级分组功能。建议当前先移除 parent_id非必要功能
---
### MEDIUM — 代码质量/维护性 (9项)
| ID | 问题 | 修复 |
|----|------|------|
| M-1 | `network/mod.rs.tmp.*` 临时文件 | 删除文件 |
| M-2 | `include_dir` Cargo依赖未使用 | 从 Cargo.toml 移除 |
| M-3 | `dayjs`/`@vueuse/core` npm依赖未使用 | 从 package.json 移除 |
| M-4 | 多个未使用的协议类型 | 清理或标记为reserved |
| M-5 | `fetchDeviceHistory` store action 无调用方 | 移除或实现前端历史图表 |
| M-6 | PopupBlocker.vue 表单缺 enabled 字段 | 添加 enabled 开关 |
| M-7 | 前端大量 `any` 类型 | 定义 TypeScript 接口 |
| M-8 | 无前端测试 | 添加 vitest + @vue/test-utils |
| M-9 | 3个插件不反馈执行状态 | 添加状态上报消息 |
---
## 6. 修复优先级路线图
### Phase 1: 关键链路修复 (C-1, C-2)
1. 修复 disk_encryption 全链路 (protocol -> client -> server -> migration)
2. 添加 PluginControl API (plugin_state CRUD + TCP推送)
### Phase 2: 数据完整性 (H-1, H-3, H-7)
3. 实现 Monitor 磁盘/网络指标采集
4. 添加 Popup Blocker 拦截统计上报
5. 清理 Protocol 重复类型
### Phase 3: 前端统一化 (H-4, H-5, H-6)
6. 统一 HTTP 客户端为 api.ts
7. 修复前端静默错误处理
8. 添加 PopupBlocker enabled 字段
### Phase 4: 代码清洁 (M-*)
9. 清理临时文件和未使用依赖
10. 清理未使用协议类型
### Phase 5: 新功能 (C-3)
11. 实现 print_audit 插件
12. 实现 clipboard_control 插件
---
## 7. 统计摘要
| 指标 | 数值 |
|------|------|
| 核心功能完成度 | 85.5% |
| 插件完成度 | 72.2% |
| 综合完成度 | **80.4%** |
| CRITICAL 问题 | 3 |
| HIGH 问题 | 8 |
| MEDIUM 问题 | 9 |
| 端到端通过链路 | 10/14 (71.4%) |
| Dead Code 项 | 15+ |
| "写了没接" 差距 | 5 |
| "接了没传" 差距 | 4 |
| "传了没存" 差距 | 1 |
| "存了没用" 差距 | 4 |
| "双系统不同步" 差距 | 4 |