Files
opsxsql/docs/CONFIGURATION.md
T
logan 3a6dd99633 feat: 审核规则驱动SQL检查 + db_type过滤 + Redis只读拦截 + 配置文档
1. 审核规则改为从audit_rules表动态匹配(去硬编码)
   - CreateTicket提交时查audit_rules WHERE db_type=? AND is_enabled=true
   - 正则匹配SQL,value=reject拦截,warn/review放行
   - UPDATE/DELETE无WHERE: Go RE2不支持(?!...)负向前瞻
     → 用value=where_check特殊标记+strings.Contains WHERE检测
   - 修复UPDATE/DELETE无WHERE正则(Go兼容)

2. ListAuditRules按db_type过滤
   - ghost.go: 添加c.Query('db_type') WHERE过滤
   - MySQL不显示KEYS规则,Redis不显示DROP规则

3. Redis只读命令拦截(工单提交)
   - 新增Redis只读命令白名单: GET/HGET/MGET/HGETALL/KEYS/SCAN等28个
   - 只读命令走工单→直接拦截,引导用户用查询功能

4. 补充audit_rules规则
   - Redis新增7条: DEBUG/SHUTDOWN/SCRIPT/SAVE/BGSAVE/BGREWRITEAOF/SLAVEOF/CLUSTER
   - MySQL新增1条: DROP SCHEMA
   - 总计34条规则(MySQL12/Redis11/PG7/MongoDB4)

5. docs/CONFIGURATION.md 配置系统文档
   - 三套配置体系: system_settings/audit_rules/ldap_configs
   - 每项配置: key/默认值/作用/代码引用位置
   - 未引用配置标注: executor_batch_size/executor_backup/query_max_rows_examined(待实现)
   - LDAP冗余配置: system_settings中7项ldap_*无代码引用(LDAP用独立表)

验证: 5/5审批流通过, 36/36安全测试通过, 27/27审核规则匹配正确
2026-06-03 03:17:22 +08:00

486 lines
23 KiB
Markdown
Raw 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.
# OpsxSQL 平台配置系统文档
> 本文档详细说明 OpsxSQL 平台的三套配置体系:`system_settings` 系统设置、`audit_rules` 审核规则、`ldap_configs` LDAP 配置。
>
> 最后更新:2025-06
---
## 目录
- [一、配置体系总览](#一配置体系总览)
- [二、查询控制 (query)](#二查询控制-query)
- [三、审核规则 (audit_rules)](#三审核规则-audit_rules)
- [四、数据脱敏 (data_masking)](#四数据脱敏-data_masking)
- [五、执行器 (executor)](#五执行器-executor)
- [六、Ghost / OSC 在线 DDL (ghost)](#六ghost--osc-在线-ddl-ghost)
- [七、安全策略 (security)](#七安全策略-security)
- [八、日志清理 (cleanup)](#八日志清理-cleanup)
- [九、LDAP 配置 (ldap)](#九ldap-配置-ldap)
- [十、未引用 / 待实现配置](#十未引用--待实现配置)
- [附录:数据模型](#附录数据模型)
---
## 一、配置体系总览
| 配置体系 | 存储表 | 配置项数 | 用途 |
|----------|--------|---------|------|
| 系统设置 | `system_settings` | 42 项(7 个分组) | 平台运行参数 |
| 审核规则 | `audit_rules` | 34 条(4 种 DB 类型) | SQL 提交审核拦截 |
| LDAP 配置 | `ldap_configs` | 独立 CRUD | LDAP 认证集成 |
### system_settings 分组概览
| 分组 | 配置项数 | 有效引用 | 状态 |
|------|---------|---------|------|
| `query` 查询控制 | 5 | 4 | ⚠️ `query_max_rows_examined` 未引用 |
| `security` 安全策略 | 5 | 5 | ✅ 全部有效 |
| `data_masking` 数据脱敏 | 2 | 2 | ✅ 全部有效 |
| `cleanup` 日志清理 | 4 | 4 | ✅ 全部有效 |
| `executor` 执行器 | 4 | 2 | ⚠️ `batch_size`/`backup` 未引用 |
| `ghost` 在线 DDL | 13 | 13 | ✅ 全部有效 |
| `ldap` LDAP | 9 | 0 | ❌ 全部冗余(LDAP 使用独立 `ldap_configs` 表)|
### 配置读写 API
| 操作 | 端点 | 说明 |
|------|------|------|
| 读取所有设置 | `GET /api/v1/settings` | 按 `group` 字段分组返回 |
| 批量更新设置 | `PUT /api/v1/settings` | 接收 `[{key, value}, ...]` 数组 |
| 读取审核规则 | `GET /api/v1/audit-rules?db_type=mysql` | 可按 `db_type` 过滤 |
配置均在服务启动时通过 `seedDefaultSettings()` / `seedAuditRules()` 幂等初始化。
---
## 二、查询控制 (query)
查询控制配置作用于在线查询功能(`instance_detail.go`),限制用户对数据库的查询行为。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|-----|------|--------|------|----------|
| `query_limit_max` | number | `1000` | SELECT 查询返回的最大行数,超过自动截断 | `instance_detail.go:525` |
| `query_timeout` | number | `30` | 单次查询最长执行时间(秒),超时自动终止 | `instance_detail.go:616-617` |
| `query_auto_limit` | boolean | `true` | 用户未写 LIMIT 时自动追加,防止全表扫描 | `instance_detail.go:526` |
| `query_dangerous_pattern` | boolean | `true` | 检测不带 WHERE 的 DELETE/UPDATE 等高危操作 | `instance_detail.go:540` |
| `query_max_rows_examined` | number | `1000000` | 单次查询允许扫描的最大行数 | ⚠️ **待实现** — 仅 seed 定义 |
### 作用机制
**query_limit_max** — 查询请求中的 `limit` 参数不能超过此值:
```go
maxLimit := getSettingInt("query_limit_max", 1000)
if input.Limit <= 0 {
input.Limit = maxLimit
}
// ... 后续截断到 maxLimit
```
**query_auto_limit** — 当用户未指定 LIMIT 时,自动追加平台默认上限:
```go
autoLimit := getSetting("query_auto_limit", "true") == "true"
```
**query_timeout** — 使用 Go `context.WithTimeout` 实现硬超时:
```go
timeoutSec := getSettingInt("query_timeout", 30)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutSec)*time.Second)
```
**query_dangerous_pattern** — 在执行前检测 SQL 中是否包含高危操作关键字:
```go
if getSetting("query_dangerous_pattern", "true") == "true" {
for _, pat := range []string{"DELETE FROM", "UPDATE ", "DROP ", "TRUNCATE", "ALTER ", "RENAME "} {
// ... 检测并拦截
}
}
```
---
## 三、审核规则 (audit_rules)
### 概述
审核规则存储在 `audit_rules` 表中,在 **工单提交时**(`CreateTicket`)自动触发检查。系统预置 34 条规则,覆盖 MySQL、PostgreSQL、Redis、MongoDB 四种数据库类型。
### 匹配机制
```
CreateTicket → 加载 audit_rules WHERE db_type=? AND is_enabled=true
→ 对每条 SQL 语句逐一匹配
→ Pattern 正则匹配 ⟶ value=where_check 时使用字符串检测
```
**正则匹配流程**(`ticket.go:299-303`):
```go
for _, rule := range rules {
matched, _ := regexp.MatchString(*rule.Pattern, checkStmt)
if matched { /* 规则命中 */ }
}
```
**WHERE 特殊检测**(`ticket.go:305-314`):
由于 Go 的 RE2 正则引擎不支持负向前瞻(negative lookahead),无法用正则"匹配不含 WHERE 的 DELETE"。因此采用两步检测:
1. 正则匹配 `DELETE FROM` / `UPDATE ... SET` 等基础模式
2. 若规则 `value` 字段为 `"where_check"`,则用 `strings.Contains(upperSQL, "WHERE")` 判断是否包含 WHERE 子句
3. 包含 WHERE → 跳过(安全);不包含 → 拦截
### 规则字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | string | 规则名称 |
| `description` | text | 规则描述 |
| `rule_type` | string | 规则类型:DDL / DML / DCL / DQL / performance / security |
| `severity` | string | 严重级别:error / warning / info |
| `db_type` | string | 目标数据库类型:mysql / postgresql / redis / mongodb |
| `pattern` | text | 正则表达式(RE2 语法) |
| `is_enabled` | boolean | 是否启用 |
| `message` | string(500) | 命中时的提示消息 |
| `value` | string(255) | 处理方式:`reject`(拦截) / `review`(需审核) / `warn`(警告) / `where_check`(WHERE检测) |
| `code` | string(50) | 规则编码(预留) |
| `config_json` | text | 扩展配置 JSON(预留) |
### MySQL 审核规则(12 条)
| 规则名称 | 类型 | 严重级别 | Pattern | Value | 说明 |
|----------|------|---------|---------|-------|------|
| 禁止 DROP TABLE | DDL | error | `(?i)^\s*DROP\s+TABLE` | reject | 防止数据永久丢失 |
| 禁止 DROP DATABASE | DDL | error | `(?i)^\s*DROP\s+DATABASE` | reject | 禁止删库 |
| 禁止 TRUNCATE TABLE | DDL | error | `(?i)^\s*TRUNCATE\s+TABLE?` | reject | 请用 DELETE 逐批删除 |
| ALTER TABLE 需审核 | DDL | warning | `(?i)^\s*ALTER\s+TABLE` | review | 需审批后执行 |
| 禁止 DELETE 无 WHERE | DML | error | `(?i)^\s*DELETE\s+FROM?\s+\S+\s*$` | reject | 必须包含 WHERE 条件 |
| 禁止 UPDATE 无 WHERE | DML | error | `(?i)^\s*UPDATE\s+\S+\s+SET\s+.*\s*$` | reject | 必须包含 WHERE 条件 |
| SELECT * 建议 | DQL | info | `(?i)^\s*SELECT\s+\*\s+FROM` | warn | 建议明确指定查询字段 |
| INSERT 需指定列 | DML | warning | `(?i)^\s*INSERT\s+INTO\s+\S+\s+VALUES` | review | 应明确指定列名 |
| 禁止 GRANT ALL | DCL | error | `(?i)^\s*GRANT\s+ALL` | reject | 禁止授予全部权限 |
| 大表变更警告 | performance | warning | _(空 pattern)_ | warn | 影响行数大时警告 |
| 禁止不带 LIMIT 的 DELETE | DML | warning | `(?i)^\s*DELETE\s+FROM\s+\S+\s+WHERE` | warn | 建议添加 LIMIT 分批删除 |
> **注意**:seed 中 MySQL 预置 12 条,实际按 `len(allRules["mysql"])` 计算。上表列出 11 条有明确 pattern 的规则,另含 1 条 "大表变更警告"(无 pattern,作为提示性规则存在)。
### PostgreSQL 审核规则(7 条)
| 规则名称 | 类型 | 严重级别 | Value | 说明 |
|----------|------|---------|-------|------|
| 禁止 DROP TABLE | DDL | error | reject | 同 MySQL |
| 禁止 DROP DATABASE | DDL | error | reject | 同 MySQL |
| 禁止 DELETE 无 WHERE | DML | error | reject | 同 MySQL |
| 禁止 UPDATE 无 WHERE | DML | error | reject | 同 MySQL |
| ALTER TABLE 需审核 | DDL | warning | review | 同 MySQL |
| SELECT * 建议 | DQL | info | warn | 同 MySQL |
| 禁止 GRANT ALL | DCL | error | reject | 同 MySQL |
### Redis 审核规则(4 条)
| 规则名称 | 类型 | 严重级别 | Pattern | Value | 说明 |
|----------|------|---------|---------|-------|------|
| 禁止 FLUSHALL | DDL | error | `(?i)^FLUSHALL` | reject | 禁止清空所有数据 |
| 禁止 FLUSHDB | DDL | error | `(?i)^FLUSHDB` | reject | 清空数据库需审批 |
| 禁止 CONFIG | security | error | `(?i)^CONFIG\s` | reject | 配置修改需走审批 |
| KEYS 命令警告 | performance | error | `(?i)^KEYS\s` | reject | 生产环境禁止 KEYS,请使用 SCAN |
### MongoDB 审核规则(4 条)
| 规则名称 | 类型 | 严重级别 | Pattern | Value | 说明 |
|----------|------|---------|---------|-------|------|
| 禁止 dropDatabase | DDL | error | `dropDatabase` | reject | 禁止删除数据库 |
| 禁止 drop 集合 | DDL | error | `(?i)\.drop\(\)` | reject | 禁止删除集合 |
| remove 需带条件 | DML | error | `(?i)remove\(\s*\)` | reject | remove 必须带查询条件 |
| updateMany 需审核 | DML | warning | `(?i)updateMany` | review | 批量更新需审批 |
---
## 四、数据脱敏 (data_masking)
数据脱敏功能作用于在线查询返回结果,自动将敏感字段的内容替换为 `***`。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|-----|------|--------|------|----------|
| `data_masking_enabled` | boolean | `true` | 全局脱敏开关 | `instance_detail.go:1522-1525` |
| `data_masking_sensitive_fields` | string | _(见下方)_ | 全局敏感字段列表(逗号分隔) | `instance_detail.go:1531-1534` |
**默认敏感字段列表**:
```
mobile, concat_mobile, email_alias, email, password, ga_key,
private_key, secret, secret_key, key_snow, telephone, username,
real_name, token, two_factor_secret, content, phone
```
### 作用机制
`applyDataMasking()` 函数(`instance_detail.go:1520`)执行以下逻辑:
1. 读取 `data_masking_enabled`,若非 `true` 则跳过
2. 读取 `data_masking_sensitive_fields`,按逗号拆分为字段名列表
3. 合并实例级别 `instance.mask_fields` 的字段
4. 遍历查询结果的每一行每一列,若列名(不区分大小写)匹配敏感字段,则将值替换为 `***`
**字段匹配方式**:列名包含(contains)敏感字段名即匹配,不区分大小写。
**优先级**:全局敏感字段 ∪ 实例级 `mask_fields`,两者合并生效。
---
## 五、执行器 (executor)
执行器配置控制工单中 SQL 语句的实际执行行为。
| Key | 类型 | 默认值 | 说明 | 引用位置 | 状态 |
|-----|------|--------|------|----------|------|
| `executor_timeout` | number | `300` | SQL 执行的最大等待时间(秒) | `ticket.go:725,766` | ✅ 有效 |
| `executor_dry_run` | boolean | `true` | 执行前先 EXPLAIN 验证 SQL 语法 | `ticket.go:770` | ✅ 有效 |
| `executor_batch_size` | number | `100` | DML 批量执行时每批的行数 | _(无)_ | ⚠️ 待实现 |
| `executor_backup` | boolean | `true` | DML 执行前自动备份受影响数据 | _(无)_ | ⚠️ 待实现 |
### 作用机制
**executor_timeout** — 为每个 SQL 语句创建带超时的 context:
```go
// OSC (gh-ost) 路径
execTimeout := getSettingInt("executor_timeout", 300)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(execTimeout)*time.Second)
// 原生执行路径
execTimeout := getSettingInt("executor_timeout", 300)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(execTimeout)*time.Second)
```
**executor_dry_run** — 对 DDL 语句执行 EXPLAIN 预检查:
```go
if getSetting("executor_dry_run", "true") == "true" {
ddlPrefixes := []string{"CREATE", "ALTER", "DROP", "TRUNCATE", "RENAME"}
// 对每条 DDL 语句执行 EXPLAIN,语法错误则拦截
}
```
---
## 六、Ghost / OSC 在线 DDL (ghost)
Ghost 配置控制 [gh-ost](https://github.com/github/gh-ost) 在线 DDL 变更工具的默认参数。共 13 项配置,全部在 `ghost.go` 的 `applyGhostSettings()` 函数和 OSC 触发逻辑中引用。
### 基本设置
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|-----|------|--------|------|----------|
| `ghost_enabled` | boolean | `false` | 启用 gh-ost 在线 DDL 变更工具 | `ticket.go` (OSC 触发判断) |
| `ghost_path` | string | `gh-ost` | gh-ost 二进制文件路径 | `ghost.go` (任务创建) |
| `ghost_default_mode` | string | `dry_run` | 默认执行模式:`dry_run`(预演) / `execute`(直接执行) | `ghost.go` (任务创建) |
| `ghost_osc_priority` | string | `native_first` | OSC 优先级策略:`native_first` / `ghost_first` / `ghost_only` | `ticket.go` (OSC 触发判断) |
| `ghost_env_mode` | string | `development` | 环境模式:`development` / `staging` / `production` | `ghost.go` (任务创建) |
| `ghost_cloud_type` | string | `self_hosted` | 部署类型:`self_hosted` / `rds` / `cloud` | `ghost.go` (任务创建) |
### 自动触发
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|-----|------|--------|------|----------|
| `ghost_auto_trigger_rows` | number | `10` | 表行数超过此阈值(万行)自动推荐使用 OSC | `ticket.go` (大表检测) |
| `ghost_auto_trigger_ddl` | string | `ADD COLUMN,MODIFY COLUMN,ADD INDEX` | 自动触发 OSC 的 DDL 操作类型列表(逗号分隔) | `ticket.go` (DDL 类型匹配) |
### 性能调优
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|-----|------|--------|------|----------|
| `ghost_default_chunk_size` | number | `1000` | 每次拷贝的行数 | `ghost.go:387` (`applyGhostSettings`) |
| `ghost_max_load` | string | `Threads_running=25` | 超过此负载暂停拷贝 | `ghost.go:391` |
| `ghost_critical_load` | string | `Threads_running=50` | 超过此负载立即停止 | `ghost.go:395` |
| `ghost_allow_on_master` | boolean | `true` | 是否允许直接在主库运行 gh-ost | `ghost.go:403` |
| `ghost_max_lag_millis` | number | `1500` | 从库复制延迟超过此值(ms)暂停拷贝 | `ghost.go:399` |
### 作用机制
**自动触发 OSC 流程**(`ticket.go`):
1. 检查 `ghost_enabled` 是否启用
2. 检查 SQL 是否为 ALTER TABLE 类型
3. 检查 DDL 操作类型是否在 `ghost_auto_trigger_ddl` 列表中
4. 检查目标表行数是否超过 `ghost_auto_trigger_rows`(万)
5. 根据 `ghost_osc_priority` 决定使用原生 ALTER 还是 gh-ost
**参数注入流程**(`ghost.go:applyGhostSettings`):
```go
func applyGhostSettings(task *ghost.GhOstTask) {
task.ChunkSize = getSettingInt("ghost_default_chunk_size", 1000)
task.MaxLoad = getSetting("ghost_max_load", "")
task.CriticalLoad = getSetting("ghost_critical_load", "")
task.MaxLagMillis = getSettingInt("ghost_max_lag_millis", 1500)
task.AllowOnMaster = getSetting("ghost_allow_on_master", "true") == "true"
}
```
---
## 七、安全策略 (security)
安全策略配置控制用户登录和认证行为,全部在 `auth.go`(handler)和 `middleware/auth.go` 中引用。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|-----|------|--------|------|----------|
| `login_max_attempts` | number | `5` | 连续登录失败达到此次数后锁定账号 | `auth.go:34,365` |
| `login_lockout_minutes` | number | `30` | 账号锁定后的持续时长(分钟) | `auth.go:35,366` |
| `password_min_length` | number | `8` | 用户密码的最短字符数 | `auth.go` (密码校验) |
| `password_require_complex` | boolean | `true` | 要求密码包含大小写字母、数字和特殊字符 | `auth.go` (密码校验) |
| `session_timeout_hours` | number | `24` | JWT Token 有效期(小时) | `middleware/auth.go:20` |
### 作用机制
**登录锁定流程**(`auth.go`):
1. 登录时检查 `login_max_attempts` 和 `login_lockout_minutes`
2. 密码错误时调用 `handleFailedLogin()`,递增 `FailedLoginAttempts`
3. 达到 `login_max_attempts` 时,设置 `LockedUntil = now + lockout_minutes`
4. 账号锁定期间拒绝登录,返回剩余锁定时间
**会话超时**(`middleware/auth.go`):
```go
func getSessionTimeoutHours() int {
// 从 system_settings 读取 session_timeout_hours
// 用于 JWT Token 的过期时间计算
}
```
---
## 八、日志清理 (cleanup)
清理配置控制各类日志和工单数据的自动保留期限。全部在 `ghost.go`(清理定时任务)和 `main.go`(seed)中引用。
| Key | 类型 | 默认值 | 说明 | 引用位置 |
|-----|------|--------|------|----------|
| `ticket_retention_days` | number | `180` | 超过此天数的已完成/已关闭工单将被清理 | `ghost.go` (清理任务) |
| `audit_log_retention_days` | number | `365` | 超过此天数的审计日志将被清理 | `ghost.go` (清理任务) |
| `query_history_retention_days` | number | `90` | 超过此天数的查询历史将被清理 | `ghost.go` (清理任务) |
| `slow_log_retention_days` | number | `180` | 超过此天数的慢查询日志将被清理 | `ghost.go` (清理任务) |
---
## 九、LDAP 配置 (ldap)
### system_settings 中的 LDAP 配置(⚠️ 冗余)
以下 9 项配置存在于 `system_settings` 表的 `ldap` 分组中,但 **全部未被业务代码引用**。LDAP 功能使用独立的 `ldap_configs` 表进行管理。
| Key | 类型 | 默认值 | 说明 | 状态 |
|-----|------|--------|------|------|
| `ldap_host` | string | `8.217.205.92` | LDAP 服务器地址 | ❌ 冗余 |
| `ldap_port` | string | `389` | LDAP 端口 | ❌ 冗余 |
| `ldap_use_ssl` | boolean | `false` | 启用 LDAPS (SSL/TLS) | ❌ 冗余 |
| `ldap_bind_dn` | string | `cn=admin,dc=opsx,dc=vip` | 管理员 DN | ❌ 冗余 |
| `ldap_base_dn` | string | `dc=opsx,dc=vip` | Base DN | ❌ 冗余 |
| `ldap_user_filter` | string | `(objectClass=inetOrgPerson)` | 用户过滤器 | ❌ 冗余 |
| `ldap_uid_attr` | string | `uid` | UID 属性 | ❌ 冗余 |
| `ldap_mail_attr` | string | `mail` | 邮箱属性 | ❌ 冗余 |
| `ldap_cn_attr` | string | `cn` | 显示名属性 | ❌ 冗余 |
### ldap_configs 独立表(实际使用)
LDAP 功能通过独立的 `ldap_configs` 表管理,提供完整的 CRUD 功能:
| 功能 | API 端点 | 说明 |
|------|----------|------|
| 配置 CRUD | `/api/v1/ldap-configs` | 增删改查 LDAP 服务器配置 |
| 测试连接 | `/api/v1/ldap-configs/:id/test` | 验证 LDAP 服务器连通性 |
| OU 管理 | `/api/v1/ldap-configs/:id/ous` | 管理 LDAP 组织单元 |
| 用户导入 | `/api/v1/ldap-configs/:id/import` | 从 LDAP 导入用户到平台 |
> **建议**:后续版本可清理 `system_settings` 中 `ldap` 分组的冗余配置项,避免维护混淆。
---
## 十、未引用 / 待实现配置
以下配置项在 `seed.go` 中定义,但在业务代码中 **无实际引用**,标注为"待实现":
| Key | 分组 | 默认值 | 预期功能 | 状态 |
|-----|------|--------|----------|------|
| `executor_batch_size` | executor | `100` | DML 批量执行时每批的行数 | ⚠️ 待实现 |
| `executor_backup` | executor | `true` | DML 执行前自动备份受影响数据 | ⚠️ 待实现 |
| `query_max_rows_examined` | query | `1000000` | 单次查询允许扫描的最大行数 | ⚠️ 待实现 |
| `ldap_host` | ldap | `8.217.205.92` | LDAP 服务器地址 | ❌ 冗余(使用 ldap_configs 表) |
| `ldap_port` | ldap | `389` | LDAP 端口 | ❌ 冗余 |
| `ldap_use_ssl` | ldap | `false` | 启用 LDAPS | ❌ 冗余 |
| `ldap_bind_dn` | ldap | `cn=admin,dc=opsx,dc=vip` | 管理员 DN | ❌ 冗余 |
| `ldap_base_dn` | ldap | `dc=opsx,dc=vip` | Base DN | ❌ 冗余 |
| `ldap_user_filter` | ldap | `(objectClass=inetOrgPerson)` | 用户过滤器 | ❌ 冗余 |
| `ldap_uid_attr` | ldap | `uid` | UID 属性 | ❌ 冗余 |
| `ldap_mail_attr` | ldap | `mail` | 邮箱属性 | ❌ 冗余 |
| `ldap_cn_attr` | ldap | `cn` | 显示名属性 | ❌ 冗余 |
**汇总**:
- ⚠️ **待实现**:3 项(`executor_batch_size`、`executor_backup`、`query_max_rows_examined`)
- ❌ **冗余**:9 项(`ldap` 分组全部,LDAP 使用独立 `ldap_configs` 表)
---
## 附录:数据模型
### system_settings 表结构
```go
type SystemSetting struct {
ID int `gorm:"primaryKey" json:"id"`
Key string `gorm:"size:100;not null" json:"key"` // 唯一配置键
Value string `gorm:"type:text;not null" json:"value"` // 当前值
ValueType string `gorm:"size:20;not null" json:"value_type"` // number / boolean / string
Group string `gorm:"size:50;not null" json:"group"` // 分组名
Label string `gorm:"size:100;not null" json:"label"` // 前端显示名
Desc *string `gorm:"type:text" json:"description"` // 配置说明
DefaultValue *string `gorm:"type:text" json:"default_value"` // 默认值
SortOrder int `gorm:"not null" json:"sort_order"` // 组内排序
UpdatedAt *time.Time `json:"updated_at"`
}
```
### audit_rules 表结构
```go
type AuditRule struct {
ID int `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:100;not null" json:"name"` // 规则名称
Desc *string `gorm:"type:text" json:"description"` // 规则描述
RuleType string `gorm:"size:50;not null" json:"rule_type"` // DDL/DML/DCL/DQL/performance/security
Severity *string `gorm:"size:20" json:"severity"` // error/warning/info
DBType *string `gorm:"size:20" json:"db_type"` // mysql/postgresql/redis/mongodb
Pattern *string `gorm:"type:text" json:"pattern"` // RE2 正则表达式
IsEnabled *bool ` json:"is_enabled"` // 是否启用
Message string `gorm:"size:500;not null" json:"message"` // 命中提示消息
Value *string `gorm:"size:255" json:"value"` // reject/review/warn/where_check
Code *string `gorm:"size:50" json:"code"` // 规则编码(预留)
ConfigJSON *string `gorm:"type:text;column:config_json" json:"config_json"` // 扩展配置(预留)
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
```
### 配置读取辅助函数
```go
// ghost.go — 读取字符串配置
func getSetting(key, fallback string) string {
var s model.SystemSetting
if model.DB.Where("`key` = ?", key).Take(&s).Error == nil && s.Value != "" {
return s.Value
}
return fallback
}
// ghost.go — 读取整数配置
func getSettingInt(key string, fallback int) int {
// 读取字符串并 strconv.Atoi,失败返回 fallback
}
```
---
> **文档维护说明**:新增配置项时,需同步更新 `seed.go` 的 `seedDefaultSettings()` / `seedAuditRules()` 函数及本文档。