feat: harden data access and simplify user management
This commit is contained in:
1 parent
3dd5731751
commit
adb780bc82
51 files changed
+3239
-2121
No files matched your search
@@ -35,8 +35,8 @@ http://localhost:8102/docs
|
||||
| `/v1/openapi/knowledge-qa/query` | `POST` | 百姓惠智能客服第三方问答接口 |
|
||||
| `/v1/admin/travel/customer-service-query` | `POST` | 兼容旧版外部问答接口 |
|
||||
| `/v1/admin/super-agent/run` | `POST` | Super Agent 任务 |
|
||||
| `/v1/admin/roles` | `GET/POST` | 角色管理 |
|
||||
| `/v1/admin/users` | `GET/POST` | 用户管理 |
|
||||
| `/v1/admin/users` | `GET/POST` | 用户管理;仅接受“数据管理”或“数据查看”权限 |
|
||||
| `/v1/admin/users/{user_id}` | `PATCH` | 修改权限、状态或重置密码;用户不做物理删除 |
|
||||
|
||||
## 登录示例
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ flowchart TB
|
||||
| `admin-web/src/panels/plaza/` | 数据大屏、业务问答、图谱浏览和 Super Agent |
|
||||
| `admin-web/src/panels/data-platform/` | 项目数据库、表、记录、CSV 与 SQL 工作区 |
|
||||
| `admin-web/src/panels/modeling/` | 当前项目 Schema 的只读展示 |
|
||||
| `admin-web/src/panels/system/` | 用户、权限、Agent 任务和调用日志 |
|
||||
| `admin-web/src/panels/system/` | 简化用户管理(数据管理/数据查看)和接口中心 |
|
||||
|
||||
## 数据层
|
||||
|
||||
|
||||
+165
-17
@@ -39,7 +39,9 @@ docker compose -f docker-compose.yml -f docker-compose.server.yml up -d --build
|
||||
2. 创建 PostgreSQL 数据卷。
|
||||
3. PostgreSQL 初始化脚本恢复 `snapshots/postgres/kg_admin_new2.dump`。
|
||||
4. `falkordb-seed` 把 `snapshots/falkordb/dump.rdb` 写入 FalkorDB 数据卷。
|
||||
5. FastAPI 服务等待 PostgreSQL 和 FalkorDB 健康后启动。
|
||||
5. 初始化独立 MySQL 数据中心与账号签发用户。
|
||||
6. 启动只允许数据库端口转发的 DBeaver SSH 网关。
|
||||
7. FastAPI 服务等待 PostgreSQL、MySQL、FalkorDB 与 SSH 网关健康后启动。
|
||||
|
||||
## 常用命令
|
||||
|
||||
@@ -61,13 +63,16 @@ docker compose logs -f api
|
||||
docker compose down
|
||||
```
|
||||
|
||||
停止并删除数据卷,下一次启动将重新恢复快照:
|
||||
仅在本地开发环境停止并删除数据卷,下一次启动将重新恢复快照:
|
||||
|
||||
```bash
|
||||
docker compose down -v
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
生产服务器禁止执行 `docker compose down -v`。生产 MySQL 使用独立磁盘绑定目录,
|
||||
虽然该命令不会删除这个目录,但会删除 PostgreSQL、FalkorDB 等其他 Docker 数据卷。
|
||||
|
||||
## 无 sudo 服务器的 rootless Docker 启动
|
||||
|
||||
如果服务器账号不能使用 `sudo`,并且 `loginctl show-user <用户> -p Linger` 显示 `Linger=no`,用户级 `docker.service` 可能会在 SSH 退出后停止。此时可以使用项目脚本把 rootless Docker 的 socket 固定到用户目录:
|
||||
@@ -111,10 +116,111 @@ HTTPS 443 端口访问,不再直接开放 8102。可复制
|
||||
|
||||
- `443/tcp`:所有合法业务来源;
|
||||
- `22/tcp`:仅运维固定 IP 或 VPN 网段;
|
||||
- `2222/tcp`:仅 DBeaver 数据管理员固定 IP 或 VPN 网段;
|
||||
- `80/tcp`:仅用于跳转 HTTPS 或证书签发。
|
||||
|
||||
严禁向公网开放 `8102`、`3307`、`5433`、`6380` 和 `3002`。
|
||||
|
||||
## 生产 MySQL 持久化存储(首次部署必做)
|
||||
|
||||
生产环境采用两层存储,职责不能混用:
|
||||
|
||||
1. MySQL 运行目录使用服务器独立的本地块存储(例如云硬盘/SSD 挂载到
|
||||
`/mnt/sdr`),不放在代码仓库、容器可写层、临时目录、NFS 或对象存储中;
|
||||
2. 加密逻辑备份写到另一个目录,并继续自动同步到异地对象存储或另一台服务器。
|
||||
|
||||
服务器运维人员先在云平台挂载并格式化数据盘、配置 `/etc/fstab`,确认服务器重启后
|
||||
仍能自动挂载。项目脚本不会格式化磁盘,也不会自动搬迁旧数据。设置 `.env`:
|
||||
|
||||
```dotenv
|
||||
MYSQL_STORAGE_MOUNT=/mnt/sdr
|
||||
MYSQL_STORAGE_ID=prod-mysql-storage-2026-001
|
||||
MYSQL_DATA_DIR=/mnt/sdr/nianxx/mysql
|
||||
MYSQL_CONTAINER_UID=999
|
||||
MYSQL_CONTAINER_GID=999
|
||||
DATA_BACKUP_ROOT=/mnt/backup/nianxx/mysql
|
||||
DATA_BACKUP_RETENTION_DAYS=30
|
||||
DATA_BACKUP_PASSPHRASE_FILE=/etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
DATA_BACKUP_ENABLED=false
|
||||
```
|
||||
|
||||
脚本读取当前进程环境,因此把 `.env` 中以下非敏感路径变量一并导出后再准备目录
|
||||
(Linux 服务器):
|
||||
|
||||
```bash
|
||||
export MYSQL_STORAGE_MOUNT=/mnt/sdr
|
||||
export MYSQL_STORAGE_ID=prod-mysql-storage-2026-001
|
||||
export MYSQL_DATA_DIR=/mnt/sdr/nianxx/mysql
|
||||
export DATA_BACKUP_ROOT=/mnt/backup/nianxx/mysql
|
||||
export MYSQL_CONTAINER_UID=999
|
||||
export MYSQL_CONTAINER_GID=999
|
||||
sudo -E ./scripts/prepare_mysql_production_storage.sh
|
||||
```
|
||||
|
||||
该脚本会确认 `/mnt/sdr` 确实是独立、可写、本地持久化挂载,写入磁盘身份标识,并
|
||||
设置 MySQL 容器 UID/GID 权限。如果挂载丢失、磁盘身份不一致、目录出现半初始化
|
||||
数据,`mysql-storage-guard` 会阻止 MySQL 启动,避免系统在错误的空目录中悄悄创建
|
||||
一个新数据库。存储标识位于挂载根目录,MySQL 数据目录在首次初始化前保持为空。
|
||||
|
||||
先只启动 MySQL:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.server.yml up -d mysql
|
||||
docker compose -f docker-compose.yml -f docker-compose.server.yml ps mysql mysql-storage-guard
|
||||
```
|
||||
|
||||
然后安装每日加密备份。备份服务默认使用执行 `sudo` 的服务器账号;该账号必须有
|
||||
Docker 权限,并独占读取口令文件:
|
||||
|
||||
```bash
|
||||
sudo install -d -m 0750 -o root -g "$(id -gn)" /etc/travel-kg/secrets
|
||||
sudo touch /etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
sudo chown "$USER:$(id -gn)" /etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
sudo chmod 600 /etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
openssl rand -base64 48 > /etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
|
||||
export DATA_BACKUP_PASSPHRASE_FILE=/etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
export DATA_BACKUP_RETENTION_DAYS=30
|
||||
sudo -E ./scripts/install_mysql_backup_systemd.sh
|
||||
```
|
||||
|
||||
安装程序会立即执行并验证第一份备份,成功后启用每天的 systemd timer。确认备份已
|
||||
同步到异地存储后,把 `.env` 中 `DATA_BACKUP_ENABLED=true`,再启动完整生产服务:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.server.yml up -d --build
|
||||
```
|
||||
|
||||
生产覆盖配置把 MySQL 主机端口硬编码绑定到 `127.0.0.1`;即使误设
|
||||
`MYSQL_HOST_BIND=0.0.0.0` 也不会将 MySQL 暴露到公网。
|
||||
|
||||
### 从原 Docker named volume 迁移
|
||||
|
||||
已有数据不能通过重新初始化获得。先在旧 MySQL 仍运行时完成加密备份,再停写并冷
|
||||
拷贝;以下示例中的卷名要先通过 `docker volume ls` 和 `docker volume inspect`
|
||||
核实:
|
||||
|
||||
```bash
|
||||
export DATA_BACKUP_ROOT=/mnt/backup/nianxx/mysql
|
||||
export DATA_BACKUP_PASSPHRASE_FILE=/etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
export DATA_BACKUP_RETENTION_DAYS=30
|
||||
./scripts/backup_mysql_encrypted.sh
|
||||
|
||||
docker compose stop api dbeaver-gateway mysql
|
||||
sudo -E ./scripts/prepare_mysql_production_storage.sh
|
||||
docker run --rm \
|
||||
-v travel-knowledge-graph_mysql-data:/from:ro \
|
||||
-v /mnt/sdr/nianxx/mysql:/to \
|
||||
alpine:3.22 sh -c 'cd /from && tar cf - . | tar xpf - -C /to'
|
||||
|
||||
docker compose -f docker-compose.yml -f docker-compose.server.yml up -d mysql
|
||||
docker compose -f docker-compose.yml -f docker-compose.server.yml exec -T mysql sh -c \
|
||||
'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysqlcheck -uroot --all-databases'
|
||||
```
|
||||
|
||||
完成表数量、记录数量和业务抽样核对前,不要删除原 Docker volume。若源目录不是完整
|
||||
MySQL 数据目录,准备脚本和启动守卫都会拒绝继续。
|
||||
|
||||
## 端口配置
|
||||
|
||||
可以在启动时覆盖端口:
|
||||
@@ -138,6 +244,8 @@ docker compose up -d --build
|
||||
| `POSTGRES_PORT` | `5433` | PostgreSQL 映射端口 |
|
||||
| `MYSQL_HOST_BIND` | `127.0.0.1` | MySQL 只绑定服务器本机,DBeaver 经 SSH 隧道接入 |
|
||||
| `MYSQL_PORT` | `3307` | MySQL 服务器本机映射端口,不向公网开放 |
|
||||
| `DATA_MYSQL_SSH_BIND` | `127.0.0.1` | DBeaver 专用 SSH 网关监听地址;远程部署必须显式绑定可达网卡并配防火墙白名单 |
|
||||
| `DATA_MYSQL_SSH_PORT` | `2222` | DBeaver 专用 SSH 网关端口,不提供服务器终端 |
|
||||
| `FALKORDB_HOST_BIND` | `127.0.0.1` | FalkorDB Redis 协议只绑定服务器本机 |
|
||||
| `FALKORDB_PORT` | `6380` | FalkorDB Redis 协议端口 |
|
||||
| `FALKORDB_BROWSER_HOST_BIND` | `127.0.0.1` | FalkorDB Browser 只绑定服务器本机 |
|
||||
@@ -161,9 +269,11 @@ cp .env.example .env
|
||||
AUTH_SECRET=换成32位以上随机字符串
|
||||
AUTH_DEFAULT_PASSWORD=换成12位以上后台管理员密码
|
||||
INTERFACE_API_SECRET=与AUTH_SECRET不同的32位以上随机字符串
|
||||
MYSQL_ACCESS_BROKER_PASSWORD=至少24位独立随机字符串
|
||||
INGEST_API_KEYS=至少24位的外部系统接口Key
|
||||
CORS_ALLOWED_ORIGINS=https://你的后台域名
|
||||
TRUSTED_HOSTS=你的后台域名
|
||||
DATA_MYSQL_SSH_HOST=你的服务器域名或可达IP
|
||||
LLM_API_BASE=你的OpenAI兼容模型地址
|
||||
LLM_API_KEY=你的模型Key
|
||||
```
|
||||
@@ -177,10 +287,16 @@ LLM_API_KEY=你的模型Key
|
||||
| `DB_SCHEMA` | 默认 `kg_admin_new2` |
|
||||
| `DB_MIGRATIONS_ENABLED` | 快照部署默认 `false` |
|
||||
| `DATA_MYSQL_SSH_HOST`、`DATA_MYSQL_SSH_PORT` | DBeaver SSH 标签页使用的服务器地址和 SSH 端口 |
|
||||
| `DATA_MYSQL_SSH_BIND`、`DATA_MYSQL_SSH_USERNAME` | 专用 SSH 网关监听地址与固定隧道用户;默认用户为 `dbeaver` |
|
||||
| `MYSQL_ACCESS_BROKER_USER`、`MYSQL_ACCESS_BROKER_PASSWORD` | 接口中心签发/撤销个人 MySQL 账号使用的独立服务凭证,不得与 `data_center` 或 `root` 共用 |
|
||||
| `DATA_MYSQL_ADMIN_HOST`、`DATA_MYSQL_ADMIN_PORT` | DBeaver Main 标签页使用的隧道远端 MySQL 地址,默认 `127.0.0.1:3307` |
|
||||
| `DATA_MYSQL_AUDIT_ENABLED` | 只有数据库审计真实启用后才设置为 `true` |
|
||||
| `DATA_SQL_CONSOLE_WRITE_ENABLED` | 默认 `false`,生产 SQL 控制台保持只读 |
|
||||
| `DATA_BACKUP_ENABLED` | 自动备份任务真实部署后才设置为 `true` |
|
||||
| `MYSQL_STORAGE_MOUNT`、`MYSQL_STORAGE_ID` | 独立数据盘挂载点及其唯一身份标识,生产必填 |
|
||||
| `MYSQL_DATA_DIR` | 独立数据盘内的 MySQL 运行目录,不能位于代码仓库内 |
|
||||
| `DATA_BACKUP_ROOT` | 代码仓库和 MySQL 运行目录之外的加密备份目录 |
|
||||
| `DATA_BACKUP_ENABLED` | 首次备份与自动任务验证成功后才设置为 `true`,生产为必填真值 |
|
||||
| `DATA_BACKUP_RETENTION_DAYS` | 本机加密备份保留天数,允许 7–3650 天 |
|
||||
| `DATA_BACKUP_PASSPHRASE_FILE` | 仓库外的备份加密口令文件,权限必须为 600 |
|
||||
| `FALKORDB_HOST` | Docker 内默认 `falkordb` |
|
||||
| `FALKORDB_GRAPH` | 默认业务图 `guiyang_new2` |
|
||||
@@ -197,6 +313,40 @@ LLM_API_KEY=你的模型Key
|
||||
| `TRAVEL_DELIVERY_ROOT` | POI 交付 CSV 目录,仅运行采集/增强脚本时需要 |
|
||||
| `TRAVEL_KG_EXPORT_ROOT` | 采集/构图脚本导出目录 |
|
||||
|
||||
## DBeaver 远程管理接入
|
||||
|
||||
本地模拟服务器环境:
|
||||
|
||||
```env
|
||||
DATA_MYSQL_SSH_HOST=localhost
|
||||
DATA_MYSQL_SSH_BIND=127.0.0.1
|
||||
DATA_MYSQL_SSH_PORT=2222
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose up -d --build mysql dbeaver-gateway api
|
||||
```
|
||||
|
||||
打开 `/admin/system/interfaces`,页面直接提供 DBeaver 管理接入,由页面生成管理员
|
||||
个人私钥、MySQL 用户名和一次性密码。DBeaver 的 SSH 标签页连接
|
||||
`localhost:2222`、用户 `dbeaver`;Main 标签页固定使用 `127.0.0.1:3307`。
|
||||
|
||||
服务器部署时把 `DATA_MYSQL_SSH_HOST` 改为服务器域名。如果管理员电脑需要通过
|
||||
网络连接,把 `DATA_MYSQL_SSH_BIND` 设置为服务器内网 IP;只有确实需要公网接入时
|
||||
才使用 `0.0.0.0`,并在云安全组和主机防火墙中将 `2222/tcp` 限定到管理员固定 IP
|
||||
或 VPN 网段。MySQL 的 `3307/tcp` 始终保持回环绑定。
|
||||
|
||||
升级已有 MySQL 数据卷后,初始化脚本不会自动重跑,需要执行一次:
|
||||
|
||||
```bash
|
||||
./scripts/enable_managed_dbeaver_access.sh
|
||||
docker compose up -d --build dbeaver-gateway api
|
||||
```
|
||||
|
||||
专用 SSH 用户不能打开终端或 SFTP,只能转发到 MySQL;每位管理员的公钥与 MySQL
|
||||
账号均可在接口中心一键撤销。完整私钥和 MySQL 密码只展示一次;DBeaver 首次
|
||||
连接时必须核对页面显示的服务器 SSH 主机指纹。
|
||||
|
||||
## 百姓惠智能客服接口
|
||||
|
||||
给外部系统对接时,只开放这个接口即可:
|
||||
@@ -232,26 +382,24 @@ curl https://你的域名/v1/openapi/knowledge-qa/query \
|
||||
|
||||
## MySQL 加密备份
|
||||
|
||||
先在代码仓库之外创建口令文件:
|
||||
|
||||
```bash
|
||||
sudo install -d -m 700 /etc/travel-kg/secrets
|
||||
openssl rand -base64 48 | sudo tee /etc/travel-kg/secrets/mysql-backup-passphrase >/dev/null
|
||||
sudo chmod 600 /etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
```
|
||||
|
||||
执行备份和校验:
|
||||
口令文件、外部备份目录和自动任务应按“生产 MySQL 持久化存储”章节创建。手动执行
|
||||
与校验示例:
|
||||
|
||||
```bash
|
||||
export DATA_BACKUP_ROOT=/mnt/backup/nianxx/mysql
|
||||
export DATA_BACKUP_PASSPHRASE_FILE=/etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
export MYSQL_DATA_DIR=/mnt/sdr/nianxx/mysql
|
||||
export MYSQL_STORAGE_ID=prod-mysql-你的唯一标识
|
||||
export DATA_BACKUP_RETENTION_DAYS=30
|
||||
./scripts/backup_mysql_encrypted.sh
|
||||
./scripts/verify_mysql_backup.sh ./backups/mysql/mysql-all-时间.sql.gz.enc
|
||||
./scripts/verify_mysql_backup.sh /mnt/backup/nianxx/mysql/mysql-all-时间.sql.gz.enc
|
||||
```
|
||||
|
||||
备份采用 `mysqldump --single-transaction`、gzip 和 AES-256/PBKDF2,并生成
|
||||
SHA-256 校验文件。`.enc`、`.sha256`、`.json` 三个文件必须同步到独立账号的
|
||||
异地对象存储。校验脚本不等于恢复演练;至少每月在隔离 MySQL 实例执行一次
|
||||
完整恢复,确认账号、表结构和业务数据均可恢复。
|
||||
脚本不再提供仓库内默认备份目录:目录缺失、位于仓库内、与运行数据重叠、口令权限
|
||||
过宽或保留周期不合规都会直接失败。备份采用 `mysqldump --single-transaction`、
|
||||
Binlog 坐标、gzip 和 AES-256/PBKDF2,生成 SHA-256 与清单,并在清理过期备份前
|
||||
自动解密验包。`.enc`、`.sha256`、`.json` 三个文件必须同步到独立账号的异地对象
|
||||
存储。验包不等于恢复演练;至少每月在隔离 MySQL 实例完整恢复一次。
|
||||
|
||||
默认问答链路需要配置问答环节 LLM;可在后台 `外部图谱问答 API -> 问答环节 LLM 模型` 单独配置,也可以继承全局 LLM。
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
- PostgreSQL:继续保存账号、权限、图谱项目与 Schema 等系统元数据。
|
||||
- FalkorDB:继续保存已发布知识图谱节点和关系。
|
||||
- MySQL:只负责“数据中心”的关系型业务数据。
|
||||
- 接口中心:只通过受控 HTTPS API 访问 MySQL 数据中心,不允许外部用户执行任意 SQL。
|
||||
- DBeaver:仅供受信任的数据管理员通过 SSH 隧道管理 MySQL,使用独立 MySQL 用户和 `GRANT` 权限;不复用接口密钥,也不公开 MySQL 端口。
|
||||
- 接口中心当前页面只管理 DBeaver 管理接入:选择数据库、签发个人密钥与账号、查看状态和撤销权限。
|
||||
- DBeaver:仅供受信任的数据管理员通过专用 SSH 隧道管理 MySQL,使用独立 MySQL 用户和 `GRANT` 权限;不复用接口密钥,也不公开 MySQL 端口。
|
||||
- SQL 控制台:生产默认只读;写入通过数据表页面执行,以保留记录级变更历史,物理删除始终禁止。
|
||||
|
||||
每个数据中心数据库都是真实 MySQL Database:中文名称只用于页面显示,英文数据库编码直接作为物理 MySQL 数据库名。前端数据中心的现有 URL、布局和 `/v1/admin/data-platform/*` 契约保持不变。
|
||||
@@ -21,28 +21,53 @@ DATA_MYSQL_REQUIRED=true
|
||||
DATA_MYSQL_POOL_MIN_SIZE=2
|
||||
DATA_MYSQL_POOL_MAX_SIZE=20
|
||||
INTERFACE_API_SECRET=another-long-random-secret
|
||||
DATA_MYSQL_DIRECT_ACCESS_ENABLED=false
|
||||
DATA_MYSQL_DIRECT_ACCESS_ENABLED=true
|
||||
MYSQL_HOST_BIND=127.0.0.1
|
||||
MYSQL_PORT=3307
|
||||
DATA_MYSQL_DIRECT_TRANSPORT=SSH 隧道(强制)
|
||||
DATA_MYSQL_SSH_TUNNEL_REQUIRED=true
|
||||
DATA_MYSQL_SSH_HOST=server.example.com
|
||||
DATA_MYSQL_SSH_PORT=22
|
||||
DATA_MYSQL_SSH_PORT=2222
|
||||
DATA_MYSQL_SSH_BIND=127.0.0.1
|
||||
DATA_MYSQL_SSH_USERNAME=dbeaver
|
||||
DATA_MYSQL_SSH_AUTH_METHOD=SSH 私钥 / SSH Agent
|
||||
DATA_MYSQL_MANAGED_ACCESS_ENABLED=true
|
||||
DATA_MYSQL_SSH_AUTHORIZED_KEYS_FILE=/var/lib/travel-kg/dbeaver-access/authorized_keys
|
||||
DATA_MYSQL_SSH_HOST_PUBLIC_KEY_FILE=/var/lib/travel-kg/dbeaver-access/ssh_host_ed25519_key.pub
|
||||
MYSQL_ACCESS_BROKER_USER=access_broker
|
||||
MYSQL_ACCESS_BROKER_PASSWORD=至少24位独立随机字符串
|
||||
DATA_MYSQL_ADMIN_HOST=127.0.0.1
|
||||
DATA_MYSQL_ADMIN_PORT=3307
|
||||
DATA_MYSQL_ADMIN_ACCOUNT_POLICY=一人一号 · 单库授权 · 禁止 root
|
||||
DATA_MYSQL_AUDIT_ENABLED=false
|
||||
DATA_SQL_CONSOLE_WRITE_ENABLED=false
|
||||
MYSQL_STORAGE_MOUNT=/mnt/sdr
|
||||
MYSQL_STORAGE_ID=prod-mysql-storage-2026-001
|
||||
MYSQL_DATA_DIR=/mnt/sdr/nianxx/mysql
|
||||
DATA_BACKUP_ROOT=/mnt/backup/nianxx/mysql
|
||||
DATA_BACKUP_RETENTION_DAYS=30
|
||||
DATA_BACKUP_PASSPHRASE_FILE=/etc/travel-kg/secrets/mysql-backup-passphrase
|
||||
DATA_BACKUP_ENABLED=false
|
||||
```
|
||||
|
||||
`MYSQL_HOST_BIND` 在生产环境必须保持 `127.0.0.1`。`DATA_MYSQL_DIRECT_ACCESS_ENABLED` 只表示管理员接入是否完成运维配置,不会开放端口;本项目不提供公开 MySQL 直连模式。只有数据库审计真实启用后,才把 `DATA_MYSQL_AUDIT_ENABLED` 改成 `true`。
|
||||
`MYSQL_HOST_BIND` 在生产环境必须保持 `127.0.0.1`。远程电脑访问的是专用 SSH
|
||||
网关端口,不是 MySQL 端口。`DATA_MYSQL_SSH_BIND=127.0.0.1` 只支持服务器本机
|
||||
测试;服务器上线后可设置为服务器内网地址,或设置为 `0.0.0.0` 并在安全组/防火墙
|
||||
中仅放行管理员固定 IP 或 VPN 网段。只有数据库审计真实启用后,才把
|
||||
`DATA_MYSQL_AUDIT_ENABLED` 改成 `true`。
|
||||
|
||||
`access_broker` 是仅供接口中心签发/撤销个人 MySQL 账号的独立服务账号。普通
|
||||
`data_center` 账号不持有 `CREATE USER` 或 `GRANT OPTION`,两者密码不得相同。
|
||||
|
||||
应用会记录 API 调用、记录新增/修改/软删除以及 SQL 控制台的成功、失败和拒绝
|
||||
事件;SQL 审计只保存语句 SHA-256,不保存可能包含敏感值的原文。DBeaver 绕过
|
||||
应用,因此仍必须由数据库审计能力单独留痕,未完成前不得开放长期写权限。
|
||||
|
||||
生产 MySQL 数据目录绑定到服务器独立块存储,不使用项目目录或普通 Docker named
|
||||
volume。Compose 启动前会核对独立磁盘身份标识、目录写权限和已有 MySQL 数据结构;
|
||||
挂载丢失或路径错误时直接停止,不会初始化一个看似正常的空库。准备磁盘、迁移旧卷、
|
||||
安装每日加密备份的完整流程见 `docs/DEPLOYMENT.md`。
|
||||
|
||||
生产 MySQL 开启 ROW Binlog、`sync_binlog=1` 与
|
||||
`innodb_flush_log_at_trx_commit=1`,用于时间点恢复与事务落盘;加密备份脚本和
|
||||
恢复要求见 `docs/DEPLOYMENT.md`。
|
||||
@@ -52,25 +77,33 @@ DATA_BACKUP_ENABLED=false
|
||||
## 首次部署
|
||||
|
||||
```bash
|
||||
docker compose up -d mysql
|
||||
docker compose up -d --build api
|
||||
docker compose -f docker-compose.yml -f docker-compose.server.yml up -d --build mysql dbeaver-gateway api
|
||||
```
|
||||
|
||||
已有 MySQL 数据卷不会重新运行初始化脚本。升级既有部署后执行一次:
|
||||
|
||||
```bash
|
||||
./scripts/enable_managed_dbeaver_access.sh
|
||||
```
|
||||
|
||||
接口中心页面:`/admin/system/interfaces`。
|
||||
|
||||
页面以“服务器被访问”为方向:`DBeaver 管理接入`只给受信任的数据管理员展示 SSH 隧道参数,`HTTPS API`负责电脑、设备和业务系统的身份、密钥、最小权限与调用日志。接口中心不会主动连接外部数据库。
|
||||
页面以“服务器被访问”为方向:为受信任的数据管理员生成个人 SSH 密钥、独立
|
||||
MySQL 账号和最小权限。接口中心不会主动连接外部数据库,也不在这个页面混入
|
||||
HTTPS API 客户端、接口策略或调用日志等其他管理流程。
|
||||
|
||||
## DBeaver 安全连接
|
||||
|
||||
DBeaver 不使用 URL 模式直接填写服务器公网地址。按两组参数配置:
|
||||
|
||||
1. `SSH` 标签页:`Host/IP=服务器域名`、`Port=22`、认证方式使用私钥或 SSH Agent;
|
||||
2. `Main` 标签页:`Server Host=127.0.0.1`、`Port=3307`、`Database=获授权数据库编码`;
|
||||
3. 关闭 `Show all databases`;
|
||||
4. 使用运维为当前人员签发的独立 MySQL 账号,禁止使用 `root` 和后端服务账号 `data_center`;
|
||||
5. 默认只授予 `SELECT`,写入和结构修改权限按需临时授予。
|
||||
1. 在接口中心选择数据库、管理员姓名和“只读/读写”,点击“生成 DBeaver 接入”;
|
||||
2. 私钥由浏览器本地生成,平台只接收公钥。立即下载私钥并保存一次性 MySQL 密码;
|
||||
3. `SSH` 标签页:`Host/IP=服务器域名`、`Port=2222`、`User Name=dbeaver`、认证方式选择 `Public Key` 并选择刚下载的私钥;不要启用 `Bypass host verification`,首次连接提示的 SSH 主机指纹必须与接口中心一致;
|
||||
4. `Main` 标签页:`Server Host=127.0.0.1`、`Port=3307`、`Database=获授权数据库编码`,填写生成的个人 MySQL 用户名和密码;
|
||||
5. 关闭 `Show all databases`;默认只授予查询权限,读写权限也不包含建库、建表、`ALTER`、`DROP` 或给他人授权。
|
||||
|
||||
运维人员可在服务器上创建或撤销独立账号:
|
||||
接口中心可以直接撤销管理接入,撤销会同时删除个人 MySQL 账号和 SSH 公钥。
|
||||
服务器脚本保留为故障处理备用方式:
|
||||
|
||||
```bash
|
||||
./scripts/mysql_admin_account.sh create zhangsan tourism_data read
|
||||
@@ -83,14 +116,22 @@ DBeaver 不使用 URL 模式直接填写服务器公网地址。按两组参数
|
||||
失败 5 次锁定一天,密码 90 天过期。MySQL 端口仍必须绑定回环地址,账号的
|
||||
`'%'` 主机范围不能替代网络隔离。
|
||||
|
||||
接口中心不会显示或复制 MySQL 密码。服务器安全组只允许受控来源访问 SSH 与 HTTPS,不开放 `3307`。
|
||||
完整私钥和 MySQL 密码只在生成成功时显示一次,服务器不保存私钥,也不保存可恢复
|
||||
的 MySQL 密码。专用 SSH 账号被禁止终端、PTY、SFTP、Agent/X11 转发,只允许将
|
||||
连接转发到 `127.0.0.1:3307`。服务器安全组只允许受控来源访问 HTTPS 与专用 SSH
|
||||
端口,不开放 `3307`。
|
||||
|
||||
外部数据接口前缀:`/v1/openapi/data`。调用时使用:
|
||||
本地模拟服务器连接时使用:
|
||||
|
||||
```http
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```dotenv
|
||||
DATA_MYSQL_SSH_HOST=localhost
|
||||
DATA_MYSQL_SSH_BIND=127.0.0.1
|
||||
DATA_MYSQL_SSH_PORT=2222
|
||||
```
|
||||
|
||||
服务器部署后把 `DATA_MYSQL_SSH_HOST` 改为服务器域名;若管理员电脑不在同一内网,
|
||||
还必须把 `DATA_MYSQL_SSH_BIND` 绑定到可达网卡,并用防火墙限定管理员来源 IP。
|
||||
|
||||
## 迁移旧数据中心
|
||||
|
||||
先预览,不写入:
|
||||
@@ -113,7 +154,9 @@ python3 scripts/migrate_data_center_postgres_to_mysql.py --execute --replace-tar
|
||||
|
||||
迁移会保留记录 UUID、创建/更新时间、软删除状态和数据变更审计,从而避免实体引用失效;不会修改 PostgreSQL 源数据,也不会操作 FalkorDB 或知识图谱。
|
||||
|
||||
## 权限模型
|
||||
## 预留的数据接口权限模型
|
||||
|
||||
以下后端能力为后续 HTTPS 数据接口预留,当前 DBeaver 管理接入页面不显示:
|
||||
|
||||
一条接口策略包含:
|
||||
|
||||
|
||||
Reference in new issue
Block a user