Mysql 如何查看当下加密的审计日志
适用范围
mysql 8.+
问题概述
Mysql 8.0.30 ,开启了审计加密和压缩,在这种情况下,用户想查看当下准实时的审计日志信息,但是发现审计日志文件的时间并没有发生变化。强制解密当前审计日志文件,解密失败。
现象如下:
环境准备
# 查看当前审计的密匙
mysql> SELECT KEY_ID FROM performance_schema.keyring_keys
-> WHERE KEY_ID LIKE 'audit_log%'
-> ORDER BY KEY_ID;
+-----------------------------+
| KEY_ID |
+-----------------------------+
| audit_log-20230320T082416-1 |
|+-----------------------------+
# 查看审计密码
mysql> SELECT audit_log_encryption_password_get('audit_log-20230320T082416-1');
+------------------------------------------------------------------+
| audit_log_encryption_password_get('audit_log-20230320T082416-1') |
+------------------------------------------------------------------+
| !W9RdU3%no1HSXPa |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
#审计参数
mysql> show variables like '%audit%' ;
+--------------------------------------+-------------------------------------+
| Variable_name | Value |
+--------------------------------------+-------------------------------------+
| audit_log_buffer_size | 1048576 |
| audit_log_compression | GZIP |
| audit_log_connection_policy | ALL |
| audit_log_current_session | OFF |
| audit_log_disable | OFF |
| audit_log_encryption | AES |
| audit_log_exclude_accounts | |
| audit_log_file | /u01/mysql/data/uat1/logs/audit.log |
| audit_log_filter_id | 2 |
| audit_log_flush | OFF |
| audit_log_format | NEW |
| audit_log_format_unix_timestamp | OFF |
| audit_log_include_accounts | |
| audit_log_max_size | 0 |
| audit_log_password_history_keep_days | 0 |
| audit_log_policy | ALL |
| audit_log_prune_seconds | 0 |
| audit_log_read_buffer_size | 32768 |
| audit_log_rotate_on_size | 104857600 |
| audit_log_statement_policy | ALL |
| audit_log_strategy | ASYNCHRONOUS |
+--------------------------------------+-------------------------------------+
21 rows in set (0.00 sec)
#当前审计策略,和审计用户
mysql> select * from mysql.audit_log_filter ;
+-----------------+-----------------------------------------------+
| NAME | FILTER |
+-----------------+-----------------------------------------------+
| log_all | {"filter": {"log": true}} |
| log_conn_events | {"filter": {"class": {"name": "connection"}}} |
+-----------------+-----------------------------------------------+
2 rows in set (0.00 sec)
mysql> select * from mysql.audit_log_user ;
+------+-----------+-----------------+
| USER | HOST | FILTERNAME |
+------+-----------+-----------------+
| root | localhost | log_all |
| % | | log_conn_events |
+------+-----------+-----------------+
2 rows in set (0.00 sec)
问题还原
# 审计日志文件时间 Mar 20 16:24
[root@s2ahuzcloud01 logs]# ll
total 24
-rw-r----- 1 mysql mysql 48 Mar 20 16:24 audit.log.gz.20230320T082416-1.enc
# 模拟登录失败
[root@s2ahuzcloud01 logs]# mysql -u root -p'123' --socket=/u01/mysql/data/uat1/run/mysql3306.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
# 审计时间并没有发生变化
[root@s2ahuzcloud01 logs]# ll
total 24
-rw-r----- 1 mysql mysql 48 Mar 20 16:24 audit.log.gz.20230320T082416-1.enc
# 强制解密 失败
[root@s2ahuzcloud01 logs]# openssl enc -d -aes-256-cbc -pass pass:'!W9RdU3%no1HSXPa' -md sha256 -in audit.log.gz.20230320T082416-1.enc -out audit.log.gz
bad decrypt
140368205059984:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:592:
问题原因
1.由于日志未完成切换,还不是一个完整的加密文件 ,所以不能直接对没有切换的审计文件进行解密
2.这是由于审计日志开启了异步写入的机制,所以不能及时看到审计日志文件的更新
审计日志插件可以使用多种日志写入策略中的任何一种。无论策略如何,日志记录都是在尽力而为的基础上进行的,不保证一致性。
要指定写入策略,请 audit_log_strategy在服务器启动时设置系统变量。
默认情况下,策略值为 ASYNCHRONOUS,插件异步记录到缓冲区,等待缓冲区是否已满。可以告诉插件不要等待 ( PERFORMANCE) 或同步记录,使用文件系统缓存 ( SEMISYNCHRONOUS) 或 sync()在每次写入请求后通过调用强制输出 ( SYNCHRONOUS)。
[mysqld]
audit_log_strategy=SYNCHRONOUS
# 该参数需重启DB
对于异步写入策略, audit_log_buffer_size系统变量是以字节为单位的缓冲区大小。在服务器启动时设置此变量以更改缓冲区大小。该插件使用单个缓冲区,它在初始化时分配并在终止时删除。该插件不会为非异步写入策略分配此缓冲区。
异步日志记录策略具有以下特点:
- 对服务器性能和可伸缩性的影响最小。
- 在尽可能短的时间内阻塞生成审计事件的线程;也就是说,分配缓冲区的时间加上将事件复制到缓冲区的时间。
- 输出进入缓冲区。一个单独的线程处理从缓冲区到日志文件的写入。
使用异步日志记录时,如果在写入文件期间出现问题或插件未完全关闭(例如,在服务器主机意外退出的情况下),则日志文件的完整性可能会受到损害。为了降低这种风险,设置 audit_log_strategy为使用同步日志记录。
策略的一个缺点PERFORMANCE是它会在缓冲区已满时丢弃事件。对于负载很重的服务器,审计日志可能缺少事件。
解决方案
该问题只需要强制完成一次日志的切换即可
1.由于我们设置了audit_log_rotate_on_size 大于 0,无法手动设置 audit_log_flush让其生效,所以我可以通通过设置参数的方案让期切换。
#8.0.31 前需手动移动文件
cd /mysql/data/$env/logs/
logname=`/usr/bin/ls -l audit.log.gz*enc|awk '{print $9}'`
/usr/bin/mv $logname `date +%Y%m%d%M%S`.${logname}
#然后在手动刷新
set global audit_log_rotate_on_size=0 ;
set global audit_log_flush=on ;
#8.0.31后可以执行以下命令
set global audit_log_rotate_on_size=0 ;
SELECT audit_log_rotate();
2.我们可以通过 audit_log_encryption_password_set() 函数重设加密密码,触发让其强制切换。
#重设密码
mysql> select audit_log_encryption_password_set('123') ;
+------------------------------------------+
| audit_log_encryption_password_set('123') |
+------------------------------------------+
| 1 |
+------------------------------------------+
1 row in set (0.01 sec)
# 日志发换了切换
[root@s2ahuzcloud01 logs]# ll
total 24
-rw-r----- 1 mysql mysql 752 Mar 20 16:24 audit.20230320T082416.log.gz.20230314T031345-1.enc
-rw-r----- 1 mysql mysql 48 Mar 20 16:24 audit.log.gz.20230320T082416-1.enc
#解密 用原来的密码
[root@s2ahuzcloud01 logs]# openssl enc -d -aes-256-cbc -pass pass:'!W9RdU3%no1HSXPa' -md sha256 -in audit.20230320T082416.log.gz.20230314T031345-1.enc -out audit.20230320T082416.log.gz
[root@s2ahuzcloud01 logs]# ll
total 24
-rw-r--r-- 1 root root 729 Mar 20 16:24 audit.20230320T082416.log.gz
-rw-r----- 1 mysql mysql 752 Mar 20 16:24 audit.20230320T082416.log.gz.20230314T031345-1.enc
-rw-r----- 1 mysql mysql 48 Mar 20 16:24 audit.log.gz.20230320T082416-1.enc
#解压缩
[root@s2ahuzcloud01 logs]# gunzip audit.20230320T082416.log.gz > audit.20230320T082416.log
# 查看刚刚登录失败的日志
# cat audit.20230320T082416.log
...
<AUDIT_RECORD>
<TIMESTAMP>2023-03-20T08:39:52 UTC</TIMESTAMP>
<RECORD_ID>7_2023-03-20T08:24:16</RECORD_ID>
<NAME>Connect</NAME>
<CONNECTION_ID>12</CONNECTION_ID>
<STATUS>1045</STATUS>
<STATUS_CODE>1</STATUS_CODE>
<USER>root</USER>
<OS_LOGIN/>
<HOST>localhost</HOST>
<IP/>
<COMMAND_CLASS>connect</COMMAND_CLASS>
<CONNECTION_TYPE>Socket</CONNECTION_TYPE>
<PRIV_USER>root</PRIV_USER>
<PROXY_USER/>
<DB/>
</AUDIT_RECORD>
...
参考文档
https://dev.mysql.com/doc/refman/8.0/en/audit-log-logging-configuration.html#audit-log-file-name
https://dev.mysql.com/doc/refman/8.0/en/audit-log-logging-configuration.html