8.4.5.5 配置审计日志记录特征
本节描述了如何配置审计日志记录特征,例如,audit log插件写入事件的文件、事件格式是否启用压缩和加密,以及空间管理。
关于影响审计日志的函数和系统变量,见审计日志函数,和审计日志选项和变量。
审计日志插件也可以根据事件内容或事件来源控制将哪些事件写入到审计日志文件中。见第8.4.5.7节,“审计日志过滤”。
要配置审计日志文件名,在服务器启动时设置audit_log_file
系统变量。默认名称是服务器数据目录中的audit.log
。为了最佳安全性,写入审计日志到只有MySQL服务器和有合法理由查看日志的用户可以访问的目录。
插件将audit_log_file
值解释为可选前缀、基本名称和可选后缀组成。如果启用压缩或加密,实际使用的文件名与配置文件名不同,因为它有额外的后缀:
-
如果启用压缩,插件添加
.gz
后缀。 -
如果加密已启用,插件将添加一个后缀
.
,其中pwd_id
.encpwd_id
指示用于日志文件操作的加密密码。审核日志插件将加密密码存储在keyring中;请参阅加密审核日志文件。
有效的审核日志文件名是根据配置文件名添加适用压缩和加密后缀后的结果。例如,如果配置了audit_log_file
值为 audit.log
,那么有效的文件名将是以下表格中所示的值。
Enabled Features | Effective File Name |
---|---|
无压缩或加密 | audit.log |
压缩 | audit.log.gz |
加密 | audit.log. |
压缩、加密 | audit.log.gz. |
pwd_id
表示用于加密或解密文件的密码ID。 pwd_id
格式为 pwd_timestamp-seq
,其中:
-
pwd_timestamp
是一个UTC值,在
格式表示密码创建的时间。YYYYMMDD
Thhmmss
-
seq
是一个顺序号。具有相同pwd_timestamp
值的密码的顺序号从 1 开始递增。
以下是一些示例 pwd_id
密码 ID 值:
20190403T142359-1
20190403T142400-1
20190403T142400-2
为了在密钥环中存储密码,审核日志插件将 pwd_id
值的前缀设置为 audit_log-
。如前所示的示例密码 ID 值对应的密钥环 ID 是:
audit_log-20190403T142359-1
audit_log-20190403T142400-1
audit_log-20190403T142400-2
审核日志插件当前用于加密的密码的 ID 是具有最大的 pwd_timestamp
值的那个。如果多个密码具有相同的 pwd_timestamp
值,当前密码 ID 是顺序号最大的那个。例如,在前面的密码 ID 集合中,有两个具有最大的时间戳 20190403T142400
,所以当前密码 ID 是顺序号最大的那个 (2
).
审核日志插件在初始化和终止时基于有效的审核日志文件名执行某些操作:
-
在初始化时,插件检查是否已经存在名为审核日志文件名的文件,如果存在则重命名它(在这种情况下,插件假设前一个服务器调用退出了异常地运行审核日志插件)。然后,插件写入一个新的空审核日志文件。
-
在终止时,插件重命名审核日志文件。
-
文件重命名(是否在插件初始化或终止过程中)遵循自动大小基准日志文件旋转的规则;见手动 Audit Log 文件旋转。
要配置 audit 日志文件格式,服务器启动时设置audit_log_format
系统变量。可用的格式有:
-
NEW
: 新式 XML 格式。这是默认值。 -
OLD
: 旧式 XML 格式。 -
JSON
: JSON 格式。将 audit 日志写入为 JSON 数组。只有这个格式支持可选的查询时间和大小统计信息。
每个格式的详细信息,见第8.4.5.4节,“Audit Log 文件格式”。
MySQL Enterprise Audit 提供了自动清除内存缓存的刷新间隔能力。使用audit_log_flush_interval_seconds
系统变量配置的刷新任务默认值为零,这意味着该任务不被调度运行。
当任务配置运行(值非零)时,MySQL Enterprise Audit 尝试在初始化时调用调度器组件,并配置定期、重复地刷新其内存缓存:
-
如果审核日志找不到调度注册服务的实现,它将不安排刷新继续加载。
-
审核日志实现了
dynamic_loader_services_loaded_notification
服务,并监听mysql_scheduler
的新注册,以便审核日志可以将其预定的任务注册到新的加载的调度器中。 -
审核日志只在首次加载的调度器实现中注册自己。
类似地,MySQL Enterprise Audit 在卸载时调用scheduler
组件,并取消已安排的定期刷新。它保持对调度注册服务的活动引用,直到预定的任务被卸载,以确保scheduler
组件不能在有活动预定作业时被卸载。所有执行调度器和任务的结果写入服务器错误日志。
以安排审核日志刷新任务:
-
确认
scheduler
组件已加载并启用。该组件默认启用(见component_scheduler.enabled
)。SELECT * FROM mysql.components; +--------------+--------------------+----------------------------+ | component_id | component_group_id | component_urn | +--------------+--------------------+----------------------------+ | 1 | 1 | file://component_scheduler | +--------------+--------------------+----------------------------+
-
如果尚未安装(见第8.4.5.2节,“MySQL企业版审核安装或卸载”),安装
audit_log
插件。 -
使用
audit_log_flush_interval_seconds
启动服务器,并将值设置为大于59的数字。该值的上限因平台而异。例如,配置flush任务以每2分钟重复:$> mysqld --audit_log_flush_interval_seconds=120
更多信息,请见
audit_log_flush_interval_seconds
系统变量。
在 MySQL 8.4 中,您可以使用 JSON 格式的日志文件,添加可选数据字段来显示查询时间、发送和接收字节数、客户端返回行数和检查行数。这些数据在慢查询日志中可用,以审核日志中类似地帮助检测活动分析中的异常值。这些扩展数据字段只能在 JSON 格式的审核日志(audit_log_format=JSON
)中添加,而不是默认设置。
查询统计信息通过您设置的审核日志过滤函数传递给审核日志。这些服务名为 mysql_audit_print_service_longlong_data_source
和 mysql_audit_print_service_double_data_source
。您可以选择每个输出项的数据类型。对于查询时间,longlong
输出微秒值,而 double
输出秒值。
您使用audit_log_filter_set_filter()
审核日志函数添加查询统计信息,作为 JSON 过滤语法中的 service
元素,例如:
SELECT audit_log_filter_set_filter('QueryStatistics',
'{ "filter": { "class": { "name": "general", "event": { "name": "status", "print" : '
'{ "service": { "implementation": "mysql_server", "tag": "query_statistics", "element": [ '
'{ "name": "query_time", "type": "double" }, '
'{ "name": "bytes_sent", "type": "longlong" }, '
'{ "name": "bytes_received", "type": "longlong" }, '
'{ "name": "rows_sent", "type": "longlong" }, '
'{ "name": "rows_examined", "type": "longlong" } ] } } } } } }');
要使 bytes_sent
和 bytes_received
字段被填充,系统变量log_slow_extra
必须设置为 ON
。如果系统变量的值是 OFF
,日志文件中将写入这些字段的 null 值。
如果您想停止收集查询统计信息,使用audit_log_filter_set_filter()
审核日志函数删除过滤器,例如:
SELECT audit_log_filter_remove_filter('QueryStatistics');
可以启用任何日志格式的审核日志文件压缩。
要配置审计日志文件压缩,设置服务器启动时的audit_log_compression
系统变量。允许值是 NONE
(无压缩;默认)和GZIP
(GNU Zip压缩)。
如果同时启用了压缩和加密,压缩发生在加密之前。要手动恢复原始文件,首先解密,然后解压缩。见手动解压缩和解密审计日志文件。
可以对任何日志格式启用审计日志文件加密。加密基于用户定义的密码(除了audit log插件生成的初始密码)。要使用这个功能,MySQL keyring必须启用,因为审计日志使用它来存储密码。任何keyring组件或插件都可以使用;见第8.4.4节,“MySQL Keyring”。
要配置审计日志文件加密,设置服务器启动时的audit_log_encryption
系统变量。允许值是 NONE
(无加密;默认)和AES
(AES-256-CBC加密)
要在运行时设置或获取加密密码,使用这些审计日志函数:
-
设置当前加密密码,调用
audit_log_encryption_password_set()
函数。这個函数将新密码存储在钥匙环中。如果启用了加密,它还执行日志文件旋转操作,重命名当前日志文件,并开始使用新密码加密的新日志文件。文件重命名遵循自动大小基日志文件旋转的规则;见手动 Audit Log 文件旋转。如果系统变量
audit_log_password_history_keep_days
不为零,调用audit_log_encryption_password_set()
也会导致旧的归档 Audit Log 加密密码过期。关于 Audit Log 密码历史,包括密码归档和过期,请参阅该变量的描述。 -
获取当前加密密码,调用
audit_log_encryption_password_get()
函数没有参数。要获取指定 ID 的密码,传递一个参数,指定当前密码或归档密码的钥匙环 ID。确定哪些 Audit Log 钥匙环 ID 存在,查询性能 Schema
keyring_keys
表:mysql> SELECT KEY_ID FROM performance_schema.keyring_keys WHERE KEY_ID LIKE 'audit_log%' ORDER BY KEY_ID; +-----------------------------+ | KEY_ID | +-----------------------------+ | audit_log-20190415T152248-1 | | audit_log-20190415T153507-1 | | audit_log-20190416T125122-1 | | audit_log-20190416T141608-1 | +-----------------------------+
关于审计日志加密函数的更多信息,请参见审计日志函数。
当审计日志插件初始化时,如果发现日志文件加密已启用,它将检查keyring是否包含审计日志加密密码。如果没有,插件将自动生成一个随机的初始加密密码并将其存储在keyring中。要获取这个密码,请调用audit_log_encryption_password_get()
。
如果同时启用了压缩和加密,压缩将在加密之前发生。要手动恢复原始文件,首先解密,然后解压缩。请参见手动解压缩和解密审计日志文件。
可以使用标准工具来解压缩和解密审计日志文件。这应该只对已经关闭(归档)且不再使用的日志文件进行,不要对当前由审计日志插件写入的日志文件。您可以通过检查文件名是否包含时间戳来识别归档日志文件,因为审计日志插件将在文件名中添加时间戳。
对于本讨论,假设audit_log_file
设置为audit.log
。在这种情况下,归档的审计日志文件将具有以下表格所示的名称。
Enabled Features | Archived File Name |
---|---|
无压缩或加密 | audit. |
压缩 | audit. |
加密 | audit. |
压缩、加密 | audit. |
如审核日志文件命名约定所讨论的,pwd_id
格式是pwd_timestamp-seq
。因此,存档加密日志文件实际包含两个时间戳。第一个表示文件旋转时间,第二个表示加密密码创建时间。
考虑以下存档加密日志文件名:
audit.20190410T205827.log.20190403T185337-1.enc
audit.20190410T210243.log.20190403T185337-1.enc
audit.20190415T145309.log.20190414T223342-1.enc
audit.20190415T151322.log.20190414T223342-2.enc
每个文件名都有唯一的旋转时间戳。相比之下,密码时间戳不唯一:
-
第两个文件拥有相同的密码ID和序列号(
20190403T185337-1
)。它们拥有相同的加密密码。 -
第二个文件拥有相同的密码ID(
20190414T223342
)但不同的序列号(1
,2
)。这些文件拥有不同的加密密码。
手动解压缩一个压缩日志文件,请使用gunzip、gzip -d或等效命令。例如:
gunzip -c audit.timestamp.log.gz > audit.timestamp.log
手动解密加密日志文件,使用openssl命令。例如:
openssl enc -d -aes-256-cbc -pass pass:password -md sha256
-in audit.timestamp.log.pwd_id.enc
-out audit.timestamp.log
要执行该命令,您必须获得password
,加密密码。以此方式获取密码,使用audit_log_encryption_password_get()
。例如,如果 audit 日志文件名是 audit.20190415T151322.log.20190414T223342-2.enc
,密码 ID 是 20190414T223342-2
,密钥环 ID 是 audit-log-20190414T223342-2
。像这样获取密钥环密码:
SELECT audit_log_encryption_password_get('audit-log-20190414T223342-2');
如果对 audit 记录启用了压缩和加密,压缩操作先于加密。在这种情况下,文件名添加.gz
和 .
后缀,相应于这两个操作的顺序。要恢复原始文件,首先解密,然后解压:pwd_id
.enc
openssl enc -d -aes-256-cbc -pass pass:password -md sha256
-in audit.timestamp.log.gz.pwd_id.enc
-out audit.timestamp.log.gz
gunzip -c audit.timestamp.log.gz > audit.timestamp.log
audit 日志文件可能会很大,占用大量磁盘空间。如果您收集了可选的查询时间和大小统计信息,这将增加空间要求。查询统计信息仅支持 JSON 格式。
管理使用空间,可以使用以下方法:
-
日志文件轮转。这涉及到重命名当前日志文件,然后使用原始名称打开新当前日志文件。轮转可以手动执行,也可以配置自动执行。
-
如果启用了自动旋转,JSON格式日志文件的剪裁。剪裁可以基于日志文件年龄或组合日志文件大小进行。
要配置审计日志文件空间管理,请使用以下系统变量:
-
如果
audit_log_rotate_on_size
为0(默认),自动日志文件旋转被禁用。-
除非手动进行,否则不会发生旋转。
-
要旋转当前文件,请使用以下方法:
-
运行
SELECT audit_log_rotate();
以重命名文件并使用原始名称打开新的审计日志文件。使用这个文件旋转方法,剪裁了旋转的JSON格式日志文件,如果
audit_log_max_size
或audit_log_prune_seconds
的值大于0。 -
手动重命名文件,然后启用
audit_log_flush
以关闭它并使用原始名称打开新的当前日志文件。这个文件旋转方法和audit_log_flush
变量已经弃用。使用这个文件旋转方法,剪裁了旋转的JSON格式日志文件;
audit_log_max_size
和audit_log_prune_seconds
无效。
查看手动审核日志文件旋转,获取更多信息。
-
-
-
如果
audit_log_rotate_on_size
大于0,自动审核日志文件旋转启用:-
自动旋转发生在当前日志文件的写操作使其大小超过
audit_log_rotate_on_size
值,以及某些其他条件下;查看自动审核日志文件旋转。发生自动旋转时,审核日志插件将当前日志文件重命名,并使用原始名称打开新的当前日志文件。 -
如果
audit_log_max_size
或audit_log_prune_seconds
的值大于0,旋转了的JSON格式日志文件将被剪枝。
-
对于JSON格式日志文件,旋转也发生在audit_log_format_unix_timestamp
系统变量在运行时被更改的情况下。然而,这并不是为了空间管理目的,而是为了使得给定的JSON格式日志文件中的所有记录都包含或不包含time
字段。
旋转后的日志文件不会自动删除。例如,基于大小的日志文件旋转,重命名的日志文件具有唯一名称,累积不限。它们不在名称序列末尾旋转以避免空间过度使用:
-
对于JSON格式日志文件:启用日志文件剪裁,如Audit Log File Pruning中所述。
-
否则:定期删除老文件,必要时备份。备份的日志文件如果加密,还需要将相应的加密密码安全地保存,以便后续解密文件。
以下部分详细描述了日志文件旋转和剪裁。
Manual Audit Log File Rotation
如果audit_log_rotate_on_size
为0(默认),除非手动进行,日志文件不旋转。
手动旋转审核日志文件,运行 SELECT audit_log_rotate();
将当前审核日志文件重命名并打开新的审核日志文件。文件按审核日志文件命名约定进行重命名。
使用 audit_log_rotate()
函数需要AUDIT_ADMIN
特权。
管理已归档日志文件(已经重命名的文件)和它们占用的空间是手动任务,涉及从文件系统中删除不再需要的已归档审核日志文件。
使用 audit_log_rotate()
函数重命名的审核日志文件内容可以被audit_log_read()
函数读取。
Manual Audit Log File Rotation (Old Method)
audit_log_flush
变量和审核日志文件旋转方法已弃用,预计将在 MySQL 未来版本中移除。
如果audit_log_rotate_on_size
为 0(默认),则不会自动进行日志旋转,除非手动执行。 在这种情况下,审核日志插件在audit_log_flush
值从禁用到启用的时刻关闭并重新打开日志文件。日志文件重命名需要外部服务器操作。假设日志文件名称为 audit.log
,你想维护最近三个日志文件,循环使用名称 audit.log.1
到 audit.log.3
。在 Unix 上,手动执行旋转操作如下:
-
从命令行重命名当前日志文件:
mv audit.log.2 audit.log.3 mv audit.log.1 audit.log.2 mv audit.log audit.log.1
这项策略覆盖当前
audit.log.3
内容,将存档日志文件的数量和空间限制。 -
在这个点上,插件仍然写入当前日志文件,该文件已经重命名为
audit.log.1
。连接到服务器并刷新日志文件,以便插件关闭它并重新打开一个新的audit.log
文件:SET GLOBAL audit_log_flush = ON;
audit_log_flush
特殊,因为其值保持为OFF
,因此在启用它再次执行刷新操作前不需要明确禁用它。
如果启用压缩或加密,日志文件名称包括标识启用的特征,以及如果启用加密,密码 ID。如果文件名称包含密码 ID,确保在手动重命名文件时保留 ID,以便确定解密操作的密码。
对于 JSON 格式的日志记录,手动重命名审核日志文件使它们不可用,因为审核日志插件无法确定它们是日志文件序列的一部分(见第8.4.5.6节,“读取审核日志文件”)。考虑将audit_log_rotate_on_size
设置大于0,以使用基于大小的旋转方式。
Automatic Audit Log File Rotation
如果audit_log_rotate_on_size
大于0,设置audit_log_flush
无效。相反,任何写入当前日志文件使其大小超过audit_log_rotate_on_size
值时,审核日志插件自动重命名当前日志文件并打开一个新的当前日志文件,使用原始名称。
基于大小的自动旋转也发生在以下情况下:
-
插件初始化时,如果已经存在带有审核日志文件名称的文件(见审核日志文件命名约定)。
-
插件终止时。
-
当
audit_log_encryption_password_set()
函数被调用以设置加密密码,如果启用了加密(如果禁用加密则不旋转)。
插件通过在文件名基础名前添加时间戳来重命名原始文件。例如,如果文件名是 audit.log
,插件将其重命名为类似于 audit.20210115T140633.log
的值。时间戳是一个 UTC 值,以
格式表示。对于 XML 日志记录,时间戳表示旋转时间。对于 JSON 日志记录,时间戳是文件中最后一个事件的时间戳。YYYYMMDD
Thhmmss
如果日志文件加密,原始文件名已经包含加密密码创建时间的时间戳(见Audit Log 文件命名约定)。在这种情况下,旋转后的文件名包含两个时间戳。例如,加密日志文件名为 audit.log.20210110T130749-1.enc
,将被重命名为类似于 audit.20210115T140633.log.20210110T130749-1.enc
的值。
Audit Log File Pruning
Audit 日志插件支持自动日志文件旋转的 JSON 格式 Audit 日志文件剪裁,如果启用了自动日志文件旋转。要使用这个功能:
-
将
audit_log_format
设置为JSON
。(此外,考虑同时更改audit_log_file
;见选择 Audit 日志文件格式。) -
将
audit_log_rotate_on_size
设置大于 0,以指定自动日志文件旋转的大小(以字节为单位)。 -
默认情况下,不对自动旋转的JSON格式日志文件进行剪枝。要启用剪枝,设置其中一个系统变量为大于0:
-
将
audit_log_max_size
设置为大于0,以指定旋转日志文件的总大小限制,超过该值的文件将被剪枝。 -
将
audit_log_prune_seconds
设置为大于0,以指定旋转日志文件在多少秒后被剪枝。
audit_log_max_size
的非零值优先于audit_log_prune_seconds
的非零值。如果在插件初始化时都设置为大于0,服务器错误日志中将写入警告。如果客户端在运行时设置为大于0,将返回警告到客户端。Note错误日志中的警告信息以Notes形式写入,以确保这些信息出现在错误日志中且不被丢弃。要使这些信息出现在错误日志中,需要确保错误日志的 verbosity 高度足够包括信息消息。例如,如果使用第7.4.2.5节,“基于优先级的错误日志过滤(log_filter_internal)”中描述的优先级日志过滤,设置
log_error_verbosity
系统变量为3。 -
如果启用了JSON格式日志文件的剪裁,发生如下情况:
-
当自动旋转发生时;关于此时的条件,请见自动 Audit 日志文件旋转。
-
当全局
audit_log_max_size
或audit_log_prune_seconds
系统变量在运行时设置。
基于组合旋转日志文件大小的剪裁,如果组合大小超过audit_log_max_size
指定的限制,Audit日志插件删除最老的文件直到它们的组合大小不超过限制。
基于旋转日志文件年龄的剪裁,剪裁点是当前时间减去audit_log_prune_seconds
的值。在旋转JSON格式日志文件中,每个文件名中的时间戳部分表示最后写入事件的时间戳。Audit日志插件使用文件名时间戳来确定哪些文件只包含比剪裁点更老的事件,并删除它们。
Audit日志插件可以使用多种策略来写入日志。无论策略如何,logging都以最佳努力进行,但不保证一致性。
在服务器启动时,设置audit_log_strategy
系统变量来指定写策略。默认情况下,策略值为ASYNCHRONOUS
,插件异步地将日志写入缓冲区,如果缓冲区满则等待。可以告诉插件不要等待(PERFORMANCE
)或同步写入,使用文件系统缓存(SEMISYNCHRONOUS
)或在每个写请求后强制输出(SYNCHRONOUS
)。
如果当前查询太大,插件可能直接将日志写入JSON格式。如果写策略确定了直接写的次数,可以使用Audit_log_direct_writes
状态变量来跟踪直接写的次数。
对于异步写策略,audit_log_buffer_size
系统变量是缓冲区大小,以字节为单位。在服务器启动时设置该变量来更改缓冲区大小。插件使用单个缓冲区,在初始化时分配,在终止时释放。非异步写策略不分配这个缓冲区。
异步日志写入策略具有以下特点:
-
对服务器性能和可扩展性影响最小。
-
阻塞生成 audit 事件的线程,时间是分配缓冲区的时间加上将事件写入缓冲区的时间。
-
输出到缓冲区。单独的线程处理从缓冲区写入日志文件的操作。
在异步日志记录中,如果写入文件出现问题或插件不正常关闭(例如,服务器主机意外退出),可能会损害日志文件的完整性。为了减少这个风险,可以将audit_log_strategy
设置为使用同步日志记录。
PERFORMANCE
策略的缺点是当缓冲区满时会丢弃事件。对于负载很重的服务器,审计日志可能会有事件缺失。