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系统变量是以字节为单位的缓冲区大小。在服务器启动时设置此变量以更改缓冲区大小。该插件使用单个缓冲区,它在初始化时分配并在终止时删除。该插件不会为非异步写入策略分配此缓冲区。

异步日志记录策略具有以下特点:

  1. 对服务器性能和可伸缩性的影响最小。
  2. 在尽可能短的时间内阻塞生成审计事件的线程;也就是说,分配缓冲区的时间加上将事件复制到缓冲区的时间。
  3. 输出进入缓冲区。一个单独的线程处理从缓冲区到日志文件的写入。
    使用异步日志记录时,如果在写入文件期间出现问题或插件未完全关闭(例如,在服务器主机意外退出的情况下),则日志文件的完整性可能会受到损害。为了降低这种风险,设置 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

posted @ 2023-03-28 09:57  www.cqdba.cn  阅读(207)  评论(0编辑  收藏  举报