# MySQL 8.0 OCP 查漏补缺-防火墙相关概念之二 最近在考MySQL 8.0的OCP ,开个专题专门查漏补缺下 基于8.0.26 只是做备忘,有的概念只是一笔带过,具体可自行搜索 由于该功能只在企业版上,这里没有环境,所有命令和图片来自官网 ## 1. Firewall Profiles 防火墙使用profile来决定是否允许一个语句执行,它有三个属性 - allowlist 该属性是一个规则集合来定义profile中哪些语句是可以通行的 - 一个当前的可操作(operational )模式,使得profile可以在多个模式使用,这个后面介绍 - profile的适用范围,这个定义什么客户端连接适用什么profile,包含: - - account-based profiles 基于账号的,该profile叫做Account Profiles - - group profiles 基于组的,该profile叫做Group Profiles,从8.0.23开始支持 这里注意:一个group可以包含多个account,account也可以同时属于多个group,account可以对应多个profile,只要profile包含该account. 默认情况下是没有任何profile的,这意味着所有语句都可以被执行,如果需要使用需要做如下操作: - 注册一个或多个profile到防火墙 - 针对每个profile进行训练,以用来建立一个allowlist - 将经过训练的profile置于protecting 模式来过滤语句 ## 2. Profile Operational Modes 上面我们说了Profile有三个属性,下面来讲第二个,可操作模式有如下取值: - OFF: 代表该profile未启用,防火墙会忽略它 - RECORDING: 代表该profile处于训练模式(training mode),处于这种模式后所做的操作会被记录下来并加入到allowlist,这时当前连接的用户适用该profile,这里防火墙会合并一些语句来减少规则,如将where条件的值替换成为占位符(?),类似与绑定变量。 - PROTECTING: 这个模式下防火墙会对过来的语句进行过滤,阻止不在allowlist里面的语句,如果设置了mysql_firewall_trace 变量,则会把reject的语句写入都错误日志 - DETECTING: 处于该模式下的话不会reject不在allowlist里面的语句,会执行并将这些可疑的语句写入到错误日志 可以使用RESET命令来重置profile,这个命令会删除profile下所有的规则并设置成OFF状态 ## 3. 注册一个Group Profiles ### 3.1 建立一个用户并赋权 ``` CREATE USER 'member1'@'localhost' IDENTIFIED BY 'password'; GRANT ALL ON sakila.* TO 'member1'@'localhost'; grant firewall_admin on *.* to 'root'@'localhost'; ``` ### 3.2 注册 group profile并处理RECORDING 模式 ``` CALL mysql.sp_set_firewall_group_mode('fwgrp', 'RECORDING'); ``` ### 3.3 将用户加入到组里 ``` CALL mysql.sp_firewall_group_enlist('fwgrp', 'member1@localhost'); ``` ### 3.4 开始训练 这里使用member1@localhost用户执行写语句让防火墙将这些加入到allowlist中 该allowlist适用于组内的所有用户 ``` SELECT title, release_year FROM film WHERE film_id = 1; UPDATE actor SET last_update = NOW() WHERE actor_id = 1; SELECT store_id, COUNT(*) FROM inventory GROUP BY store_id; ``` 这时可以查看相关视图来确定信息 ``` mysql> SELECT MODE FROM performance_schema.firewall_groups WHERE NAME = 'fwgrp'; SELECT * FROM performance_schema.firewall_membership WHERE GROUP_ID = 'fwgrp' ORDER BY MEMBER_ID; SELECT RULE FROM performance_schema.firewall_group_allowlist WHERE NAME = 'fwgrp'; ``` [image:1006 size:orig] ### 3.5 将profile设为protect状态 如果状态不设置成RECORDING以外的状态,mysql不会持久化规则,如果重启数据据会丢失allowlist的内容 ``` CALL mysql.sp_set_firewall_group_mode('fwgrp', 'PROTECTING'); ``` 如果需要可以再次进入到训练模式来继续训练 ### 3.6 添加别的用户到组 如果需要可以增加别的用户 ``` CALL mysql.sp_firewall_group_enlist('fwgrp', 'member2@localhost'); CALL mysql.sp_firewall_group_enlist('fwgrp', 'member3@localhost'); CALL mysql.sp_firewall_group_enlist('fwgrp', 'member4@localhost'); ``` 当然也可以删除 ``` CALL mysql.sp_firewall_group_delist('fwgrp', 'member3@localhost'); ``` ### 3.7 禁用profile ``` CALL mysql.sp_set_firewall_group_mode(group, 'OFF'); ``` ### 3.8 重置profile ``` CALL mysql.sp_set_firewall_group_mode(group, 'RESET'); ``` ## 4. 注册一个Account Profiles ### 4.1 建立用户 ``` CREATE USER 'fwuser'@'localhost' IDENTIFIED BY 'password'; GRANT ALL ON sakila.* TO 'fwuser'@'localhost'; grant firewall_admin on *.* to 'root'@'localhost'; ``` ### 4.2 设置成RECORDING模式 ``` CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING'); ``` ### 4.3开始训练 ``` SELECT first_name, last_name FROM customer WHERE customer_id = 1; UPDATE rental SET return_date = NOW() WHERE rental_id = 1; SELECT get_customer_balance(1, NOW()); ``` 这时可以查看相关状态 ``` mysql> SELECT MODE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS WHERE USERHOST = 'fwuser@localhost'; mysql> SELECT RULE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST WHERE USERHOST = 'fwuser@localhost'; ``` [image:1007 size:orig] ### 4.4 设置成保护模式 ``` CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING'); ``` 如果需要可以再次进入到训练模式来继续训练 ### 4.5 设置成检测模式 ``` CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'DETECTING'); ``` ### 4.6 禁用profile ``` CALL mysql.sp_set_firewall_mode(user, 'OFF'); ``` ### 4.7 重置profile ``` CALL mysql.sp_set_firewall_mode(user, 'RESET'); ``` ## 5.监控防火墙 使用如下命令查看 ``` SHOW GLOBAL STATUS LIKE 'Firewall%'; ``` [image:1008 size:orig] 分别代表拒绝的,接受的,可疑的,加入的规则。 ## 6. 将Account Profiles 变为 Group Profiles 由于Group Profiles 从8.0.23才有,如果哟需要可以进行迁移 ``` CALL mysql.sp_migrate_firewall_user_to_group('admin@localhost', 'admins'); CALL mysql.sp_migrate_firewall_user_to_group('local_client@localhost', 'local_clients'); CALL mysql.sp_migrate_firewall_user_to_group('remote_client@localhost', 'remote_clients') ``` 必须处于非recording状态,account profile必须存在,group profile必须不存在