# 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必须不存在