MySQL的审计功能实现方案

Posted bisal(Chen Liu)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL的审计功能实现方案相关的知识,希望对你有一定的参考价值。

数据库的安全(可以参考《数据库安全的重要性》、《MySQL的安全解决方案》、《提供使用国密算法的MySQL》)对企业来说,是至关重要的,审计是其中一种保障数据库安全的手段。

熟悉Oracle的朋友可能都知道,Oracle内置支持audit功能,可以提供细粒度到字段的审计。开源社区的这篇文章《技术分享 | MySQL 审计功能实现方案》为我们介绍了mysql中,对于审计功能的实现方式,值得借鉴。

背景

鉴于目前MySQL审计需求不断深入扩张,以提高数据资产的安全,使得数据库愈来愈规范化管理,数据库实现审计功能成为必要安全环节。

众所周知,MySQL社区版是不带审计插件的(Audit Plugin),那么该如何实现审计功能呢?我们自然会想到使用binlog日志做审计,因为binlog日志本就记录着数据库上的所有改变。但是无奈,binlog日志并不会记录用户的登录信息,所以无法做到真正意义上的审计。那使用general_log日志呢?

general_log日志可不仅记录着登录信息,甚至错误的登录信息、select等所有对数据库的操作都会记录着。也正是因为general_log日志记录得过于详细,不好做区分。且当并发访问量过大时,极大的占用空间,影响数据库的性能。所以也不会将之作为实现审计功能的工具。

本文将介绍如下三种方式,实现使用审计功能。

相关说明:本文所使用的工具版本

环境:MySQL - 5.7.25(社区版)

工具:

工具获取源包名
MariaDB审计插件mariadb-10.2.43-linux-systemd-x86_64
McAfee审计插件audit-plugin-mysql-5.7-1.1.11-985-linux-x86_64.zip


方案1,init_connect参数

init_connect是社区版MySQL自带的参数。MySQL官方手册释义:“A string to be executed by the server for each client that connects. The string consists of one or more SQL statements, separated by semicolon characters.”

即:在连接客户端时刻,服务器要为每个连接,执行init_connect所定义的字符串。这个字符串可以由一个或多个 SQL 语句组成,以分号字符分隔。《》

那么该如何去利用这个参数呢?要实现审计功能,审计信息至少要包括登录MySQL的用户名、登录IP、登录时间等内容(谁在哪个时刻动了我的数据库啦!)。我们知道,init_connect参数所定义的字符串在登录连接时刻执行。如果我们提前创建一个表,并且把init_connect所定义的字符串写成insert语句(登录时刻,插入用户登录的信息)那么利用这个参数的特性,就可以实现简单的审计功能。

实现步骤

1、创建审计日志表

审计日志表记录内容包括:登录数据库的用户、IP、本次登录时间(审计必要信息);

CREATE TABLE `test_db`.`audit` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `USER` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '登录用户名',
  `ADRESS` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '登录IP',
  `LOGIN_TIME` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '登录时间',
  PRIMARY KEY (`ID`),
  KEY `IDX_USER` (`USER`),
  KEY `IDX_HOST` (`ADRESS`),
  KEY `IDX_LOGIN_TIME` (`LOGIN_TIME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='普通用户审计日志表';

2、对数据库中所有用户都授予审计日志表的权限

审计原理其实就是用户在登录时刻执行init_connect所指定的内容(对审计日志表进行insert操作),那么必须要求所有的用户都要有此表的insert权限才行,

##为了文章的继续发展,注意这里并没有给普通用户'user_3'@'%'授权哦
mysql> select user,host from mysql.user;
+---------------+--------------+
| user          | host         |
+---------------+--------------+
| user_1        | %            |
| user_3        | %            |
| user_2        | 10.186.61.17 |
| mysql.session | localhost    |
| mysql.sys     | localhost    |
| root          | localhost    |
+---------------+--------------+
6 rows in set (0.00 sec)


mysql> grant insert on test_db.audit to 'user_1'@'%';
Query OK, 0 rows affected (0.01 sec)

mysql> grant insert on test_db.audit to 'user_2'@'10.186.61.17';
Query OK, 0 rows affected (0.01 sec)

3、动态设置,开启审计日志表

##动态设置init_connect参数
mysql> set global init_connect="insert into test_db.audit(USER,ADRESS) values(current_user(),substring_index(user(),'@',-1));";
Query OK, 0 rows affected (0.00 sec)

##补充说明current_user()可以查到当前登录的用户信息,substring_index()是一个截取函数,例如使用普通用户'user_2'@'10.186.61.17'
mysql> select current_user();
+---------------------+
| current_user()      |
+---------------------+
| user_2@10.186.61.17 |
+---------------------+
1 row in set (0.00 sec)
mysql> select substring_index(user(),'@',-1);
+--------------------------------+
| substring_index(user(),'@',-1) |
+--------------------------------+
| 10.186.61.17                   |
+--------------------------------+
1 row in set (0.00 sec)

为了永久生效,必须还要在配置文件中添加如下内容,

[mysqld]
init_connect="insert into test_db.audit(USER,ADRESS) values(current_user(),substring_index(user(),'@',-1));";

4、审计日志表结果说明

(1)对于普通用户,需要提前被授予一定权限,否则不会被记录到审计日志表中,并且会导致连接失败('user_3'@'%'用户因为没有审计表的insert权限,所以没有被记录)。

(2)对于普通用户,如果init_connect的内容有语法错误,依然会直接导致连接失败(无法执行init_connect的内容)。

(3)对于具有super权限的用户,在登录时并不会执行init_connect的内容(所以审计日志表里也没有super用户的记录)。

(4)对于密码过期的普通用户,登录数据库会直接连接失败,且不会记录也不会报错(无法执行init_connect的内容)。

##模拟对审计表有insert权限的普通用户登录数据库
[root@10-186-61-17 ~]# /data/mysql/3306/base/bin/mysql -uuser_2 -p -P6666 -h10.186.61.17
[root@10-186-61-17 ~]# /data/mysql/3306/base/bin/mysql -uuser_1 -p -P6666 -h10.186.61.17
[root@10-186-61-55 ~]# /data/mysql/3306/base/bin/mysql -uuser_1 -p -P6666 -h10.186.61.17

##模拟对审计表无insert权限的普通用户登录数据库
[root@10-186-61-17 ~]# /data/mysql/3306/base/bin/mysql -uuser_3 -p -P6666 -h10.186.61.17
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \\g.
Your MySQL connection id is 10
Server version: 5.7.25-log

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.

mysql> show databases;
ERROR 2013 (HY000): Lost connection to MySQL server during query


##使用root用户登录查看审计日志表记录结果展示
[root@10-186-61-17 ~]# /data/mysql/3306/base/bin/mysql -uroot -p -S /data/mysql/6666/data/mysqld.sock
Enter password:
……
mysql> select * from test_db.audit;
+----+---------------------+--------------+---------------------+
| ID | USER                | ADRESS       | LOGIN_TIME          |
+----+---------------------+--------------+---------------------+
|  1 | user_2@10.186.61.17 | 10.186.61.17 | 2022-05-26 14:17:35 |
|  2 | user_1@%            | 10.186.61.17 | 2022-05-26 14:18:12 |
|  3 | user_1@%            | 10.186.61.55 | 2022-05-26 14:19:34 |
+----+---------------------+--------------+---------------------+
3 rows in set (0.02 sec)

优点

(1)实现原理和操作步骤简单;

(2)几乎不影响MySQL性能。

缺点

(1)记录的内容简略(仅记录登录时刻执行init_connect所定义插入的值);

(2)只记录登入行为,不记录登录数据库后的行为;

(3)不会记录有super权限的用户的登录行为;

(4)密码过期的用户登录数据库,会直接连接失败,且不会记录也不会报错。

方案2,MariaDB审计插件

MariaDB开发的MariaDB审计插件,虽然具有一些仅适用于MariaDB的独特功能,但它也可以与MySQL一起使用。MariaDB审计插件所生成的审计日志记录内容包括:用户名和主机、执行了哪些查询、访问了哪些表以及更改了服务器变量等详情信息。

实现步骤

1、获取MariaDB的审计插件 - server_audit.so

##下载MariaDB Server安装包
##下载地址:https://mariadb.org/download/?t=mariadb&p=mariadb&r=10.2.43&os=Linux&cpu=x86_64&i=systemd&m=bkns
##本地解压后,在解压目录下找到审计插件`server_audit.so`
./mariadb/mariadb-10.2.43-linux-systemd-x86_64/lib/plugin/server_audit.so

2、将审计插件 server_audit.so复制到MySQL的plugin目录下,并授权

cp ./mariadb/mariadb-10.2.43-linux-systemd-x86_64/lib/plugin/server_audit.so /data/mysql/3306/base/lib/plugin/
chown -R mysql:mysql server_audit.so
chmod 755 server_audit.so

3、进入MySQL客户端,安装插件

##install审计插件
mysql> install plugin server_audit soname 'server_audit.so';
Query OK, 0 rows affected (0.07 sec)

##查看当前的插件信息
mysql> show plugins;
+----------------------------+----------+--------------------+--------------------+---------+
| Name                       | Status   | Type               | Library            | License |
+----------------------------+----------+--------------------+--------------------+---------+
 ……
| ngram                      | ACTIVE   | FTPARSER           | NULL               | GPL     |
| rpl_semi_sync_master       | ACTIVE   | REPLICATION        | semisync_master.so | GPL     |
| rpl_semi_sync_slave        | ACTIVE   | REPLICATION        | semisync_slave.so  | GPL     |
| SERVER_AUDIT               | ACTIVE   | AUDIT              | server_audit.so    | GPL     |
+----------------------------+----------+--------------------+--------------------+---------+
47 rows in set (0.00 sec)

4、配置说明

当安装完审计插件之后,MySQL中将有一些新的全局变量出现。这些变量就是用于配置审计日志的,例如配置审计日志的位置、日志大小、记录的信息格式等。

查看相关变量,

mysql> show variables like '%server_audit%';
+-------------------------------+-----------------------+
| Variable_name                 | Value                 |
+-------------------------------+-----------------------+
| server_audit_events           |                       |
| server_audit_excl_users       |                       |
| server_audit_file_path        | server_audit.log      |
| server_audit_file_rotate_now  | OFF                   |
| server_audit_file_rotate_size | 1000000               |
| server_audit_file_rotations   | 9                     |
| server_audit_incl_users       |                       |
| server_audit_loc_info         |                       |
| server_audit_logging          | OFF                   |
| server_audit_mode             | 1                     |
| server_audit_output_type      | file                  |
| server_audit_query_log_limit  | 1024                  |
| server_audit_syslog_facility  | LOG_USER              |
| server_audit_syslog_ident     | mysql-server_auditing |
| server_audit_syslog_info      |                       |
| server_audit_syslog_priority  | LOG_INFO              |
+-------------------------------+-----------------------+
16 rows in set (0.01 sec)

部分变量说明,

变量名获取源包名
server_audit_logging控制审计功能的开关;
server_audit_events指定记录的事件类型;
如果设置指定值,则审核日志只记录在设定值范围内的事件类型;
如果未设置,则每个事件类型都会记录到审核日志中(默认值选项)。
server_audit_file_path当server_audit_output_type=file时,设置日志文件的路径和文件名;
默认文件路径为datadir,默认文件名为server_audit.log 。
server_audit_file_rotate_now手工触发审计日志轮换;
即:设置为 ON 或 1 来强制日志文件轮换。
server_audit_file_rotate_size日志大小限制,达到了阈值,审计日志会自动轮换。
server_audit_file_rotations指定轮换后所保留的日志文件个数;
如果设置为 0,则日志永远不会轮换;
默认值为 9,即保存最多9个审计日志。
server_audit_incl_users指定用户列表,在内的用户,将被记录;
注:CONNECT 记录不受此变量的影响。
server_audit_excl_users指定用户列表,在内的用户,不会被记录;
如果用户在server_audit_incl_users中也指定了,用户活动仍会被记录;
注:CONNECT 记录不受此变量的影响。
server_audit_query_log_limit限制记录中查询字符串的长度。

配置示例,

##开启审计功能
mysql> SET GLOBAL server_audit_logging=ON;

##指定记录内容‘connect,query’,记录用户的连接和查询语句
SET global server_audit_events='connect,query';
##重命名审计日志
mysql> set global server_audit_file_path='mysql_3306_audit.log';

为了永久生效,必须还要在配置文件中添加如下内容,

##这里仅定义了两项变量值供参考
[server]
server_audit_logging=ON
server_audit_events=connect,query
…

5、审计日志结果说明

##模拟相关操作(查询结果篇幅过长,省略部分内容)
mysql> show databases;
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
mysql> select count(*) from sbtest1;
mysql> select * from sbtest1 limit 3;
+----+--------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| id | k      | c                                                                                                                       | pad                                                         |
+----+--------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
|  1 | 498670 | 31451373586-15688153734-79729593694-96509299839-83724898275-86711833539-78981337422-35049690573-51724173961-87474696253 | 98996621624-36689827414-04092488557-09587706818-65008859162 |
|  2 | 497778 | 21472970079-70972780322-70018558993-71769650003-09270326047-32417012031-10768856803-14235120402-93989080412-18690312264 | 04776826683-45880822084-77922711547-29057964468-76514263618 |
|  3 | 498956 | 49376827441-24903985029-56844662308-79012577859-40518387141-60588419212-24399130405-42612257832-29494881732-71506024440 | 26843035807-96849339132-53943793991-69741192222-48634174017 |
+----+--------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
3 rows in set (0.00 sec)
mysql> exit
Bye

[root@10-186-65-155 plugin]# /data/mysql/3306/base/bin/mysql -utest -p -S /data/mysql/3306/data/mysqld.sock
Enter password:
mysql> show databases;
mysql> use occdb
mysql> show tables;
mysql> create table abc like occ_application_config;
Query OK, 0 rows affected (10.09 sec)
mysql> exit
Bye

##查看datadir下审计日志文件
[root@10-186-65-155 data]# cd /data/mysql/3306/data/ && ll -h | grep 'audit.log'
-rw-r----- 1 mysql mysql  711 Apr 19 15:30 mysql_3306_audit.log
-rw-r----- 1 mysql mysql  329 Apr 19 15:26 server_audit.log

##查看审计日志`mysql_3306_audit.log`记录的内容
20220419 15:26:04,10-186-65-155,root,localhost,6,6,QUERY,,'set global server_audit_file_path=\\'mysql_3306_audit.log\\'',0
20220419 15:29:30,10-186-65-155,root,localhost,6,7,QUERY,,'show databases',0
20220419 15:29:38,10-186-65-155,root,localhost,6,8,QUERY,,'SELECT DATABASE()',0
20220419 15:29:38,10-186-65-155,root,localhost,6,10,QUERY,test,'show databases',0
20220419 15:29:38,10-186-65-155,root,localhost,6,11,QUERY,test,'show tables',0
20220419 15:29:43,10-186-65-155,root,localhost,6,17,QUERY,test,'show tables',0
20220419 15:30:04,10-186-65-155,root,localhost,6,18,QUERY,test,'select count(*) from sbtest1',0
20220419 15:30:25,10-186-65-155,root,localhost,6,19,QUERY,test,'select * from sbtest1 limit 3',0
20220419 15:36:14,10-186-65-155,root,localhost,6,0,DISCONNECT,test,,0
20220419 15:36:24,10-186-65-155,test,localhost,7,0,CONNECT,,,0
20220419 15:36:24,10-186-65-155,test,localhost,7,21,QUERY,,'select @@version_comment limit 1',0
20220419 15:36:28,10-186-65-155,test,localhost,7,22,QUERY,,'show databases',0
20220419 15:36:36,10-186-65-155,test,localhost,7,23,QUERY,,'SELECT DATABASE()',0
20220419 15:36:36,10-186-65-155,test,localhost,7,25,QUERY,occdb,'show databases',0
20220419 15:36:36,10-186-65-155,test,localhost,7,26,QUERY,occdb,'show tables',0
20220419 15:36:39,10-186-65-155,test,localhost,7,28,QUERY,occdb,'show tables',0
20220419 15:36:55,10-186-65-155,test,localhost,7,29,QUERY,occdb,'create table abc like occ_application_config',0
20220419 15:37:11,10-186-65-155,test,localhost,7,0,DISCONNECT,occdb,,0

补充:下发的错误语句,或者连接失败等语句,审计日志依然会记录在内。

##模拟错误语句和连接失败情景
mysql> show creates table abc;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'creates table abc' at line 1
mysql> exit
Bye
[root@10-186-65-155 plugin]# /data/mysql/3306/base/bin/mysql -utest -p -S /data/mysql/3306/data/mysqld.sock
Enter password:
ERROR 1045 (28000): Access denied for user 'test'@'localhost' (using password: NO)

##查看审计日志记录的相关内容
……
20220419 15:42:16,10-186-65-155,test,localhost,9,45,QUERY,occdb,'show creates table abc',1064
20220419 15:42:34,10-186-65-155,test,localhost,9,0,DISCONNECT,occdb,,0
20220419 15:42:48,10-186-65-155,test,localhost,10,0,FAILED_CONNECT,,,1045

根据以上记录的内容可以总结审计日志的记录格式,

[timestamp],[serverhost],[username],[host],[connectionid],[queryid],[operation],[database],[object],[retcode]

优点

(1)使用xml格式和内容明确且详细;

(2)审计粒度细:例如可通过server_audit_events和server_audit_incl_users等参数指定需要审计的内容;

(3)审计日志维护管理方便:自带审计日志切割轮换参数;

(4)审计日志会记录下发的错误语句、连接失败信息等。

缺点

(1)对MySQL性能有一定影响。

方案3,McAfee审计插件

所属McAfee公司McAfee审计插件,专门为MySQL提供审计功能。其设计重点是安全和审计要求。可以独立的作为审计插件,实现MySQL的审计功能,实现步骤与MariaDB审计插件类似。

实现步骤

1、获取审计插件 - libaudit_plugin.so

##下载插件
##下载地址:https://github.com/mcafee/mysql-audit/releases
##本地解压后,在解压目录下找到审计插件libaudit_plugin.so
./audit-plugin-mysql-5.7-1.1.11-985/lib/libaudit_plugin.so

2、将审计插件server_audit.so复制到MySQL的plugin目录下,并授权

cp ./audit-plugin-mysql-5.7-1.1.11-985/lib/libaudit_plugin.so /data/mysql/6666/base/lib/plugin/
chown -R mysql:mysql libaudit_plugin.so
chmod 755 libaudit_plugin.so

3、进入MySQL客户端,安装插件

mysql> INSTALL PLUGIN AUDIT SONAME 'libaudit_plugin.so';
Query OK, 0 rows affected (1.08 sec)
 
mysql> show plugins;
+----------------------------+----------+--------------------+--------------------+---------+
| Name                       | Status   | Type               | Library            | License |
+----------------------------+----------+--------------------+--------------------+---------+
……
| rpl_semi_sync_master       | ACTIVE   | REPLICATION        | semisync_master.so | GPL     |
| rpl_semi_sync_slave        | ACTIVE   | REPLICATION        | semisync_slave.so  | GPL     |
| AUDIT                      | ACTIVE   | AUDIT              | libaudit_plugin.so | GPL     |
+----------------------------+----------+--------------------+--------------------+---------+
47 rows in set (0.00 sec)

4、配置说明

同Mariadb的审计插件类似,当安装完审计插件之后,MySQL中将有一些新的全局变量,用于配置审计日志相关属性。

mysql> show variables like '%audit%';
+---------------------------------+-----------------------------------------------------------------------------------------------                  
| Variable_name                   | Value                                                                                                           
+---------------------------------+-----------------------------------------------------------------------------------------------                  
| audit_before_after              | after                                                                                                           
| audit_checksum                  |                                                                                                                 
| audit_client_capabilities       | OFF                                                                                                             
| audit_delay_cmds                |                                                                                                                 
| audit_delay_ms                  | 0                                                                                                               
| audit_force_record_logins       | OFF                                                                                                             
| audit_header_msg                | ON                                                                                                              
| audit_json_file                 | OFF                                                                                                             
| audit_json_file_bufsize         | 1                                                                                                               
| audit_json_file_flush           | OFF                                                                                                             
| audit_json_file_retry           | 60                                                                                                              
| audit_json_file_sync            | 0                                                                                                               
| audit_json_log_file             | mysql-audit.json                                                                                                
| audit_json_socket               | OFF                                                                                                             
| audit_json_socket_name          | /var/run/db-audit/mysql.audit__data_mysql_6666_data_6666                                                        
| audit_json_socket_retry         | 10                                                                                                              
| audit_json_socket_write_timeout | 1000                                                                                                            
| audit_offsets                   |                                                                                                                 
| audit_offsets_by_version        | ON                                                                                                              
| audit_password_masking_cmds     | CREATE_USER,GRANT,SET_OPTION,SLAVE_START,CREATE_SERVER,ALTER_SERVER,CHANGE_MASTER,UPDATE                        
| audit_password_masking_regex    | 
| audit_record_cmds               |                                                                                                                 
| audit_record_objs               |                                                                                                                 
| audit_sess_connect_attrs        | ON                                                                                                              
| audit_socket_creds              | ON                                                                                                              
| audit_uninstall_plugin          | OFF                                                                                                             
| audit_validate_checksum         | ON                                                                                                              
| audit_validate_offsets_extended | ON                                                                                                              
| audit_whitelist_cmds            | BEGIN,COMMIT,PING                                                                                               
| audit_whitelist_users           |                                                                                                                 
+---------------------------------+-----------------------------------------------------------------------------------------------                  
30 rows in set (0.01 sec)

部分变量说明,

变量名获取源包名
audit_json_file是否开启审计  ON/OFF;
默认值:OFF。
audit_json_log_file设置日志文件的路径和文件名;
默认值:mysql-audit.json,默认路径:datadir。
audit_record_cmds设置要记录的语句类型,例如:insert,update,delete ;
默认记录所有的命令。
audit_record_objs设置要记录到审计跟踪的对象(表),例如:database.table,可以使用通配符。
audit_whitelist_cmds设置不需要记录的语句类型。
audit_whitelist_users设置不需要记录的用户。
audit_before_after控制是在执行当前 SQL 语句之前还是之后写入其日志记录,或两者兼而有之。可能的值为'before'、'after'或'both',默认为'after'。
audit_json_file_flush手工进行轮换日志。
audit_json_file_sync控制日志刷写周期json,如果此变量的值为N(N≠0),则审计日志将在每N次写入后同步到磁盘。默认值:0 。

配置示例,

mysql> set global audit_json_file=on;
Query OK, 0 rows affected (0.01 sec)

mysql> set global audit_json_log_file='mysql_6666_audit.log';
Query OK, 0 rows affected (0.00 sec)

为了永久生效,必须还要在配置文件中添加如下内容,

##这里仅定义了两项变量值供参考
[mysqld]
audit_json_file=on
audit_record_cmds='query_type'  ##自定义需要记录的语句类型
……

5、审计日志结果说明

##模拟相关操作(查询结果篇幅过长,省略部分内容)
[root@10-186-65-155 plugin]# /data/mysql/6666/base/bin/mysql -uroot -p -S /data/mysql/6666/data/mysqld.sock
Enter password:
Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.

mysql> show databases;
mysql> select count(*) from mysql.user;
mysql> create database test;
mysql> use test;
Database changed
mysql> create table aaa(id int,name varchar(20),primary key(id));
mysql> insert into aaa values (1,'zhangsan'),(2,'lisi');
mysql> exit
Bye
[root@10-186-65-155 plugin]# /data/mysql/6666/base/bin/mysql -utest -p -S /data/mysql/6666/data/mysqld.sock
Enter password:
mysql> use test;
mysql> select * from aaa;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
+----+----------+

 ##查看datadir下的审计日志记录内容
 "msg-type":"activity","date":"1650361253128","thread-id":"11","query-id":"0","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","cmd":"Connect","query":"Connect"
"msg-type":"activity","date":"1650361253129","thread-id":"11","query-id":"145","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"select","query":"select @@version_comment limit 1"
"msg-type":"activity","date":"1650361255866","thread-id":"11","query-id":"146","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"4","status":"0","cmd":"show_databases","objects":["db":"information_schema","name":"/data/mysql/6666/tmp/#sql_1b0f_0","obj_type":"TABLE"],"query":"show databases"
"msg-type":"activity","date":"1650361283561","thread-id":"11","query-id":"147","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"select","objects":["db":"mysql","name":"user","obj_type":"TABLE"],"query":"select count(*) from mysql.user"
"msg-type":"activity","date":"1650361313234","thread-id":"11","query-id":"148","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","status":"0","cmd":"create_db","query":"create database test"
"msg-type":"activity","date":"1650361318055","thread-id":"11","query-id":"149","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"select","query":"SELECT DATABASE()"
"msg-type":"activity","date":"1650361318055","thread-id":"11","query-id":"150","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"Init DB","objects":["db":"test","obj_type":"DATABASE"],"query":"Init DB"
"msg-type":"activity","date":"1650361318057","thread-id":"11","query-id":"151","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"5","status":"0","cmd":"show_databases","objects":["db":"information_schema","name":"/data/mysql/6666/tmp/#sql_1b0f_0","obj_type":"TABLE"],"query":"show databases"
"msg-type":"activity","date":"1650361318057","thread-id":"11","query-id":"152","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","status":"0","cmd":"show_tables","objects":["db":"information_schema","name":"/data/mysql/6666/tmp/#sql_1b0f_0","obj_type":"TABLE"],"query":"show tables"
"msg-type":"activity","date":"1650361361491","thread-id":"11","query-id":"153","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","status":"0","cmd":"create_table","objects":["db":"test","name":"aaa","obj_type":"TABLE"],"query":"create table aaa(id int,name varchar(20),primary key(id))"
"msg-type":"activity","date":"1650361424702","thread-id":"11","query-id":"154","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"2","status":"0","cmd":"insert","objects":["db":"test","name":"aaa","obj_type":"TABLE"],"query":"insert into aaa values (1,'zhangsan'),(2,'lisi')"
"msg-type":"activity","date":"1650361432156","thread-id":"11","query-id":"155","user":"root","priv_user":"root","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5151","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5151","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","cmd":"Quit","query":"Quit"
"msg-type":"activity","date":"1650361439497","thread-id":"12","query-id":"0","user":"test","priv_user":"test","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5162","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5162","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","cmd":"Connect","query":"Connect"
"msg-type":"activity","date":"1650361439498","thread-id":"12","query-id":"156","user":"test","priv_user":"test","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5162","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5162","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"select","query":"select @@version_comment limit 1"
"msg-type":"activity","date":"1650361443135","thread-id":"12","query-id":"157","user":"test","priv_user":"test","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5162","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5162","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"select","query":"SELECT DATABASE()"
"msg-type":"activity","date":"1650361443136","thread-id":"12","query-id":"158","user":"test","priv_user":"test","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5162","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5162","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"Init DB","objects":["db":"test","obj_type":"DATABASE"],"query":"Init DB"
"msg-type":"activity","date":"1650361443138","thread-id":"12","query-id":"159","user":"test","priv_user":"test","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5162","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5162","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"5","status":"0","cmd":"show_databases","objects":["db":"information_schema","name":"/data/mysql/6666/tmp/#sql_1b0f_0","obj_type":"TABLE"],"query":"show databases"
"msg-type":"activity","date":"1650361443139","thread-id":"12","query-id":"160","user":"test","priv_user":"test","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5162","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5162","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"1","status":"0","cmd":"show_tables","objects":["db":"information_schema","name":"/data/mysql/6666/tmp/#sql_1b0f_0","obj_type":"TABLE"],"query":"show tables"
"msg-type":"activity","date":"1650361454500","thread-id":"12","query-id":"162","user":"test","priv_user":"test","ip":"","host":"localhost","_os":"linux-glibc2.12","_client_name":"libmysql","_pid":"5162","_client_version":"5.7.25","_platform":"x86_64","program_name":"mysql","pid":"5162","os_user":"root","appname":"/data/mysql/6666/base/bin/mysql","rows":"2","status":"0","cmd":"select","objects":["db":"test","name":"aaa","obj_type":"TABLE"],"query":"select * from aaa"

根据以上的记录内容可总结审计日志的记录格式,

审计日志使用的是json格式记录,如下为一条记录内容

	"msg-type": "activity",
	"date": "1650361454500",
	"thread-id": "12",
	"query-id": "162",
	"user": "test",
	"priv_user": "test",
	"ip": "",
	"host": "localhost",
	"_os": "linux-glibc2.12",
	"_client_name": "libmysql",
	"_pid": "5162",
	"_client_version": "5.7.25",
	"_platform": "x86_64",
	"program_name": "mysql",
	"pid": "5162",
	"os_user": "root",
	"appname": "/data/mysql/6666/base/bin/mysql",
	"rows": "2",
	"status": "0",
	"cmd": "select",
	"objects": [
		"db": "test",
		"name": "aaa",
		"obj_type": "TABLE"
	],
	"query": "select * from aaa"

优点

(1)使用json格式和内容明确且详细;

(2)审计粒度细:例如可通过audit_record_cmds和audit_record_objs等指定需要审计的内容;

(3)记录连接失败的语句(audit_force_record_logins参数值为on条件下);

(4)审计日志刷写策略可控,可通过audit_json_file_sync参数控制。

缺点

(1)对MySQL性能有一定影响;

(2)不记录下发错误的语句;

(3)审计日志维护管理不便,无自带审计日志切割轮换参数。

补充说明

Percona公司开发的审计插件audit_log.so(可以在Percona Server包中获取),目前无法直接install到社区版MySQL中使用,

mysql> INSTALL PLUGIN audit_log SONAME 'audit_log.so';
ERROR 1126 (HY000): Can't open shared library '/data/mysql/7777/base/lib/plugin/audit_log.so' (errno: 2 /data/mysql/7777/base/lib/plugin/audit_log.so: undefined symbol: plugin_thdvar_safe_update)

本文介绍的三种实现审计功能的方案,各个方案都有自己的优缺点。如果仅仅记录普通用户的登录信息就能够满足审计需求,那就选择第一种方案(init_connect参数)再好不过了。如果想要实现更全面的审计功能,那么第二种或者第三种方案会更加合适。根据审计需求来选择自己认为最合适的方案。另外,在实际使用之前,请务必做好充分的测试工作。

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

近期更新的文章:

"--"注释在Oracle和MySQL下的区别

最近碰到的一些问题

1024的一个小福利

Oracle 19c对VARCHAR2的限制

提供使用国密算法的MySQL

近期的热文:

"红警"游戏开源代码带给我们的震撼

文章分类和索引:

公众号1100篇文章分类和索引

以上是关于MySQL的审计功能实现方案的主要内容,如果未能解决你的问题,请参考以下文章

利用mysql注释实现无硬件成本的审计功能

mysql利用init-connect增加访问审计功能的实现

如何实现MySQL数据库使用情况的审计

mysql审计实现方法

mysql实现访问审计

MMM高可用mysql方案