14.9.1 访问控制与权限最小化策略
访问控制与权限最小化策略#
本节目标是在 ProxySQL 层建立清晰的权限边界:管理接口隔离、业务账号分级、后端账号最小化、规则联动与审计。
原理草图(管理接口与业务通道分离)
1. 安装/环境检查(确保管理接口可配置)
# 检查 ProxySQL 运行状态
systemctl status proxysql
# 查看监听端口(6032 管理端口,6033 业务端口)
ss -lntp | grep proxysql
预期效果: 看到 6032/6033 端口已监听。
2. 管理接口访问控制(绑定管理口 + 管理账号最小化)
2.1 仅绑定管理口到本地回环
-- 连接管理接口
mysql -u admin -padmin -h 127.0.0.1 -P 6032
-- 仅允许本机访问管理端口
SET GLOBAL admin-mysql_ifaces='127.0.0.1:6032';
LOAD ADMIN VARIABLES TO RUNTIME;
SAVE ADMIN VARIABLES TO DISK;
-- 验证
SELECT * FROM global_variables WHERE variable_name='admin-mysql_ifaces';
命令解释:
- admin-mysql_ifaces:控制管理端口监听地址;
- LOAD ... TO RUNTIME:立即生效;
- SAVE ... TO DISK:重启不丢失。
2.2 创建只读管理账号(用于监控)
-- 删除默认 admin(仅示例,生产按变更流程执行)
DELETE FROM admin_users WHERE username='admin';
-- 创建具备只读权限的监控账号
INSERT INTO admin_users(username,password,default_hostgroup,active,admin)
VALUES('mon_ro','Str0ng!Pwd',0,1,0);
LOAD ADMIN USERS TO RUNTIME;
SAVE ADMIN USERS TO DISK;
-- 验证
SELECT username,admin FROM admin_users;
说明: admin=0 表示只读权限,适合监控采集。
3. 业务用户与权限分级(读写分离绑定用户组)
-- 定义用户(读写)
INSERT INTO mysql_users(username,password,default_hostgroup,transaction_persistent,active)
VALUES('app_rw','AppRw#2024',10,1,1);
-- 定义用户(只读)
INSERT INTO mysql_users(username,password,default_hostgroup,transaction_persistent,active)
VALUES('app_ro','AppRo#2024',20,1,1);
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
-- 验证
SELECT username,default_hostgroup FROM mysql_users;
说明:
- default_hostgroup=10:读写主库组;
- default_hostgroup=20:只读从库组。
4. 后端数据库账户最小化(MySQL 侧权限控制)
-- 在 MySQL 主库创建业务最小权限账号
CREATE USER 'app_rw'@'proxysql_ip' IDENTIFIED BY 'AppRw#2024';
GRANT SELECT,INSERT,UPDATE,DELETE ON appdb.* TO 'app_rw'@'proxysql_ip';
CREATE USER 'app_ro'@'proxysql_ip' IDENTIFIED BY 'AppRo#2024';
GRANT SELECT ON appdb.* TO 'app_ro'@'proxysql_ip';
FLUSH PRIVILEGES;
说明: 禁止 ALL PRIVILEGES,按库/表授权。
5. 规则与权限联动(限制高风险语句)
-- 禁止只读账号执行写操作(拦截 INSERT/UPDATE/DELETE)
INSERT INTO mysql_query_rules(rule_id,active,username,match_pattern,apply,flagOUT)
VALUES(1001,1,'app_ro','^(INSERT|UPDATE|DELETE|REPLACE|ALTER|DROP)',1,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
-- 验证
SELECT rule_id,username,match_pattern FROM mysql_query_rules WHERE rule_id=1001;
预期效果: app_ro 执行写语句将被拒绝。
6. 会话与连接限制(降低误操作风险)
-- 限制高权限账号连接数
UPDATE mysql_users SET max_connections=20 WHERE username='app_rw';
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
-- 验证
SELECT username,max_connections FROM mysql_users WHERE username='app_rw';
7. 权限审计与变更核对
-- 导出 runtime 与配置表进行比对
SELECT * FROM runtime_mysql_users INTO OUTFILE '/tmp/runtime_mysql_users.csv';
SELECT * FROM mysql_users INTO OUTFILE '/tmp/mysql_users.csv';
说明: 对比差异,确认是否有未持久化或异常变更。
排错清单
# 1) 无法连接管理端口
ss -lntp | grep 6032
mysql -u mon_ro -p -h 127.0.0.1 -P 6032 -e "SELECT 1;"
# 2) 变更未生效
mysql -u mon_ro -p -h 127.0.0.1 -P 6032 -e "SELECT * FROM runtime_mysql_users;"
# 3) 规则未生效
mysql -u mon_ro -p -h 127.0.0.1 -P 6032 -e "SELECT * FROM runtime_mysql_query_rules;"
说明:
- 若 runtime_ 表无变更,检查是否执行 LOAD ... TO RUNTIME;
- 规则未命中,检查 match_pattern 正则是否匹配。
练习
1. 将管理端口改为 127.0.0.1:6032,并验证外部主机无法访问。
2. 创建 report_ro 账号,仅允许访问从库,禁止写操作并验证报错。
3. 为 app_rw 设置 max_connections=5,尝试超过限制并观察行为。