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