文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  配置审计日志特性

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_timestampYYYYMMDDThhmmss 格式的 UTC 值,指示密码何时创建。

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

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

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

为了构建用于在密钥环中存储密码的相应密钥环 ID,审计日志插件会在 pwd_id 值前面添加 audit_log- 前缀。对于刚刚显示的示例密码 ID,相应的密钥环 ID 为

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

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

审计日志插件根据有效的审计日志文件名在初始化和终止期间执行某些操作

  • 在初始化期间,插件会检查是否存在具有审计日志文件名的文件,如果存在则将其重命名。(在这种情况下,插件假定之前的服务器调用意外退出,并且审计日志插件正在运行。)然后,插件写入新的空审计日志文件。

  • 在终止期间,插件会重命名审计日志文件。

  • 文件重命名(无论是在插件初始化期间还是终止期间)都根据基于大小的自动日志文件轮转的常规规则进行;请参阅 手动审计日志文件轮转

选择审计日志文件格式

要配置审计日志文件格式,请在服务器启动时设置 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 的数字。该值的上线限因平台而异。例如,要将刷新任务配置为每两分钟循环一次

    $> 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_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,则会将空值写入这些字段的日志文件。

如果您想停止收集查询统计信息,请使用 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()。此函数将新密码存储在密钥环中。如果启用了加密,它还会执行日志文件轮转操作,该操作会重命名当前日志文件并开始使用该密码加密的新日志文件。文件重命名根据基于大小的自动日志文件轮转的常规规则进行;请参阅 手动审计日志文件轮转

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

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

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

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

当审计日志插件初始化时,如果发现日志文件加密已启用,它会检查密钥环中是否包含审计日志加密密码。如果没有,插件会自动生成一个随机的初始加密密码并将其存储在密钥环中。要发现此密码,请调用 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),但序列号不同 (1, 2)。这些文件具有不同的加密密码。

要手动解压缩压缩的日志文件,请使用 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
审计日志文件空间管理

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

为了管理所使用的空间,请使用以下方法

  • 日志文件轮换。这涉及通过重命名当前日志文件来轮换它,然后使用原始名称打开新的当前日志文件。轮换可以手动执行,也可以配置为自动发生。

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

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

注意

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

注意

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

  • 对于 JSON 格式的日志文件:启用日志文件修剪,如 审计日志文件修剪 中所述。

  • 否则:定期删除旧文件,必要时先备份它们。如果备份的日志文件已加密,请将相应的加密密码备份到安全位置,以备日后需要解密文件时使用。

以下部分详细介绍了日志文件轮换和修剪。

手动审计日志文件轮换

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

要手动轮换审计日志文件,请运行 SELECT audit_log_rotate(); 以重命名当前审计日志文件并打开新的审计日志文件。文件根据 审计日志文件命名约定 中描述的约定进行重命名。

需要 AUDIT_ADMIN 特权才能使用 audit_log_rotate() 函数。

管理存档日志文件的数量(已重命名的文件)以及它们使用的空间是一项手动任务,涉及从文件系统中删除不再需要的存档审计日志文件。

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

手动审计日志文件轮换(旧方法)
注意

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;

    audit_log_flush 的特殊之处在于,它的值保持为 OFF,因此您无需在再次启用它之前显式地禁用它以执行另一次刷新。

注意

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

注意

对于 JSON 格式的日志记录,手动重命名审计日志文件会使它们对日志读取函数不可用,因为审计日志插件无法再确定它们是日志文件序列的一部分(请参见 第 8.4.5.6 节,“读取审计日志文件”)。考虑将 audit_log_rotate_on_size 设置为大于 0,以使用基于大小的轮换来代替。

自动审计日志文件轮换

如果audit_log_rotate_on_size 大于 0,设置 audit_log_flush 将不起作用。相反,每当写入当前日志文件导致其大小超过 audit_log_rotate_on_size 值时,审计日志插件会自动重命名当前日志文件,并使用原始名称打开新的当前日志文件。

在以下情况下,也会发生自动基于大小的轮换

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

如果日志文件已加密,则原始文件名已包含一个时间戳,表示加密密码创建的时间(请参见 审计日志文件命名约定)。在这种情况下,轮换后的文件名将包含两个时间戳。例如,一个名为 audit.log.20210110T130749-1.enc 的加密日志文件将重命名为 audit.20210115T140633.log.20210110T130749-1.enc 之类的值。

审计日志文件修剪

如果启用了自动日志文件轮换,则审计日志插件支持修剪轮换的 JSON 格式审计日志文件。要使用此功能

  • audit_log_format 设置为 JSON。(此外,还可以考虑更改 audit_log_file;请参见 选择审计日志文件格式。)

  • 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,则会向客户端返回警告。

    注意

    写入错误日志的警告以“注释”的形式写入,它们是信息消息。为了确保此类消息出现在错误日志中并且不会被丢弃,请确保错误日志记录详细程度足以包含信息消息。例如,如果您使用基于优先级的日志过滤,如 第 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) 或在每个写入请求后强制输出带有 sync() 调用 (SYNCHRONOUS)。

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

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

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

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

  • 生成审计事件的线程的阻塞时间尽可能短;也就是说,分配缓冲区的时间加上将事件复制到缓冲区的时间。

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

对于异步日志记录,如果在写入文件期间发生问题,或者插件没有干净地关闭(例如,服务器主机意外退出),则日志文件的一致性可能会受到损害。要降低这种风险,请将 audit_log_strategy 设置为使用同步日志记录。

PERFORMANCE 策略的一个缺点是,当缓冲区已满时,它会丢弃事件。对于负载很重的服务器,审计日志中可能缺少事件。