TheCactuslxf/sql-gatekeeper
GitHub: TheCactuslxf/sql-gatekeeper
一个位于 AI Agent 与 MySQL 之间的 SQL 安全网关,提供分片路由、SQL 重写、安全审查与审计执行功能。
Stars: 1 | Forks: 0
# SQL Gatekeeper
[](https://github.com/TheCactuslxf/sql-gatekeeper/actions/workflows/ci.yml)
[](https://www.python.org/)
[](LICENSE)
SQL Gatekeeper 位于 AI agent 和 MySQL 之间。它允许 agent 编写简单的逻辑 SQL,而网关则负责决定查询是否安全,将逻辑表映射到物理分片,重写 SQL,检查执行计划,并记录决策。
```
flowchart LR
A["LLM / AI Agent"] --> B["SQL Gatekeeper API"]
B --> C["Basic SQL guard"]
C --> D["Parser"]
D --> E["Route resolver"]
E --> F["SQL rewrite"]
F --> G["Policy filters"]
G --> H["EXPLAIN risk check"]
H --> I["Read-only execution"]
H --> J["Audit log"]
I --> J
```
## 为什么开发此项目
让 LLM 与数据库交互非常有用,但直接执行 SQL 是一个存在风险的边界:
- 模型可能会生成写操作、多语句、缺少 limit 的查询或昂贵的扫描。
- 当模型控制查询结构时,预编译语句和 ORM 转义无法解决问题。
- 生产环境的 schema 通常使用逻辑表、物理分片和路由元数据,而这些是模型不需要了解的。
- 团队需要为已批准和已拒绝的 AI 生成查询提供审计记录。
SQL Gatekeeper 正是为了解决这一边界问题而构建的。
## 功能简介
- 接收由 LLM 或 agent 生成的 SQL。
- 支持 MySQL 逻辑表查询,例如 `select * from user where uid = 10001 limit 10`。
- 从 SQL 断言或请求上下文中解析路由因子。
- 将逻辑表重写为已注册的物理表,例如将 `user` 重写为 `user_1`。
- 拒绝非 `SELECT` 语句、多语句、缺少 `LIMIT` 的查询、过大的 `LIMIT`、跨数据源 join 以及不安全的执行计划。
- 根据策略,使用 MySQL `EXPLAIN` 阻止大规模扫描、`Using temporary` 和 `Using filesort`。
- 使用只读数据源凭证执行已批准的 SQL。
- 记录检查和执行的审计日志。
## 快速开始
克隆项目并以可编辑模式安装:
```
git clone https://github.com/TheCactuslxf/sql-gatekeeper.git
cd sql-gatekeeper
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```
启动本地 MySQL stack:
```
docker compose up -d
```
创建元数据表并植入演示路由:
```
python -m sql_gatekeeper.bootstrap.meta
```
运行 API:
```
uvicorn sql_gatekeeper.api.app:app --host 127.0.0.1 --port 8080
```
检查逻辑 SQL 查询:
```
curl -s http://127.0.0.1:8080/api/v1/sql/check \
-H "content-type: application/json" \
-d '{
"request_id": "demo-001",
"operator": "ai-agent",
"scene": "demo",
"sql": "select uid, user_name from user where uid = 10001 limit 10",
"route_context": {}
}'
```
预期结果:
```
{
"allowed": true,
"reason_code": "ALLOW",
"rewritten_sql": "select uid, user_name from user_1 where uid = 10001 limit 10",
"logical_tables": ["user"],
"physical_tables": ["user_1"],
"datasource_codes": ["biz_user_db"]
}
```
## API
### `POST /api/v1/sql/check`
返回决策、重写后的 SQL、路由诊断和 EXPLAIN 摘要,而不执行查询。
### `POST /api/v1/sql/execute`
运行相同的安全 pipeline,然后使用只读数据源凭证执行已批准的 SQL。
请求结构:
```
{
"request_id": "req-123",
"operator": "ai-agent",
"scene": "chatops",
"sql": "select * from order where order_id = 'A1002' limit 1",
"route_context": {
"biz_date": "2025-07"
}
}
```
## 路由示例
演示元数据包含两个逻辑表:
| 逻辑表 | 路由因子 | 规则 | 物理目标 |
| --- | --- | --- | --- |
| `user` | SQL 断言 `uid` | `int(uid) % 2` | `user_0` 或 `user_1` |
| `order` | `route_context.biz_date` | `YYYY-MM` 转换为 `YYYY_MM` | `order_2025_06`, `order_2025_07` |
示例:
```
select order_id, amount from order where order_id = 'A1002' limit 1
```
使用:
```
{"biz_date": "2025-07"}
```
重写为:
```
select order_id, amount from order_2025_07 where order_id = 'A1002' limit 1
```
对于导入的分片表,调用方可以提供业务分片列名,同时将分片值保留在逻辑 SQL 断言中:
```
{
"sql": "select count(1) as cnt from partner__partner_relation_info where from_uid = '97585024' limit 1",
"route_context": {
"shard_column": "from_uid"
}
}
```
服务会提取断言值,根据导入的分片元数据计算路由,将逻辑表重写为物理表,并执行检查过的 SQL。调用方无需计算或提供 `route_suffix`。
## 安全检查
SQL Gatekeeper 目前会阻止:
- 空 SQL。
- 多语句 SQL。
- 前导注释。
- `INSERT`、`UPDATE`、`DELETE`、`REPLACE`、`DROP`、`ALTER` 和 `TRUNCATE`。
- 任何非 `SELECT` 语句。
- 未知的逻辑表或未注册的物理表。
- 缺少必要的路由因子。
- 跨数据源 join。
- 策略要求时缺少 `LIMIT`。
- `LIMIT` 值超过策略最大值。
- 超过扫描阈值的 EXPLAIN 计划。
- 大表的全表扫描。
- 策略拒绝时的 `Using temporary` 和 `Using filesort`。
## 架构
| 模块 | 职责 |
| --- | --- |
| API 层 | 用于检查和执行的 FastAPI 路由 |
| SQL 解析器 | 提取 SQL 类型、表、别名、断言和 limit |
| 路由决策引擎 | 将逻辑表解析为数据源和物理表 |
| SQL 重写引擎 | 将逻辑表 token 替换为物理表名 |
| 过滤器链 | 应用策略、数据源、SQL 类型、limit 和 EXPLAIN 检查 |
| 执行器 | 使用只读凭证执行已批准的 SQL |
| 审计日志记录器 | 持久化记录请求、决策、重写后的 SQL 和 EXPLAIN 摘要 |
## 开发
运行不需要 Docker MySQL 的单元测试:
```
pytest tests
```
运行由 Docker 支持的完整测试套件:
```
RUN_DOCKER_TESTS=1 pytest tests
```
有用的本地命令:
```
make up
make bootstrap-dev
make test
make down
```
## 路线图
- 用基于 AST 的解析器(例如 `sqlglot`)替换当前轻量级的正则表达式解析器。
- 添加 PostgreSQL 支持。
- 为 AI agent 添加 MCP 服务器模式。
- 添加用于租户过滤器、表允许列表和列拒绝列表的策略 DSL。
- 添加一个小型审计仪表板。
- 发布 Docker 镜像和 PyPI 包。
有关更多详细信息,请参阅 [ROADMAP.md](ROADMAP.md)。
## 相关领域
SQL Gatekeeper 在理念上类似于用于 LLM 应用的 SQL 防护项目,但它专注于生产环境的 MySQL 访问模式,在这些模式中,逻辑表、分片路由、SQL 重写、EXPLAIN 风险检查、只读执行和审计需要协同工作。
## 许可证
MIT。请参阅 [LICENSE](LICENSE)。
标签:AI网关, LLM集成, SQL审查, 分库分表, 安全防护, 数据库中间件, 请求拦截, 逆向工具