Agent调用数据库操作限制,禁止drop/alter高危
当 Agent 或自动化程序直接连接数据库执行任务时,一旦权限控制不到位,误执行 drop、alter 等高危 SQL 就可能造成数据丢失或表结构变更。
本文介绍几种实际可行的限制方案,帮助你在 Agent 调用链路上设置最后一道防线。
先判断你的使用场景
限制高危 SQL 通常有三种常见场景:
- Agent 使用高权限账号,但业务只要求读写特定表,需要收紧权限。
- Agent 需要执行复杂操作,但必须禁止删除、修改表结构等危险动作。
- DBA 希望统一审计所有来源的 SQL,尤其是自动化链路中的操作记录。
无论哪种情况,核心原则都是:最小权限 + 二次拦截。
也就是说,先在数据库层面限制账号权限,再在代理层或中间件层过滤危险语句。
方案一:数据库账号权限收紧(最基础)
以 MySQL 为例,不要直接给 Agent 使用 root 或 ALL PRIVILEGES 账号,而是按业务需要创建最小权限账号。
-- 只允许读取和修改指定库表,禁止删除表、修改表结构
CREATE USER 'agent_user'@'%' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'agent_user'@'%';
-- 如果需要执行存储过程,单独授权
GRANT EXECUTE ON PROCEDURE mydb.my_proc TO 'agent_user'@'%';
这样即使 Agent 被注入恶意 SQL,也无法执行 drop、alter 等操作,因为账号本身没有对应权限。
对于 PostgreSQL,也可以按类似方式处理:
CREATE USER agent_user WITH PASSWORD 'strong_password';
GRANT CONNECT ON DATABASE mydb TO agent_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO agent_user;
注意:数据库权限只能从源头上限制,无法拦截已经拥有高权限的账号。
如果 Agent 确实需要高权限,请参考下一个方案。
方案二:拦截中间件或代理层过滤
如果 Agent 必须使用高权限账号,或者在多套数据库间切换,建议在应用与数据库之间增加一个 SQL 拦截代理,例如 ProxySQL、MaxScale 或自研网关。
以 ProxySQL 为例,可以通过查询规则(Query Rules)拦截包含 drop、alter 的语句:
-- 添加规则:匹配到 drop 或 alter 则返回错误
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, error_msg, apply)
VALUES (10, 1, '^\s*(drop|alter)\s+', 'Detected high-risk SQL operation, blocked by proxy.', 1);
LOAD MYSQL QUERY RULES TO RUN;
SAVE MYSQL QUERY RULES TO DISK;
例如,当 Agent 尝试执行任意 drop 或 alter 语句时,ProxySQL 会直接拦截并返回自定义错误信息,不会把请求转发给后端数据库。
这种方式不依赖数据库账号权限,适合多个 Agent 共用一个账号的场景,也可以同时记录审计日志。
方案三:内置 SQL 审计插件或自定义拦截器
如果你的 Agent 是自己开发的程序,可以在连接池或数据库操作层增加一个拦截器,对所有 SQL 做正则匹配:
import re
# 高危 SQL 匹配模式
HIGH_RISK_PATTERN = re.compile(r'^\s*(drop|alter|truncate)\s+', re.IGNORECASE)
def execute_with_guard(cursor, sql):
if HIGH_RISK_PATTERN.match(sql):
raise PermissionError(f"Blocked high-risk SQL: {sql[:50]}")
cursor.execute(sql)
这种方式逻辑简单,但只适合单应用内部拦截。
如果存在多个 Agent 或绕过程序直接连接数据库,建议仍以中间件为主。
避坑指南
- 不要只依赖正则拦截,SQL 写法多样,例如注释、十六进制编码都可能绕过弱正则。需要配合数据库权限和代理层共同防护。
- 代理规则要测试,规则有时候会误拦截正常语句,比如
alter user或drop view,上线前务必做一轮回归验证。 - 监控和告警不能少,即使拦截成功,也需要记录日志并通知运维人员,及时排查触发原因。
- 注意协议兼容,使用代理层时,需要开启后端数据库的预处理语句(prepared statements)支持,否则部分 SQL 可能无法正常解析。
如何验证拦截是否生效
配置完毕后,请按以下步骤验证:
- 使用 Agent 的账号连接数据库,执行一条普通查询,确认正常。
- 尝试执行
DROP TABLE test_table;或ALTER TABLE test_table ADD COLUMN temp INT;。 - 观察返回结果。若使用账号权限限制,应报权限不足;若使用代理拦截,应返回自定义错误信息。
- 查询代理日志或审计日志,确认拦截记录已被记录。
- 再检查业务核心读写是否仍正常,避免误杀。
常见疑问
问:只靠数据库权限限制够吗?
不够。
如果 Agent 账号被提权,或者应用程序被注入高权限调用,数据库权限就失效了。
建议权限限制和代理层拦截配合使用。
问:正则拦截有办法完全防止高危 SQL 吗?
没有绝对安全。
任何字符串层面的拦截都可能被绕过,最可靠的办法是数据库账号权限严格控制,同时配合数据库审计日志做事后追溯。
问:拦截后是否影响 Agent 的正常业务?
只要规则匹配得当,不会影响。
建议先放行正常业务语句,然后逐步收紧规则,每一轮都做回归测试。
实际部署时不必一次到位,但至少要让高危 SQL 无法直接落地。
如果你的环境中 Agent 已经投入使用,优先收紧账号权限,再考虑增加代理层或代码拦截,最后通过日志验证整体效果。