如何设计数据库权限、审计与敏感数据治理
不要先背 RBAC 和脱敏;先解释“客服为什么能看到别的租户账目备注”
这一页只解决一个问题: 数据库层怎样防止合法功能查出非法数据,并在敏感访问发生后能复盘。多租户隔离、租户迁移、噪声邻居和敏感字段治理都收敛到同一件事:谁、为什么、在哪个租户、看哪些字段、占用哪些资源、留下什么证据。
客服后台有“按手机号查询账目”功能。一次排障时,客服输入手机号后看到了另一个租户的账目备注。菜单权限合法,查询功能合法,结果范围非法。
bad query:
SELECT *
FROM ledger_entries
WHERE phone = ?;
missing:
tenant_id
ticket_scope
field_masking
audit_purpose
| 补丁 | 为什么不够 | 逼出的设计 |
| 这条 SQL 加 tenant_id | 下一条查询仍可能漏 | 租户边界强制执行 |
| 收紧菜单权限 | API、导出、脚本仍可能绕过 | 权限要落到查询和字段 |
| 让客服签保密协议 | 不能替代技术控制 | 敏感访问要可证明、可追责 |
| 问题 | 例子 |
| 这行数据属于哪个租户 | 所有账目查询必须带 tenant scope |
| 哪些字段敏感 | 备注、手机号、附件、审计记录比分类名更敏感 |
| 谁因为什么目的访问 | 客服必须有工单,开发排障默认拿脱敏证据 |
| 能查这行是否等于能看所有列 | 行权限和列权限要分开 |
| 导出是否比查询更高危 | 导出文件会离开系统,要审批、水印、时效 |
| 访问后怎么复盘 | actor、tenant、字段、row_count、ticket、trace 都要记录 |
data_access_audit
- actor_id
- actor_type
- tenant_id
- action: view | export | update | delete
- table_name
- fields
- row_count
- purpose
- ticket_id
- trace_id
- expires_at
吸收点: 审计不是“记了日志”。审计要能回答某个用户的数据被谁、在什么目的下、看了哪些字段、看了多少。
| 边界 | 事故 | 设计动作 |
| 租户边界 | 漏 tenant_id 串租户 | 查询守卫、RLS、服务层 scope |
| 字段边界 | 客服看到了完整备注和附件 | 字段分级、列权限、默认脱敏 |
| 导出边界 | 全量明细文件流出系统 | 字段白名单、审批、水印、短期有效 |
| 副本边界 | 日志、索引、备份里仍有明文 | 副本也纳入脱敏、权限和保留策略 |
关键判断: 合法账号、合法菜单、合法 SQL 仍然可能产生非法数据范围。数据库权限要管结果范围,不只管入口。
| 边界 | 最低设计 | 防什么事故 |
| 查询边界 | tenant scope 强制进入查询守卫、RLS 或服务层上下文 | 漏 tenant_id 导致串租户 |
| 唯一性边界 | 手机号、分类名、外部单号按租户口径定义唯一性 | 把跨租户重复误判成全局冲突 |
| 引用边界 | entry、category、account 的 tenant_id 必须一致 | 一条账目引用到别的租户分类 |
| 资源边界 | 按租户限制连接、导入、报表、导出和慢查询预算 | 大租户拖垮共享库里的小租户 |
| 审计边界 | 每次敏感访问都记录 actor、tenant、字段、目的和工单 | 事后不知道谁看过哪家数据 |
吸收点: tenant_id 不是展示字段,而是权限、约束、索引、审计和资源调度的共同边界。只加字段但不强制执行,等于没有隔离。
tenant_directory
- tenant_id
- placement_type: shared | dedicated
- database_id
- shard_id
- route_version
- status: active | migrating | suspended | deleting
- region
| 场景 | 必须留下的证据 | 失败时怎么停 |
| 共享库迁专属库 | 租户目录、route_version、新旧数据对账、旧库写保护记录 | 旧 route_version 写入被拒绝,避免一半写旧库一半写新库 |
| 大租户噪声治理 | 租户级查询耗时、导入队列、连接占用、报表预算 | 超过租户预算就限速、排队或迁出 |
| 单租户恢复 | 恢复范围、旧值来源、隔离恢复库、复核人和审计记录 | 只恢复目标租户,不做整库回滚 |
| 样本 | 通过标准 |
| 手写 SQL 漏 tenant_id | 被拒绝或告警,不返回跨租户数据 |
| 客服无工单查看备注 | 默认脱敏或拒绝 |
| 高级客服临时查看备注 | 有工单、审批、时效和审计 |
| 导出 10 万行账目 | 进入审批,字段白名单和水印生效 |
| 搜索索引查敏感字段 | 同样执行租户 ACL 和字段策略 |
| 追查某用户被谁看过 | 能按 actor、tenant、field、ticket 完整复盘 |
总结: 数据库权限设计不是 RBAC 名词表。它要让租户边界、字段边界、导出边界、副本边界和资源边界都可执行、可审计、可复盘。