Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Configuring Audit Logging Characteristics

8.4.5.5 审核日志记录配置

本节描述如何配置审核日志记录特征,如审核日志插件写入事件的文件、写入事件的格式、是否启用日志文件压缩和加密,以及空间管理。

有关审核日志函数和系统变量的更多信息,请参阅 审核日志函数审核日志选项和变量

审核日志插件还可以控制哪些审核事件被写入审核日志文件,基于事件内容或事件来源账户。请参阅 第 8.4.5.7 节,「审核日志过滤」

审核日志文件命名约定

要配置审核日志文件名,请在服务器启动时设置 audit_log_file 系统变量。默认名称是 audit.log 在服务器数据目录中。为了最佳安全性,请将审核日志写入仅供 MySQL 服务器和合法用户查看的目录。

插件将audit_log_file值解释为可选的前导目录名、基本名称和可选的后缀。如果启用了压缩或加密,实际文件名(用于创建日志文件的名称)将不同于配置的文件名,因为它具有附加的后缀:

  • 如果启用了压缩,插件将添加一个.gz后缀。

  • 如果启用了加密,插件将添加一个.pwd_id.enc后缀,其中pwd_id指示用于日志文件操作的加密密码。审核日志插件将加密密码存储在密钥环中;请参阅加密审核日志文件

实际审核日志文件名是通过将适用的压缩和加密后缀添加到配置文件名而获得的结果。例如,如果配置的audit_log_file值为audit.log,则实际文件名将是以下表格中显示的值之一。

启用的功能 实际文件名
无压缩或加密 audit.log
压缩 audit.log.gz
加密 audit.log.pwd_id.enc
压缩、加密 audit.log.gz.pwd_id.enc

pwd_id指示用于加密或解密文件的密码ID。pwd_id格式为pwd_timestamp-seq,其中:

  • pwd_timestamp是一个UTC值,以YYYYMMDDThhmmss格式指示密码创建的时间。

  • seq是一个序列号。序列号从1开始,对于具有相同的pwd_timestamp值的密码增加。

以下是一些示例pwd_id密码ID值:

20190403T142359-1
20190403T142400-1
20190403T142400-2

要构建相应的密钥环ID以存储密码在密钥环中,审核日志插件将audit_log-前缀添加到pwd_id值中。对于刚刚显示的密码ID,相应的密钥环ID为:

audit_log-20190403T142359-1
audit_log-20190403T142400-1
audit_log-20190403T142400-2

当前用于加密的审核日志插件的密码ID是具有最大 pwd_timestamp 值的那个。如果多个密码具有该 pwd_timestamp 值,则当前密码ID是具有最大序号的那个。例如,在前面的密码ID集中,两个密码具有最大时间戳 20190403T142400,因此当前密码ID是具有最大序号(2)的那个。

审核日志插件在初始化和终止时执行某些操作,基于有效的审核日志文件名:

  • 在初始化时,插件检查是否已经存在具有审核日志文件名的文件,并重命名它(在这种情况下,插件假设前一个服务器实例以审核日志插件运行的方式退出)。然后,插件写入一个新的空审核日志文件。

  • 在终止时,插件重命名审核日志文件。

  • 文件重命名(无论是在插件初始化还是终止时)都遵循自动大小基于日志文件轮换的通常规则;见 手动审核日志文件轮换(在 MySQL 8.0.31 之前)

选择审核日志文件格式

要配置审核日志文件格式,请在服务器启动时设置 audit_log_format 系统变量。以下格式可用:

  • NEW:新式 XML 格式。这是默认值。

  • OLD:旧式 XML 格式。

  • JSON:JSON 格式。将审核日志写入 JSON 数组中。只有这个格式支持可选的查询时间和大小统计。

有关每种格式的详细信息,请参阅 第 8.4.5.4 节,“审核日志文件格式”

启用审核日志刷新任务

MySQL Enterprise Audit 提供了设置刷新间隔以自动清除内存缓存的能力。使用 audit_log_flush_interval_seconds 系统变量配置的刷新任务,默认值为零,即不计划运行。

当任务配置为运行(值非零)时,MySQL Enterprise Audit 尝试在初始化时调用 调度器 组件,并配置内存缓存的定期刷新:

  • 如果审核日志无法找到调度器注册服务的实现,它将不计划刷新并继续加载。

  • 审核日志实现了 dynamic_loader_services_loaded_notification 服务,并监听新的 mysql_scheduler 注册,以便审核日志可以将其计划任务注册到新加载的调度器中。

  • 审核日志仅将自己注册到第一个加载的调度器实现中。

类似地,MySQL Enterprise Audit 在其反初始化时调用 scheduler 组件,并取消了它计划的刷新。它保持对调度器注册服务的活动引用,直到计划任务取消注册,以确保 scheduler 组件不能在活动计划任务时卸载。所有执行调度器和其任务的结果都写入服务器错误日志。

要计划审核日志刷新任务:

  1. 确认 scheduler 组件已加载并启用。该组件默认启用 (ON),请参阅 component_scheduler.enabled

    SELECT * FROM mysql.components;
    +--------------+--------------------+----------------------------+
    | component_id | component_group_id | component_urn              |
    +--------------+--------------------+----------------------------+
    |            1 |                  1 | file://component_scheduler |
    +--------------+--------------------+----------------------------+
  2. 安装 audit_log 插件,如果尚未安装(请参阅 第 8.4.5.2 节,“安装或卸载 MySQL Enterprise Audit”)。

  3. 使用 audit_log_flush_interval_seconds 启动服务器,并将值设置为大于 59 的数字。该值的上限因平台而异。例如,要配置刷新任务每 2 分钟重复一次:

    $> mysqld --audit_log_flush_interval_seconds=120

    有关更多信息,请参阅 audit_log_flush_interval_seconds 系统变量。

添加查询统计信息以检测异常值

在 MySQL 8.3 中,您可以将 JSON 格式的日志文件扩展到可选数据字段,以显示查询时间、发送和接收的字节数、返回给客户端的行数和检查的行数。这些数据在慢查询日志中可用于检测异常值,并在审核日志中类似地帮助检测活动分析中的异常值。这些扩展数据字段只能在审核日志为 JSON 格式 (audit_log_format=JSON) 时添加,该设置不是默认设置。

查询统计信息通过组件服务传递到审核日志中,您可以设置这些服务作为审核日志过滤函数。这些服务名为 mysql_audit_print_service_longlong_data_sourcemysql_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_sentbytes_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 压缩)。

如果同时启用压缩和加密,压缩将在加密之前发生。要手动恢复原始文件,首先解密,然后解压缩。请参阅 手动解压缩和解密审核日志文件

加密审核日志文件

审核日志文件加密可以为任何日志格式启用。加密基于用户定义的密码(除初始密码外,审核日志插件生成的密码)。要使用此功能,MySQL 密钥环必须启用,因为审核日志使用它来存储密码。任何密钥环组件或插件都可以使用;有关说明,请参阅 第 8.4.4 节,“MySQL 密钥环”

要配置审核日志文件加密,请在服务器启动时设置 audit_log_encryption 系统变量。允许的值是 NONE(无加密;默认)和 AES(AES-256-CBC 密码加密)。

要设置或获取加密密码在运行时,请使用这些审核日志函数:

  • 要设置当前加密密码,请调用 audit_log_encryption_password_set()。该函数将新密码存储在密钥环中。如果加密启用,它还将执行日志文件旋转操作,重命名当前日志文件,并开始新的加密日志文件。文件重命名根据通常的自动大小基于日志文件旋转规则进行;请参阅 手动审核日志文件旋转(在 MySQL 8.0.31 之前)

    如果audit_log_password_history_keep_days系统变量不为零,调用audit_log_encryption_password_set()也会导致旧的存档审计日志加密密码过期。有关审计日志密码历史记录,包括密码存档和过期,请参阅该变量的描述。

  • 要获取当前的加密密码,请调用audit_log_encryption_password_get()不带参数。要获取密码ByID,请传递一个指定当前密码或存档密码的密钥环ID的参数。

    要确定哪些审计日志密钥环ID存在,请查询性能模式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 |
    +-----------------------------+

有关审计日志加密函数的更多信息,请参阅审计日志函数

当审计日志插件初始化时,如果发现日志文件加密已启用,它将检查密钥环中是否存在审计日志加密密码。如果没有,该插件将自动生成一个随机的初始加密密码并将其存储在密钥环中。要发现该密码,请调用audit_log_encryption_password_get()

如果同时启用了压缩和加密,压缩将在加密之前发生。要手动恢复原始文件,首先解密,然后解压缩。请参阅手动解压缩和解密审计日志文件

手动解压缩和解密审计日志文件

审计日志文件可以使用标准工具解压缩和解密。这应该仅对已关闭(存档)的日志文件进行,不是当前由审计日志插件写入的日志文件。你可以通过审计日志插件在文件名中添加时间戳来识别存档日志文件。

在本讨论中,假设audit_log_file设置为audit.log。在那种情况下,存档审计日志文件将具有以下表格所示的名称。

启用功能 存档文件名
无压缩或加密 audit.timestamp.log
压缩 audit.timestamp.log.gz
加密 audit.timestamp.log.pwd_id.enc
压缩、加密 audit.timestamp.log.gz.pwd_id.enc

审核日志文件命名约定中所讨论的那样,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)但不同的序列号(12)。这些文件具有不同的加密密码。

要手动解压缩压缩日志文件,请使用gunzipgzip -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.20190415T151322.log.20190414T223342-2.enc,密码ID为20190414T223342-2,密钥环ID为audit-log-20190414T223342-2。检索密钥环密码如下:

SELECT audit_log_encryption_password_get('audit-log-20190414T223342-2');

如果审核日志记录启用了压缩和加密,压缩将在加密之前发生。在这种情况下,文件名将添加.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
MySQL 8.0.17之前的审核日志文件加密

本节涵盖了 MySQL 8.0.17 之前的审核日志文件加密功能的差异,以及密码历史记录的实现(包括密码存档和过期)。它还表明了审核日志插件如何处理从低于 8.0.17 的版本升级到 MySQL 8.0.17 或更高版本。

功能 MySQL 8.0.17 之前 MySQL 8.0.17 及更高版本
密码数量 仅一个密码 允许多个密码
加密日志文件名 .enc 后缀 .pwd_id.enc 后缀
密码钥匙环 ID audit_log audit_log-pwd_id
密码历史记录

在 MySQL 8.0.17 之前,没有密码历史记录,因此设置新密码将使旧密码不可访问,从而使 MySQL Enterprise Audit 无法读取使用旧密码加密的日志文件。如果您预计需要手动解密这些文件,您必须保留以前的密码记录。

如果在升级到 MySQL 8.0.17 或更高版本时启用了审核日志文件加密,则审核日志插件将执行以下升级操作:

  • 在插件初始化期间,插件检查密钥环 ID 为 audit_log 的加密密码。如果找到,则插件将使用密钥环 ID 在 audit_log-pwd_id 格式的密码,并将其用作当前加密密码。(有关 pwd_id 语法的详细信息,请参阅 审核日志文件命名约定。)

  • 现有的加密日志文件具有 .enc 后缀。插件不会将这些文件重命名为 .pwd_id.enc,但只要密钥环 ID 为 audit_log 的密钥仍然存在于密钥环中,插件就可以读取这些文件。

  • 当密码清理发生时,如果插件到期了任何密钥环 ID 为 audit_log-pwd_id 格式的密码,也将到期密钥环 ID 为 audit_log 的密码,如果它存在。(此时,具有 .enc 后缀而不是 .pwd_id.enc 的加密日志文件将变得不可读,因此假设您不再需要它们。)

审核日志文件空间管理

审核日志文件可能会变得非常大,占用大量磁盘空间。如果您正在收集可选的查询时间和大小统计信息,这将增加空间要求。查询统计信息仅支持 JSON 格式。

管理空间使用的方法:

  • 日志文件轮换。这涉及到重命名当前日志文件,然后使用原始名称打开新的当前日志文件。轮换可以手动或自动配置。

  • 如果启用自动轮换,裁剪已轮换的 JSON 格式日志文件。裁剪可以根据日志文件年龄或组合日志文件大小进行。

要配置审核日志文件空间管理,请使用以下系统变量:

Note

对于 JSON 格式日志文件,旋转也会在运行时更改 audit_log_format_unix_timestamp 系统变量时发生。但是,这不是为了空间管理目的,而是为了确保给定的 JSON 格式日志文件中的所有记录都包含或不包含 time 字段。

Note

旋转(重命名)日志文件不会被自动删除。例如,在基于大小的日志文件旋转中,重命名的日志文件具有唯一的名称并且会无限期地累积它们不会从名称序列中旋转出去。为了避免空间的过度使用:

  • 对于 JSON 格式日志文件:启用日志文件修剪,如 Audit Log File Pruning 中所述。

  • 否则(对于非 JSON 文件或 MySQL 8.0.24 之前的所有日志格式):定期删除旧文件,必要时先备份它们。如果备份的日志文件是加密的,也备份相应的加密密码,以便日后解密文件。

以下部分将详细描述日志文件旋转和修剪。

Manual Audit Log File Rotation (Before MySQL 8.0.31)
Note

从 MySQL 8.0.31 开始,audit_log_flush 变量和该方法的审计日志文件旋转将被弃用;预计在未来版本的 MySQL 中将删除支持。

如果 audit_log_rotate_on_size 为 0(默认值),则不会发生日志旋转,除非手动执行。在这种情况下,审计日志插件在 audit_log_flush 值从禁用更改为启用时关闭并重新打开日志文件。日志文件重命名必须在服务器外部进行。假设日志文件名为 audit.log,您想维护最新的三个日志文件,循环使用名称 audit.log.1audit.log.3。在 Unix 上,手动旋转日志文件,如下所示:

  1. 从命令行重命名当前日志文件:

    mv audit.log.2 audit.log.3
    mv audit.log.1 audit.log.2
    mv audit.log audit.log.1

    这种策略将覆盖当前 audit.log.3 的内容,限制存档日志文件的数量和所占用的空间。

  2. 此时,插件仍在写入当前日志文件,该文件已被重命名为 audit.log.1。连接到服务器并刷新日志文件,以便插件关闭它并重新打开一个新的 audit.log 文件:

    SET GLOBAL audit_log_flush = ON;

    审核日志刷新 特殊之处在于其值保持 OFF,因此您无需在启用它之前显式禁用它,以便执行另一次刷新。

Note

如果启用了压缩或加密,日志文件名将包括表示启用功能的后缀,以及加密时的密码 ID。如果文件名包括密码 ID,请确保在手动重命名文件时保留该 ID,以便确定用于解密操作的密码。

Note

对于 JSON 格式日志,手动重命名审核日志文件将使其不可用于日志读取函数,因为审核日志插件无法确定它们是日志文件序列的一部分(见 第 8.4.5.6 节,“读取审核日志文件”)。考虑将 audit_log_rotate_on_size 设置为大于 0,以使用基于大小的旋转。

Manual Audit Log File Rotation (From MySQL 8.0.31)

如果 audit_log_rotate_on_size 为 0(默认值),除非手动执行,否则不会发生日志旋转。

要手动旋转审核日志文件,请运行 SELECT audit_log_rotate(); 以重命名当前审核日志文件并打开一个新的审核日志文件。文件将根据 审核日志文件命名约定 进行重命名。

需要 AUDIT_ADMIN 权限来使用 audit_log_rotate() 函数。

管理已存档日志文件的数量(即已重命名的文件)及其所占用的空间是一个手动任务,涉及从文件系统中删除不再需要的已存档审核日志文件。

使用 audit_log_rotate() 函数重命名的审核日志文件的内容可以由 audit_log_read() 函数读取。

Automatic Audit Log File Rotation

如果 audit_log_rotate_on_size 大于 0,设置 audit_log_flush 将无效。相反,当写入当前日志文件时,如果其大小超过 audit_log_rotate_on_size 值,审核日志插件将自动重命名当前日志文件并打开一个新的当前日志文件,使用原始名称。

自动大小基于旋转也会在以下条件下发生:

插件将原始文件重命名,插入时间戳就在其基本名称后面。例如,如果文件名是audit.log,插件将其重命名为类似audit.20210115T140633.log的值。时间戳是一个UTC值,以YYYYMMDDThhmmss格式表示。对于XML日志记录,时间戳表示轮换时间。对于JSON日志记录,时间戳是最后一个事件写入文件的时间。

如果日志文件被加密,原始文件名已经包含了加密密码创建时间的时间戳(见Audit Log Files的命名约定)。在这种情况下,文件名在轮换后包含两个时间戳。例如,一个加密的日志文件名为audit.log.20210110T130749-1.enc,将被重命名为类似audit.20210115T140633.log.20210110T130749-1.enc的值。

Audit Log File Pruning

审核日志插件支持自动轮换的JSON格式审核日志文件的修剪,如果启用了自动日志文件轮换。

  • audit_log_format设置为JSON。(此外,还可以考虑更改audit_log_file;见选择Audit Log文件格式。)

  • 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。如果在插件初始化时同时设置了这两个变量的非零值,将在服务器错误日志中写入警告。如果客户端在运行时同时设置了这两个变量的非零值,将返回警告给客户端。

    Note

    错误日志中的警告将被写入为 Notes,即信息消息。为了确保这些消息出现在错误日志中而不被丢弃,请确保错误日志的详细程度足以包括信息消息。例如,如果您使用基于优先级的日志过滤,如第 7.4.2.5 节,“基于优先级的错误日志过滤(log_filter_internal)”所述,设置log_error_verbosity系统变量的值为 3。

JSON 格式日志文件的修剪,如果启用,将按照以下方式进行:

对于基于旋转日志文件大小的修剪,如果旋转日志文件的总大小超过audit_log_max_size指定的限制,审计日志插件将删除最旧的文件,直到总大小不超过限制。

对于基于旋转日志文件年龄的修剪,修剪点是当前时间减去audit_log_prune_seconds的值。在旋转的 JSON 格式日志文件中,每个文件名的时间戳部分表示文件中最后一个事件的时间戳。审计日志插件使用文件名时间戳来确定哪些文件仅包含比修剪点更旧的事件,并删除它们。

审计日志写入策略

审计日志插件可以使用多种策略来写入日志。无论使用哪种策略,日志记录都是尽力而为的,没有一致性保证。

要指定写入策略,请在服务器启动时设置audit_log_strategy系统变量。默认情况下,策略值为ASYNCHRONOUS,插件异步地将日志写入缓冲区,如果缓冲区满则等待。您可以告诉插件不要等待(PERFORMANCE)或同步地写入日志,使用文件系统缓存(SEMISYNCHRONOUS)或在每个写入请求后强制输出(SYNCHRONOUS)。

在许多情况下,如果当前查询太大无法写入缓冲区,插件将直接写入 JSON 格式审计日志。写入策略确定插件如何增加直接写入计数。您可以使用Audit_log_direct_writes状态变量来跟踪直接写入的数量。

对于异步写策略,audit_log_buffer_size 系统变量是以字节为单位的缓冲区大小。在服务器启动时设置该变量以更改缓冲区大小。插件在初始化时分配一个缓冲区,并在终止时删除该缓冲区。对于非异步写策略,插件不分配该缓冲区。

异步日志策略具有以下特征:

  • 对服务器性能和可扩展性的最小影响。

  • 生成审核事件的线程阻塞时间最短;即缓冲区分配时间加上将事件复制到缓冲区的时间。

  • 输出到缓冲区。一个单独的线程处理从缓冲区到日志文件的写入。

使用异步日志记录时,如果在写入文件或插件未正确关闭(例如,服务器主机意外退出)时出现问题,日志文件的完整性可能会受到损害。为了减少这种风险,可以将 audit_log_strategy 设置为使用同步日志记录。

使用 PERFORMANCE 策略的一个缺点是,当缓冲区满时,它会丢弃事件。在服务器负载很高的情况下,审核日志可能会缺少事件。