TheCactuslxf/sql-gatekeeper

GitHub: TheCactuslxf/sql-gatekeeper

一个位于 AI Agent 与 MySQL 之间的 SQL 安全网关,提供分片路由、SQL 重写、安全审查与审计执行功能。

Stars: 1 | Forks: 0

# SQL Gatekeeper [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/TheCactuslxf/sql-gatekeeper/actions/workflows/ci.yml) [![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](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审查, 分库分表, 安全防护, 数据库中间件, 请求拦截, 逆向工具