MySQL8 中文参考(三十二)
8.4.5.11 审计日志参考
以下各节提供了 MySQL 企业审计元素的参考:
-
审计日志表
-
审计日志功能
-
审计日志选项和变量参考
-
审计日志选项和变量
-
审计日志状态变量
要安装审计日志表和功能,请使用第 8.4.5.2 节,“安装或卸载 MySQL 企业审计”中提供的说明。除非安装了这些对象,否则audit_log插件将以传统模式运行(在 MySQL 8.0.34 中已弃用)。请参阅第 8.4.5.10 节,“传统模式审计日志过滤”。
审计日志表
MySQL 企业审计使用mysql系统数据库中的表来持久存储过滤器和用户帐户数据。只有具有该数据库权限的用户才能访问这些表。要使用不同的数据库,请在服务器启动时设置audit_log_database系统变量。这些表使用InnoDB存储引擎。
如果这些表缺失,audit_log插件将以(已弃用的)传统模式运行。请参阅第 8.4.5.10 节,“传统模式审计日志过滤”。
audit_log_filter表存储过滤器定义。该表具有以下列:
-
名称过滤器名称。
-
FILTER与过滤器名称相关联的过滤器定义。定义存储为
JSON值。
audit_log_user表存储用户帐户信息。该表具有以下列:
-
用户帐户的用户名部分。对于帐户
user1@localhost,USER部分是user1。 -
HOST帐户的主机名部分。对于帐户
user1@localhost,HOST部分是localhost。 -
FILTERNAME分配给帐户的过滤器名称。过滤器名称将帐户与
audit_log_filter表中定义的过滤器关联起来。
审计日志功能
本节描述了每个审计日志功能的目的、调用顺序和返回值。有关这些功能可以在何种条件下调用的信息,请参阅第 8.4.5.7 节,“审计日志过滤”。
每个审计日志函数都会返回一个字符串,指示操作是否成功。OK表示成功。ERROR: *message*表示失败。
截至 MySQL 8.0.19,审计日志函数将字符串参数转换为utf8mb4,并且字符串返回值为utf8mb4字符串。在 MySQL 8.0.19 之前,审计日志函数将字符串参数视为二进制字符串(这意味着它们不区分大小写),并且字符串返回值为二进制字符串。
如果从mysql客户端调用审计日志函数,则二进制字符串结果将使用十六进制表示,具体取决于--binary-as-hex的值。有关该选项的更多信息,请参见第 6.5.1 节,“mysql — MySQL 命令行客户端”。
可用的审计日志函数包括:
-
audit_log_encryption_password_get([*keyring_id*])此函数从 MySQL 钥匙环中获取审计日志加密密码,必须启用,否则将出现错误。可以使用任何钥匙环组件或插件;有关说明,请参见第 8.4.4 节,“MySQL 钥匙环”。
没有参数时,函数将检索当前加密密码作为二进制字符串。可以给定参数以指定要检索的哪个审计日志加密密码。参数必须是当前密码或存档密码的钥匙环 ID。
有关审计日志加密的更多信息,请参见加密审计日志文件。
参数:
keyring_id:从 MySQL 8.0.17 开始,这个可选参数表示要检索的密码的钥匙环 ID。最大允许长度为 766 字节。如果省略,函数将检索当前密码。在 MySQL 8.0.17 之前,不允许有任何参数。该函数始终检索当前密码。
返回值:
成功的密码字符串(最多 766 字节),或失败时为
NULL和错误。示例:
检索当前密码:
mysql> SELECT audit_log_encryption_password_get(); +-------------------------------------+ | audit_log_encryption_password_get() | +-------------------------------------+ | secret | +-------------------------------------+要通过 ID 检索密码,可以通过查询性能模式
keyring_keys表来确定存在哪些审计日志钥匙环 ID: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 | +-----------------------------+ mysql> SELECT audit_log_encryption_password_get('audit_log-20190416T125122-1'); +------------------------------------------------------------------+ | audit_log_encryption_password_get('audit_log-20190416T125122-1') | +------------------------------------------------------------------+ | segreto | +------------------------------------------------------------------+ -
audit_log_encryption_password_set(*password*)将当前审计日志加密密码设置为参数,并将密码存储在 MySQL 钥匙环中。截至 MySQL 8.0.19,密码存储为
utf8mb4字符串。在 MySQL 8.0.19 之前,密码以二进制形式存储。如果启用了加密,此函数将执行一个日志文件旋转操作,重命名当前日志文件,并开始一个新的日志文件,使用密码加密。必须启用密钥环,否则将出现错误。可以使用任何密钥环组件或插件;有关说明,请参见第 8.4.4 节,“MySQL 密钥环”。
有关审计日志加密的更多信息,请参见加密审计日志文件。
参数:
password: 密码字符串。最大允许长度为 766 字节。返回值:
成功返回 1,失败返回 0。
示例:
mysql> SELECT audit_log_encryption_password_set(*password*); +---------------------------------------------+ | audit_log_encryption_password_set(*password*) | +---------------------------------------------+ | 1 | +---------------------------------------------+ -
audit_log_filter_flush()调用任何其他过滤函数会立即影响操作审计日志过滤,并更新审计日志表。如果您改为直接修改这些表的内容,使用诸如
INSERT、UPDATE和DELETE等语句,更改不会立即影响过滤。要刷新更改并使其生效,请调用audit_log_filter_flush()。警告
只有在直接修改审计表后,才应使用
audit_log_filter_flush()来强制重新加载所有过滤器。否则,应避免使用此函数。实际上,这是使用UNINSTALL PLUGIN加INSTALL PLUGIN卸载和重新加载audit_log插件的简化版本。audit_log_filter_flush()会影响所有当前会话,并将它们从先前的过滤器中分离。当前会话不再被记录,除非它们断开连接并重新连接,或执行更改用户操作。如果此函数失败,将返回错误消息,并且审计日志将被禁用,直到下一次成功调用
audit_log_filter_flush()。参数:
无。
返回值:
一个指示操作是否成功的字符串。
OK表示成功。ERROR: *message*表示失败。示例:
mysql> SELECT audit_log_filter_flush(); +--------------------------+ | audit_log_filter_flush() | +--------------------------+ | OK | +--------------------------+ -
audit_log_filter_remove_filter(*filter_name*)给定一个过滤器名称,从当前过滤器集中移除该过滤器。过滤器不存在也不会报错。
如果已删除的过滤器分配给任何用户帐户,则这些用户将停止被过滤(它们将从
audit_log_user表中删除)。停止过滤包括这些用户的任何当前会话:它们将从过滤器中分离,并且不再被记录。参数:
filter_name:指定过滤器名称的字符串。
返回值:
一个指示操作是否成功的字符串。
OK表示成功。ERROR: *message*表示失败。示例:
mysql> SELECT audit_log_filter_remove_filter('SomeFilter'); +----------------------------------------------+ | audit_log_filter_remove_filter('SomeFilter') | +----------------------------------------------+ | OK | +----------------------------------------------+ -
audit_log_filter_remove_user(*user_name*)给定用户账户名称,使用户不再分配到过滤器。如果用户没有分配过滤器,则不会出错。用户的当前会话过滤保持不受影响。如果存在默认账户过滤器,则使用默认账户过滤器过滤用户的新连接,否则不记录。
如果名称为
%,则函数会移除用于没有明确分配过滤器的任何用户账户的默认账户过滤器。参数:
user_name:用户账户名称,以*user_name*@*host_name*格式的字符串表示,或者使用%表示默认账户。
返回值:
一个指示操作是否成功的字符串。
OK表示成功。ERROR: *message*表示失败。示例:
mysql> SELECT audit_log_filter_remove_user('user1@localhost'); +-------------------------------------------------+ | audit_log_filter_remove_user('user1@localhost') | +-------------------------------------------------+ | OK | +-------------------------------------------------+ -
audit_log_filter_set_filter(*filter_name*, *definition*)给定过滤器名称和定义,将过滤器添加到当前过滤器集中。如果过滤器已经存在并且被当前会话使用,那么这些会话将与过滤器分离,并且不再记录。这是因为新的过滤器定义具有与先前 ID 不同的新过滤器 ID。
参数:
-
filter_name:指定过滤器名称的字符串。 -
definition:指定过滤器定义的JSON值。
返回值:
一个指示操作是否成功的字符串。
OK表示成功。ERROR: *message*表示失败。示例:
mysql> SET @f = '{ "filter": { "log": false } }'; mysql> SELECT audit_log_filter_set_filter('SomeFilter', @f); +-----------------------------------------------+ | audit_log_filter_set_filter('SomeFilter', @f) | +-----------------------------------------------+ | OK | +-----------------------------------------------+ -
-
audit_log_filter_set_user(*user_name*, *filter_name*)给定用户账户名称和过滤器名称,将过滤器分配给用户。用户只能分配一个过滤器,因此如果用户已经分配了过滤器,则分配将被替换。用户的当前会话过滤保持不受影响。新连接将使用新的过滤器进行过滤。
作为特例,名称
%代表默认账户。该过滤器用于来自没有明确分配过滤器的任何用户账户的连接。参数:
-
user_name:用户账户名称,以*user_name*@*host_name*格式的字符串表示,或者使用%表示默认账户。 -
filter_name:指定过滤器名称的字符串。
返回值:
一个指示操作是否成功的字符串。
OK表示成功。ERROR: *message*表示失败。示例:
mysql> SELECT audit_log_filter_set_user('user1@localhost', 'SomeFilter'); +------------------------------------------------------------+ | audit_log_filter_set_user('user1@localhost', 'SomeFilter') | +------------------------------------------------------------+ | OK | +------------------------------------------------------------+ -
-
读取审计日志并返回一个
JSON字符串结果。如果审计日志格式不是JSON,则会出错。没有参数或者一个
JSON哈希参数时,audit_log_read()从审计日志中读取事件,并返回一个包含审计事件数组的JSON字符串。哈希参数中的项会影响读取过程,稍后会描述。返回数组中的每个元素都是一个以JSON哈希表示的事件,除了最后一个元素可能是一个JSONnull值,表示没有更多事件可供读取。使用由
JSONnull值组成的参数时,audit_log_read()将关闭当前读取序列。有关审计日志读取过程的更多详细信息,请参见第 8.4.5.6 节,“读取审计日志文件”。
参数:
要获取最近写入事件的书签,请调用
audit_log_read_bookmark()。arg: 参数是可选的。如果省略,函数将从当前位置读取事件。如果存在,参数可以是一个JSONnull值以关闭读取序列,或者一个JSON哈希。在哈希参数中,项是可选的,并控制读取操作的方面,例如从哪个位置开始读取或者要读取多少事件。以下项是重要的(其他项将被忽略):-
start: 审计日志中要读取的第一个事件的位置。位置以时间戳给出,并且从时间戳值之后发生的第一个事件开始读取。start项的格式如下,其中*value*是一个字面时间戳值:"start": { "timestamp": "*value*" }start项自 MySQL 8.0.22 版本开始允许使用。 -
timestamp,id: 要读取的第一个事件在审计日志中的位置。timestamp和id项一起构成一个书签,唯一标识特定事件。如果audit_log_read()参数包含任一项,则必须同时包含两项才能完全指定位置,否则会出错。 -
max_array_length: 从日志中读取的最大事件数。如果省略此项,则默认读取到日志末尾或者直到读取缓冲区已满为止。
要指定给
audit_log_read()的起始位置,传递一个包含start项或由时间戳和id项组成的书签的哈希参数。如果哈希参数同时包含start项和书签,则会出现错误。如果哈希参数未指定起始位置,则从当前位置继续读取。
如果时间戳值不包含时间部分,则假定时间部分为
00:00:00。返回值:
如果调用成功,返回值是包含审核事件数组的
JSON字符串,或者如果将其作为参数传递以关闭读取序列,则返回JSONnull值。如果调用失败,返回值为NULL,并出现错误。示例:
mysql> SELECT audit_log_read(audit_log_read_bookmark()); +-----------------------------------------------------------------------+ | audit_log_read(audit_log_read_bookmark()) | +-----------------------------------------------------------------------+ | {"timestamp":"2020-05-18 22:41:24","id":0,"class":"connection", ... | +-----------------------------------------------------------------------+ mysql> SELECT audit_log_read('null'); +------------------------+ | audit_log_read('null') | +------------------------+ | null | +------------------------+注意:
在 MySQL 8.0.19 之前,字符串返回值是二进制的[
JSON字符串。有关将这些值转换为非二进制字符串的信息,请参见第 8.4.5.6 节,“读取审计日志文件”。 -
-
audit_log_read_bookmark()返回一个表示最近写入的审计日志事件的
JSON字符串书签。如果审计日志格式不是JSON,则会出现错误。书签是一个包含
时间戳和id项的JSON哈希,用于唯一标识审核日志中事件的位置。适合传递给audit_log_read()以指示该函数开始读取的位置。有关审计日志读取过程的更多详细信息,请参见第 8.4.5.6 节,“读取审计日志文件”。
参数:
无。
返回值:
包含成功书签的
JSON字符串,或包含失败的NULL和错误。示例:
mysql> SELECT audit_log_read_bookmark(); +-------------------------------------------------+ | audit_log_read_bookmark() | +-------------------------------------------------+ | { "timestamp": "2019-10-03 21:03:44", "id": 0 } | +-------------------------------------------------+注意:
在 MySQL 8.0.19 之前,字符串返回值是二进制的
JSON字符串。有关将这些值转换为非二进制字符串的信息,请参见第 8.4.5.6 节,“读取审计日志文件”。 -
audit_log_rotate()参数:
无。
返回值:
重命名后的文件名。
示例:
mysql> SELECT audit_log_rotate();使用
audit_log_rotate()需要AUDIT_ADMIN权��。
审计日志选项和变量参考
表 8.44 审计日志选项和变量参考
| 名称 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 变量范围 | 动态 |
|---|---|---|---|---|---|---|
| audit-log | 是 | 是 | ||||
| 审计日志缓冲区大小 | 是 | 是 | 是 | 全局 | 否 | |
| 审计日志压缩 | 是 | 是 | 是 | 全局 | 否 | |
| 审计日志连接策略 | 是 | 是 | 是 | 全局 | 是 | |
| 当前审计日志会话 | 是 | 两者 | 否 | |||
| 审计日志当前大小 | 是 | 全局 | 否 | |||
| 审计日志数据库 | 是 | 是 | 是 | 全局 | 否 | |
| 禁用审计日志 | 是 | 是 | 是 | 全局 | 是 | |
| 审计日志加密 | 是 | 是 | 是 | 全局 | 否 | |
| 审计日志事件最大丢弃大小 | 是 | 全局 | 否 | |||
| 审计日志事件 | 是 | 全局 | 否 | |||
| 已过滤审计日志事件 | 是 | 全局 | 否 | |||
| 已丢失审计日志事件 | 是 | 全局 | 否 | |||
| 已写入审计日志事件 | 是 | 全局 | 否 | |||
| 排除账户的审计日志 | 是 | 是 | 是 | 全局 | 是 | |
| 审计日志文件 | 是 | 是 | 是 | 全局 | 否 | |
| 审计日志过滤器 ID | 是 | 两者 | 否 | |||
| 审计日志刷新 | 是 | 全局 | 是 | |||
| 审计日志刷新间隔秒数 | 是 | 是 | 全局 | 否 | ||
| 审计日志格式 | 是 | 是 | 是 | 全局 | 否 | |
| 包含账户的审计日志 | 是 | 是 | 是 | 全局 | 是 | |
| 审计日志最大大小 | 是 | 是 | 是 | 全局 | 是 | |
| 审计日志密码历史保留天数 | 是 | 是 | 是 | 全局 | 是 | |
| 审计日志策略 | 是 | 是 | 是 | 全局 | �� | |
| 审计日志修剪秒数 | 是 | 是 | 是 | 全局 | 是 | |
| 审计日志读取缓冲区大小 | 是 | 是 | 是 | 变化 | 变化 | |
| audit_log_rotate_on_size | 是 | 是 | 是 | 全局 | 是 | |
| audit_log_statement_policy | 是 | 是 | 是 | 全局 | 是 | |
| audit_log_strategy | 是 | 是 | 是 | 全局 | 否 | |
| Audit_log_total_size | 是 | 全局 | 否 | |||
| Audit_log_write_waits | 是 | 全局 | 否 | |||
| 名称 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 变量范围 | 动态 |
审计日志选项和变量
本节描述了配置 MySQL Enterprise Audit 操作的命令选项和系统变量。如果在启动时指定的值不正确,audit_log 插件可能无法正确初始化,服务器也不会加载它。在这种情况下,服务器可能还会因为无法识别其他审计日志设置而产生错误消息。
要配置审计日志插件的激活,请使用此选项:
-
命令行格式 --audit-log[=value]类型 枚举 默认值 ON有效值 ON``OFF``FORCE``FORCE_PLUS_PERMANENT此选项控制服务器在启动时如何加载
audit_log插件。只有在插件之前已经使用INSTALL PLUGIN注册过或者使用--plugin-load或--plugin-load-add加载过插件时才可用。参见 Section 8.4.5.2, “Installing or Uninstalling MySQL Enterprise Audit”。选项值应该是插件加载选项中可用的值之一,如 Section 7.6.1, “Installing and Uninstalling Plugins” 中所述。例如,
--audit-log=FORCE_PLUS_PERMANENT告诉服务器加载插件并防止在服务器运行时被移除。
如果启用了审计日志插件,它会暴露几个系统变量,允许对日志进行控制:
mysql> SHOW VARIABLES LIKE 'audit_log%';
+--------------------------------------+--------------+
| Variable_name | Value |
+--------------------------------------+--------------+
| audit_log_buffer_size | 1048576 |
| audit_log_compression | NONE |
| audit_log_connection_policy | ALL |
| audit_log_current_session | OFF |
| audit_log_database | mysql |
| audit_log_disable | OFF |
| audit_log_encryption | NONE |
| audit_log_exclude_accounts | |
| audit_log_file | audit.log |
| audit_log_filter_id | 0 |
| audit_log_flush | OFF |
| audit_log_flush_interval_seconds | 0 |
| 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 | 0 |
| audit_log_statement_policy | ALL |
| audit_log_strategy | ASYNCHRONOUS |
+--------------------------------------+--------------+
你可以在服务器启动时设置任何这些变量,有些变量可以在运行时设置。只能用于传统模式审计日志过滤的变量会有相应标注。
-
audit_log_buffer_size命令行格式 --audit-log-buffer-size=#系统变量 audit_log_buffer_size范围 全局 动态 否 SET_VAR提示适用否 类型 整数 默认值 1048576最小值 4096最大值(64 位平台) 18446744073709547520最大值(32 位平台) 4294967295单位 字节 块大小 4096当审计日志插件异步写入事件到日志时,它使用一个缓冲区来存储事件内容以便写入。此变量控制该缓冲区的大小,以字节为单位。服务器将该值调整为 4096 的倍数。插件使用一个缓冲区,在初始化时分配,终止时删除。插件仅在日志记录是异步的情况下分配此缓冲区。
-
audit_log_compression命令行格式 --audit-log-compression=value系统变量 audit_log_compression作用范围 全局 动态 否 SET_VAR提示适用否 类型 枚举 默认值 NONE有效值 NONE``GZIP审计日志文件的压缩类型。允许的值为
NONE(无压缩;默认值)���GZIP(GNU Zip 压缩)。有关更多信息,请参见压缩审计日志文件。 -
audit_log_connection_policy命令行格式 --audit-log-connection-policy=value已弃用 8.0.34 系统变量 audit_log_connection_policy作用范围 全局 动态 是 SET_VAR提示适用否 类型 枚举 默认值 ALL有效值 ALL``ERRORS``NONE注意
此已弃用的变量仅适用于传统模式审计日志过滤(参见第 8.4.5.10 节,“传统模式审计日志过滤”)。
控制审计日志插件将连接事件写入其日志文件的策略。以下表格显示了允许的值。
值 描述 ALL记录所有连接事件 ERRORS仅记录连接失败事件 NONE不记录连接事件 注意
在服务器启动时,如果还指定了
audit_log_policy,则可能会覆盖对audit_log_connection_policy的任何显式值,如第 8.4.5.5 节,“配置审计日志特性”中所述。 -
audit_log_current_session系统变量 audit_log_current_session作用范围 全局,会话 动态 否 SET_VARHint Applies否 类型 布尔值 默认值 取决于过滤策略当前会话是否启用审计日志记录。此变量的会话值只读。它在会话开始时根据
audit_log_include_accounts和audit_log_exclude_accounts系统变量的值设置。审计日志插件使用会话值来确定是否为会话审计事件。(有一个全局值,但插件不使用它。) -
audit_log_database命令行格式 --audit-log-database=value引入版本 8.0.33 系统变量 audit_log_database作用范围 全局 动态 否 SET_VARHint Applies否 类型 字符串 默认值 mysql指定
audit_log插件用于查找其表的数据库。此变量只读。更多信息,请参见第 8.4.5.2 节,“安装或卸载 MySQL Enterprise Audit”。 -
audit_log_disable命令行格式 --audit-log-disable[={OFF|ON}]引入版本 8.0.28 系统变量 audit_log_disable作用范围 全局 动态 是 SET_VARHint Applies否 类型 布尔值 默认值 OFF允许禁用所有连接和已连接会话的审计日志记录。除了
SYSTEM_VARIABLES_ADMIN权限外,禁用审计日志记录还需要AUDIT_ADMIN权限。请参见第 8.4.5.9 节,“禁用审计日志记录”。 -
audit_log_encryption命令行格式 --audit-log-encryption=value系统变量 audit_log_encryption作用范围 全局 动态 否 SET_VARHint Applies否 类型 枚举 默认值 NONE有效值 NONE``AES审计日志文件的加密类型。允许的值为
NONE(无加密;默认值)和AES(AES-256-CBC 密码加密)。有关更多信息,请参见加密审计日志文件。 -
audit_log_exclude_accounts命令行格式 --audit-log-exclude-accounts=value已弃用 8.0.34 系统变量 audit_log_exclude_accounts范围 全局 动态 是 SET_VAR提示适用否 类型 字符串 默认值 NULL注意
此已弃用变量仅适用于传统模式审计日志过滤(请参见第 8.4.5.10 节,“传统模式审计日志过滤”)。
不应记录事件的帐户。该值应为
NULL或包含一个或多个逗号分隔帐户名称列表的字符串。有关更多信息,请参见第 8.4.5.7 节,“审计日志过滤”。对
audit_log_exclude_accounts的修改仅影响在修改后创建的连接,而不影响现有连接。 -
audit_log_file命令行格式 --audit-log-file=file_name系统变量 audit_log_file范围 全�� 动态 否 SET_VAR提示适用否 类型 文件名 默认值 audit.log审计日志插件写入事件的文件的基本名称和后缀。默认值为
audit.log,无论日志格式如何。要使名称后缀与格式对应,必须显式设置名称,选择不同的后缀(例如,对于 XML 格式为audit.xml,对于 JSON 格式为audit.json)。如果
audit_log_file的值是相对路径名,则插件将其解释为相对于数据目录的路径。如果该值是完整路径名,则插件将直接使用该值。如果希望将审计文件定位到单独的文件系统或目录上,完整路径名可能会很有用。出于安全原因,将审计日志文件写入仅对 MySQL 服务器和有合理查看日志原因的用户可访问的目录。有关审计日志插件如何解释
audit_log_file值以及插件初始化和终止时发生的文件重命名规则的详细信息,请参见审计日志文件命名约定。审计日志插件使用包含审计日志文件的目录(从
audit_log_file的值确定)作为可读取审计日志文件的位置。从这些日志文件和当前文件中,插件构建了一个列表,其中包含适用于审计日志标记和读取功能的文件。参见第 8.4.5.6 节,“读取审计日志文件”。 -
audit_log_filter_id系统变量 audit_log_filter_id作用域 全局,会话 动态 否 SET_VAR提示适用否 类型 整数 默认值 1最小值 0最大值 4294967295此变量的会话值表示当前会话的内部维护的审计过滤器的 ID。值为 0 表示会话未分配任何过滤器。
-
audit_log_flush系统变量 audit_log_flush作用域 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF注意
audit_log_flush变量在 MySQL 8.0.31 中已被弃用;预计在未来的 MySQL 版本中将不再支持它。它已被audit_log_rotate()函数取代。如果
audit_log_rotate_on_size为 0,则自动审计日志文件轮换被禁用,只有在手动执行时才会发生轮换。在这种情况下,通过将audit_log_flush设置为 1 或ON来启用它会导致审计日志插件关闭并重新打开其日志文件以刷新它。(变量值保持为OFF,因此您无需在再次启用它以执行另一个刷新之前显式禁用它。)有关更多信息,请参见第 8.4.5.5 节,“配置审计日志特性”。 -
audit_log_flush_interval_seconds命令行格式 --audit-log-flush-interval-seconds[=value]引入版本 8.0.34 系统变量 audit_log_flush_interval_seconds范围 全局 动态 否 SET_VAR提示适用否 类型 无符号长整型 默认值 0最大值(Windows) 4294967295最大值(其他) 18446744073709551615单位 秒 此系统变量取决于必须安装和启用的
scheduler组件(请参阅第 7.5.5 节,“调度器组件”)。要检查组件的状态:SHOW VARIABLES LIKE 'component_scheduler%'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------| | component_scheduler.enabled | On | +-----------------------------+-------+当
audit_log_flush_interval_seconds的值为零(默认值)时,即使启用了scheduler组件(ON),也不会自动刷新权限。不允许值为
1和59;相反,这些值会自动调整为60,并且服务器会发出警告。大于60的值定义了scheduler组件从启动或上一次执行开始等待多少秒,直到尝试安排另一个执行。要将此全局系统变量持久化到
mysqld-auto.cnf文件中而不设置全局变量运行时值,请在变量名称之前加上PERSIST_ONLY关键字或@@PERSIST_ONLY.限定符。 -
audit_log_format命令行格式 --audit-log-format=value系统变量 audit_log_format范围 全局 动态 否 SET_VAR提示适用否 类型 枚举 默认值 NEW有效值 OLD``NEW``JSON审计日志文件格式。允许的值为
OLD(旧式 XML)、NEW(新式 XML;默认值)和JSON。有关每种格式的详细信息,请参阅第 8.4.5.4 节,“审计日志文件格式”。 -
audit_log_format_unix_timestamp命令行格式 --audit-log-format-unix-timestamp[={OFF|ON}]引入版本 8.0.26 系统变量 audit_log_format_unix_timestamp范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF此变量仅适用于 JSON 格式的审计日志输出。当为真时,启用此变量会导致每个日志文件记录包含一个
time字段。该字段值是一个整数,表示生成审计事件的日期和时间的 UNIX 时间戳值。在运行时更改此变量的值会导致日志文件轮换,以便对于给定的 JSON 格式日志文件,文件中的所有记录要么包含
time字段,要么不包含。在运行时设置
audit_log_format_unix_timestamp的值需要AUDIT_ADMIN权限,除了通常需要设置全局系统变量运行时值的SYSTEM_VARIABLES_ADMIN权限(或已弃用的SUPER权限)。 -
audit_log_include_accounts命令行格式 --audit-log-include-accounts=value已弃用 8.0.34 系统变量 audit_log_include_accounts范围 全局 动态 是 SET_VAR提示适用否 类型 字符串 默认值 NULL注意
此已弃用变量仅适用于传统模式的审计日志过滤(参见第 8.4.5.10 节,“传统模式审计日志过滤”)。
应记录事件的帐户。该值应为
NULL或包含一个或多个逗号分隔帐户名称列表的字符串。有关更多信息,请参见第 8.4.5.7 节,“审计日志过滤”。对
audit_log_include_accounts的修改仅影响在修改后创建的连接,而不影响现有连接。 -
audit_log_max_size命令行格式 --audit-log-max-size=#引入 8.0.26 系统变量 audit_log_max_size范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 0最小值 0最大值(Windows) 4294967295最大值(其他) 18446744073709551615单位 字节 块大小 4096audit_log_max_size涉及仅支持 JSON 格式日志文件的日志文件修剪。它控制基于组合日志文件大小的修剪:-
值为 0(默认)会禁用基于大小的修剪。不强制执行大小限制。
-
值大于 0 会启用基于大小的修剪。该值是超过该值后日志文件变得需要修剪的组合大小。
如果将
audit_log_max_size设置为不是 4096 的倍数的值,则会被截断为最接近的倍数。特别是,将其设置为小于 4096 的值会将其设置为 0,不会发生基于大小的修剪。如果
audit_log_max_size和audit_log_rotate_on_size都大于 0,则audit_log_max_size应该大于audit_log_rotate_on_size的值的 7 倍以上。否则,会向服务器错误日志写入警告,因为在这种情况下,基于大小的修剪的“粒度”可能不足以防止每次发生时删除所有或大部分旋转的日志文件。注意
设置
audit_log_max_size本身并不足以导致日志文件修剪,因为修剪算法同时使用audit_log_rotate_on_size,audit_log_max_size和audit_log_prune_seconds。详情请参见审计日志文件的空间管理。 -
-
audit_log_password_history_keep_days命令行格式 --audit-log-password-history-keep-days=#引入版本 8.0.17 系统变量 audit_log_password_history_keep_days范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 0最小值 0最大值 4294967295单位 天 审计日志插件使用存储在 MySQL 密钥环中的加密密码实现日志文件加密(请参阅加密审计日志文件)。该插件还实现了密码历史记录,包括密码存档和过期(删除)。
当审计日志插件创建新的加密密码时,它会存档先前的密码(如果存在),以供以后使用。
audit_log_password_history_keep_days变量控制过期存档密码的自动删除。其值表示存档的审计日志加密密码在多少天后被删除。默认值为 0,禁用密码过期:密码保留期永远。在以下情况下创建新的审计日志加密密码:
-
在插件初始化期间,如果插件发现启用了日志文件加密,则会检查密钥环是否包含审计日志加密密码。如果没有,则插件会自动生成一个随机初始加密密码。
-
当调用
audit_log_encryption_password_set()函数设置特定密码时。
在每种情况下,插件将新密码存储在密钥环中,并用它来加密新的日志文件。
在以下情况下移除过期的审计日志加密密码:
-
在插件初始化期间。
-
当调用
audit_log_encryption_password_set()函数时。 -
当
audit_log_password_history_keep_days的运行时值从当前值更改为大于 0 的值时。运行时值更改发生在使用GLOBAL或PERSIST关键字的SET语句,但不适用于PERSIST_ONLY关键字。PERSIST_ONLY将变量设置写入mysqld-auto.cnf,但不影响运行时值。
当密码移除发生时,当前值
audit_log_password_history_keep_days决定要移除哪些密码:-
如果值为 0,则插件不会删除任何密码。
-
如果值为*
N* > 0,则插件会删除超过*N*天的密码。
注意
注意不要过期仍然需要读取已归档的加密日志文件的旧密码。
如果通常禁用密码过期(即
audit_log_password_history_keep_days的值为 0),可以通过临时分配大于零的值来执行按需清理操作。例如,要使超过 365 天的密码过期,请执行以下操作:SET GLOBAL audit_log_password_history_keep_days = 365; SET GLOBAL audit_log_password_history_keep_days = 0;设置运行时值
audit_log_password_history_keep_days需要AUDIT_ADMIN权限,除了通常需要设置全局系统变量运行时值的SYSTEM_VARIABLES_ADMIN权限(或已弃用的SUPER权限)。 -
-
audit_log_policy命令行格式 --audit-log-policy=value已弃用 8.0.34 系统变量 audit_log_policy范围 全局 动态 否 SET_VAR提示适用否 类型 枚举 默认值 ALL有效值 ALL``LOGINS``QUERIES``NONE注意
此弃用变量仅适用于传统模式审计日志过滤(参见第 8.4.5.10 节,“传统模式审计日志过滤”)。
控制审计日志插件将事件写入其日志文件的策略。以下表格显示了允许的值。
值 描述 ALL记录所有事件 LOGINS仅记录登录事件 QUERIES仅记录查询事件 NONE什么都不记录(禁用审计流) audit_log_policy只能在服务器启动时设置。在运行时,它是一个只读变量。另外两个系统变量,audit_log_connection_policy和audit_log_statement_policy,提供对日志记录策略的更精细控制,可以在启动时或运行时设置。如果在启动时使用audit_log_policy而不是其他两个变量,则服务器会使用其值来设置这些变量。有关策略变量及其交互的更多信息,请参见第 8.4.5.5 节,“配置审计日志特性”。 -
audit_log_prune_seconds命令行格式 --audit-log-prune-seconds=#引入版本 8.0.24 系统变量 audit_log_prune_seconds范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 0最小值 0最大值(Windows) 4294967295最大值(其他) 18446744073709551615单位 字节 audit_log_prune_seconds涉及审计日志文件修剪,仅支持 JSON 格式的日志文件。它根据日志文件的年龄控制修剪:-
值为 0(默认值)会禁用基于年龄的修剪。不强制执行年龄限制。
-
值大于 0 会启用基于年龄的修剪。该值是日志文件变得需要修剪的秒数。
注意
单独设置
audit_log_prune_seconds是不足以导致日志文件修剪发生的,因为修剪算法同时使用audit_log_rotate_on_size、audit_log_max_size和audit_log_prune_seconds。有关详细信息,请参见 审计日志文件的空间管理。 -
-
audit_log_read_buffer_size命令行格式 --audit-log-read-buffer-size=#系统变量 audit_log_read_buffer_size范围 (≥ 8.0.12) 全局, 会话 范围 (8.0.11) 全局 动态 (≥ 8.0.12) 是 动态 (8.0.11) 否 SET_VAR提示适用否 类型 整数 默认值 (≥ 8.0.12) 32768默认值 (8.0.11) 1048576最小值 (≥ 8.0.12) 32768最小值 (8.0.11) 1024最大值 4194304单位 字节 从审计日志文件中读取的缓冲区大小,以字节为单位。
audit_log_read()函数最多读取这么多字节。仅支持 JSON 日志格式的日志文件读取。有关更多信息,请参见 第 8.4.5.6 节,“读取审计日志文件”。截至 MySQL 8.0.12,此变量默认为 32KB,并可在运行时设置。每个客户端应适当设置其
audit_log_read_buffer_size的会话值,以供其使用audit_log_read()。在 MySQL 8.0.12 之前,audit_log_read_buffer_size默认为 1MB,影响所有客户端,并且只能在服务器启动时更改。 -
audit_log_rotate_on_size命令行格式 --audit-log-rotate-on-size=#系统变量 audit_log_rotate_on_size范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 0最小值 0最大值 18446744073709551615单位 字节 块大小 4096如果
audit_log_rotate_on_size为 0,则审计日志插件不执行基于大小的自动日志文件轮换。如果要进行旋转,必须手动执行;请参见手动审计日志文件旋转(MySQL 8.0.31 之前)。如果
audit_log_rotate_on_size大于 0,则会发生基于大小的自动日志文件轮换。每当写入日志文件导致其大小超过audit_log_rotate_on_size值时,审计日志插件会重命名当前日志文件,并使用原始名称打开一个新的当前日志文件。如果将
audit_log_rotate_on_size设置为不是 4096 的倍数的值,则会将其截断为最接近的倍数。特别是,将其设置为小于 4096 的值会将其设置为 0,并且不会发生旋转,除非手动执行。注意
audit_log_rotate_on_size控制是否发生审计日志文件轮换。它还可以与audit_log_max_size和audit_log_prune_seconds一起用于配置旋转 JSON 格式日志文件的修剪。有关详细信息,请参见审计日志文件的空间管理。 -
audit_log_statement_policy命令行格式 --audit-log-statement-policy=value已弃用 8.0.34 系统变量 audit_log_statement_policy范围 全局 动态 是 SET_VAR提示适用否 类型 枚举 默认值 ALL有效值 ALL``ERRORS``NONE注意
此已弃用的变量仅适用于传统模式审计日志过滤(参见第 8.4.5.10 节,“传统模式审计日志过滤”)。
控制审计日志插件如何将语句事件写入其日志文件的策略。以下表格显示了允许的值。
值 描述 ALL记录所有语句事件 ERRORS仅记录失败的语句事件 NONE不记录语句事件 注意
在服务器启动时,如果还指定了
audit_log_policy,则可以覆盖为audit_log_statement_policy给出的任何显式值,如第 8.4.5.5 节,“配置审计日志特性”中所述。 -
audit_log_strategy命令行格式 --audit-log-strategy=value系统变量 audit_log_strategy范围 全局 动态 否 SET_VAR提示适用否 类型 枚举 默认值 ASYNCHRONOUS有效值 ASYNCHRONOUS``PERFORMANCE``SEMISYNCHRONOUS``SYNCHRONOUS审计日志插件使用的记录方法。允许使用以下策略值:
-
ASYNCHRONOUS:异步记录。等待输出缓冲区中的空间。 -
PERFORMANCE:异步记录。在输出缓冲区中没有足够空间的请求将被丢弃。 -
SEMISYNCHRONOUS:同步记录。允许操作系统进行缓存。 -
SYNCHRONOUS:同步记录。在每个请求后调用sync()。
-
审计日志状态变量
如果启用了审计日志插件,则会公开几个提供操作信息的状态变量。这些变量适用于遗留模式审计过滤(在 MySQL 8.0.34 中已弃用)和 JSON 模式审计过滤。
-
Audit_log_current_size当前审计日志文件的大小。当事件写入日志时,该值会增加,并在日志轮换时重置为 0。
-
Audit_log_event_max_drop_size性能记录模式中最大丢弃事件的大小。有关记录模式的描述,请参见第 8.4.5.5 节,“配置审计日志特性”。
-
Audit_log_events由审计日志插件处理的事件数量,无论是否根据过滤策略写入日志(参见第 8.4.5.5 节,“配置审计日志特性”)。
-
Audit_log_events_filtered基于过滤策略(参见第 8.4.5.5 节,“配置审计日志特性”),由审计日志插件处理的事件数量被过滤(未写入日志)。
-
Audit_log_events_lost在性能记录模式下丢失的事件数量,因为事件大于可用的审计日志缓冲区空间。此值可能有助于评估如何设置
audit_log_buffer_size以调整性能模式的缓冲区大小。有关记录模式的描述,请参见第 8.4.5.5 节,“配置审计日志特性”。 -
Audit_log_events_written写入审计日志的事件数量。
-
Audit_log_total_size所有审计日志文件中写入的事件总大小。与
Audit_log_current_size不同,Audit_log_total_size的值在日志轮换时也会增加。 -
Audit_log_write_waits在异步记录模式下,事件必须等待审计日志缓冲区中的空间的次数。有关记录模式的描述,请参见第 8.4.5.5 节,“配置审计日志特性”。
原文:
dev.mysql.com/doc/refman/8.0/en/audit-log-restrictions.html
8.4.5.12 审计日志限制
MySQL Enterprise Audit 受到以下一般限制:
-
仅记录 SQL 语句。通过非 SQL API(如 memcached、Node.JS 和 NDB API)进行的更改不会被记录。
-
仅记录顶层语句,不记录存储程序内部的语句,如触发器或存储过程中的语句。
-
诸如
LOAD DATA这类语句引用的文件内容不会被记录。
NDB 集群。 可以在 MySQL NDB 集群中使用 MySQL Enterprise Audit,但需符合以下条件:
-
所有要记录的更改必须使用 SQL 接口完成。使用非 SQL 接口进行的更改(如 NDB API、memcached 或 ClusterJ 提供的接口)不会被记录。
-
插件必须安装在用于在集群上执行 SQL 的每个 MySQL 服务器上。
-
审计插件数据必须在用于集群的所有 MySQL 服务器之间进行聚合。这种聚合是应用程序或用户的责任。
8.4.6 审计消息组件
原文:
dev.mysql.com/doc/refman/8.0/en/audit-api-message-emit.html
截至 MySQL 8.0.14,audit_api_message_emit 组件使应用程序能够使用 audit_api_message_emit_udf() 函数将自己的消息事件添加到审计日志中。
audit_api_message_emit 组件与所有类型为审计的插件合作。为了具体起见,示例使用了第 8.4.5 节,“MySQL 企业审计”中描述的 audit_log 插件。
-
安装或卸载审计消息组件
-
审计消息函数
安装或卸载审计消息组件
要使服务器可用,组件库文件必须位于 MySQL 插件目录中(由 plugin_dir 系统变量命名的目录)。如果需要,通过在服务器启动时设置 plugin_dir 的值来配置插件目录位置。
要安装 audit_api_message_emit 组件,请使用以下语句:
INSTALL COMPONENT "file://component_audit_api_message_emit";
组件安装是一次性操作,不需要每次服务器启动都执行。INSTALL COMPONENT 加载组件,并在 mysql.component 系统表中注册它,以便在后续服务器启动时加载它。
要卸载 audit_api_message_emit 组件,请使用以下语句:
UNINSTALL COMPONENT "file://component_audit_api_message_emit";
UNINSTALL COMPONENT 卸载组件,并从 mysql.component 系统表中注销它,以使其在后续服务器启动时不加载。
因为安装和卸载 audit_api_message_emit 组件会安装和卸载组件实现的 audit_api_message_emit_udf() 函数,所以不需要使用 CREATE FUNCTION 或 DROP FUNCTION 来执行此操作。
审计消息函数
本节描述了 audit_api_message_emit 组件实现的 audit_api_message_emit_udf() 函数。
在使用审计消息函数之前,请根据安装或卸载审计消息组件中提供的说明安装审计消息组件。
-
audit_api_message_emit_udf(*component*, *producer*, *message*[, *key*, *value*] ...)向审计日志添加消息事件。消息事件包括调用者选择的组件、生产者和消息字符串,以及可选的一组键值对。
由此函数发布的事件发送到所有已启用的审计类型插件,每个插件根据自己的规则处理事件。如果未启用任何审计类型的插件,则发布事件不会产生任何效果。
参数:
-
component: 一个指定组件名称的字符串。 -
producer: 一个指定生产者名称的字符串。 -
message: 一个指定事件消息的字符串。 -
key,value: 事件可能包括 0 或多个键值对,指定任意应用程序提供的数据映射。每个key参数是一个指定其紧随其后的value参数名称的字符串。每个value参数指定其紧随其后的key参数的值。每个value可以是字符串或数值,或NULL。
返回值:
字符串
OK表示成功。如果函数失败,则会发生错误。示例:
mysql> SELECT audit_api_message_emit_udf('component_text', 'producer_text', 'message_text', 'key1', 'value1', 'key2', 123, 'key3', NULL) AS 'Message'; +---------+ | Message | +---------+ | OK | +---------+附加信息:
由
audit_api_message_emit_udf()接收到的事件由每个启用的审计类型插件以特定于插件的格式记录。例如,audit_log插件(参见 Section 8.4.5, “MySQL Enterprise Audit”)根据由audit_log_format系统变量配置的日志格式记录消息值,具体取决于配置的日志格式:-
JSON 格式(
audit_log_format=JSON):{ ... "class": "message", "event": "user", ... "message_data": { "component": "component_text", "producer": "producer_text", "message": "message_text", "map": { "key1": "value1", "key2": 123, "key3": null } } } -
新式 XML 格式(
audit_log_format=NEW):<AUDIT_RECORD> ... <NAME>Message</NAME> ... <COMMAND_CLASS>user</COMMAND_CLASS> <COMPONENT>component_text</COMPONENT> <PRODUCER>producer_text</PRODUCER> <MESSAGE>message_text</MESSAGE> <MAP> <ELEMENT> <KEY>key1</KEY> <VALUE>value1</VALUE> </ELEMENT> <ELEMENT> <KEY>key2</KEY> <VALUE>123</VALUE> </ELEMENT> <ELEMENT> <KEY>key3</KEY> <VALUE/> </ELEMENT> </MAP> </AUDIT_RECORD> -
旧式 XML 格式(
audit_log_format=OLD):<AUDIT_RECORD ... NAME="Message" ... COMMAND_CLASS="user" COMPONENT="component_text" PRODUCER="producer_text" MESSAGE="message_text"/>注意
以旧式 XML 格式记录的消息事件不包括键值映射,因为该格式施加的表现约束。
由
audit_api_message_emit_udf()发布的消息具有MYSQL_AUDIT_MESSAGE_CLASS的事件类别和MYSQL_AUDIT_MESSAGE_USER的子类别。(内部生成的审计消息具有相同的类别和MYSQL_AUDIT_MESSAGE_INTERNAL的子类别;目前未使用此子类别。)要在audit_log过滤规则中引用此类事件,请使用具有name值为message的class元素。例如:{ "filter": { "class": { "name": "message" } } }如果需要区分用户生成的和内部生成的消息事件,请将
subclass值与user或internal进行测试。不支持基于键值映射内容的过滤。
有关编写过滤规则的信息,请���阅 Section 8.4.5.7, “Audit Log Filtering”。
-
8.4.7 MySQL 企业防火墙
8.4.7.1 MySQL 企业防火墙元素
8.4.7.2 安装或卸载 MySQL 企业防火墙
8.4.7.3 使用 MySQL 企业防火墙
8.4.7.4 MySQL 企业防火墙参考
注意
MySQL 企业防火墙是 MySQL 企业版中包含的一个扩展,是一款商业产品。要了解更多关于商业产品的信息,请参见www.mysql.com/products/。
MySQL 企业版包括 MySQL 企业防火墙,这是一个应用级防火墙,允许数据库管理员根据匹配接受的语句模式列表来允许或拒绝 SQL 语句的执行。这有助于加固 MySQL 服务器,防止 SQL 注入等攻击或试图利用应用程序以外的合法查询工作负载特征。
注册到防火墙的每个 MySQL 账户都有自己的语句允许列表,可以根据账户进行定制保护。对于给定的账户,防火墙可以在记录、保护或检测模式下运行,用于训练接受的语句模式、主动保护不可接受的语句或被动检测不可接受的语句。该图示说明了防火墙在每种模式下如何处理传入的语句。
图 8.1 MySQL 企业防火墙操作
以下各节描述了 MySQL 企业防火墙的元素,讨论了如何安装和使用它,并为其元素提供参考信息。
8.4.7.1 MySQL 企业防火墙的元素
MySQL 企业防火墙基于一个包含以下元素的插件库:
-
一个名为
MYSQL_FIREWALL的服务器端插件在 SQL 语句执行之前检查,并根据注册的防火墙配置文件,决定是否执行或拒绝每个语句。 -
MYSQL_FIREWALL插件,以及名为MYSQL_FIREWALL_USERS和MYSQL_FIREWALL_WHITELIST的服务器端插件实现了性能模式和INFORMATION_SCHEMA表,提供了对注册配置文件的视图。 -
配置文件在内存中缓存以提高性能。
mysql系统数据库中的表提供了防火墙数据的后备存储,以确保配置文件在服务器重新启动时持久化。 -
存储过程执行诸如注册防火墙配置文件、建立其操作模式以及管理缓存与持久存储之间的防火墙数据传输等任务。
-
管理功能提供了一个 API 用于较低级别的任务,比如将缓存与持久存储同步。
-
系统变量使防火墙配置生效,状态变量提供运行时操作信息。
-
FIREWALL_ADMIN和FIREWALL_USER权限使用户能够管理任何用户的防火墙规则,以及他们自己的防火墙规则。 -
FIREWALL_EXEMPT权限(自 MySQL 8.0.27 起可用)免除用户的防火墙限制。例如,对于配置防火墙的任何数据库管理员来说,这是有用的,以避免错误配置导致管理员被锁定并无法执行语句的可能性。
原文:
dev.mysql.com/doc/refman/8.0/en/firewall-installation.html
8.4.7.2 安装或卸载 MySQL 企业防火墙
MySQL 企业防火墙安装是一次性操作,安装了 第 8.4.7.1 节,“MySQL 企业防火墙的元素” 中描述的元素。安装可以使用图形界面或手动进行:
-
在 Windows 上,MySQL 安装程序包括一个选项,可以为您启用 MySQL 企业防火墙。
-
MySQL Workbench 6.3.4 或更高版本可以安装 MySQL 企业防火墙,启用或禁用已安装的防火墙,或卸载防火墙。
-
手动安装 MySQL 企业防火墙涉及运行位于 MySQL 安装的
share目录中的脚本。
重要
在按照本节的说明之前,请阅读整个部分。根据您的环境,步骤的某些部分可能有所不同。
注意
如果安装了 MySQL 企业防火墙,即使禁用了,也会带来一些最小的开销。为避免这种开销,请不要安装防火墙,除非您打算使用它。
有关使用说明,请参阅 第 8.4.7.3 节,“使用 MySQL 企业防火墙”。有关参考信息,请参阅 第 8.4.7.4 节,“MySQL 企业防火墙参考”。
-
安装 MySQL 企业防火墙
-
卸载 MySQL 企业防火墙
安装 MySQL 企业防火墙
如果 MySQL 企业防火墙已经从较旧版本的 MySQL 安装,使用本节后面给出的说明卸载它,然后在安装当前版本之前重新启动服务器。在这种情况下,还需要重新注册您的配置。
在 Windows 上,您可以使用 MySQL 安装程序来安装 MySQL 企业防火墙,如 图 8.2,“Windows 上的 MySQL 企业防火墙安装” 所示。勾选启用 MySQL 企业防火墙复选框。(为网络访问打开防火墙端口有不同的目的。它指的是 Windows 防火墙,并控制 Windows 是否阻止 MySQL 服务器用于客户端连接的 TCP/IP 端口。)
重要
对于使用 MySQL 安装程序安装的 MySQL 8.0.19 存在一个问题,如果在服务器配置步骤中选择了 MySQL 企业防火墙,则会阻止服务器启动。如果服务器启动操作失败,请单击“取消”以结束配置过程并返回仪表板。您必须卸载服务器。
解决方法是在没有选择 MySQL 企业防火墙的情况下运行 MySQL 安装程序。(即,不要选择启用 MySQL 企业防火墙复选框。)然后按照本节后面的手动安装说明安装 MySQL 企业防火墙。这个问题在 MySQL 8.0.20 中已经得到修正。
图 8.2 Windows 上的 MySQL 企业防火墙安装
要使用 MySQL Workbench 6.3.4 或更高版本安装 MySQL 企业防火墙,请参阅 MySQL 企业防火墙界面。
要手动安装 MySQL 企业防火墙,请查看 MySQL 安装的share目录,并选择适合您平台的脚本。可用的脚本在用于引用脚本的文件名上有所不同:
-
win_install_firewall.sql -
linux_install_firewall.sql
安装脚本在默认数据库mysql中创建存储过程。在命令行上运行脚本如下。这里的示例使用 Linux 安装脚本。对于您的系统进行适当的替换。
$> mysql -u root -p < linux_install_firewall.sql
Enter password: *(enter root password here)*
注意
要在源/副本复制、组复制或 InnoDB 集群的上下文中使用 MySQL 企业防火墙,必须在在源节点上运行安装脚本之前准备好副本节点。这是必要的,因为脚本中的INSTALL PLUGIN语句不会被复制。
-
在每个副本节点上,从安装脚本中提取
INSTALL PLUGIN语句,并手动执行它们。 -
在源节点上,按照前面描述的方式运行安装脚本。
使用图形界面或手动安装 MySQL 企业防火墙应该启用防火墙。要验证,请连接到服务器并执行此语句:
mysql> SHOW GLOBAL VARIABLES LIKE 'mysql_firewall_mode';
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| mysql_firewall_mode | ON |
+---------------------+-------+
如果插件初始化失败,请检查服务器错误日志以获取诊断消息。
卸载 MySQL 企业防火墙
MySQL 企业防火墙可以使用 MySQL Workbench 或手动卸载。
要使用 MySQL Workbench 6.3.4 或更高版本卸载 MySQL 企业防火墙,请参阅 MySQL 企业防火墙界面,在第三十三章,MySQL Workbench中。
要手动卸载 MySQL 企业防火墙,请执行以下语句。语句使用IF EXISTS,因为根据先前安装的防火墙版本,一些对象可能不存在,或者通过卸载安装它们的插件而被隐式删除。
DROP TABLE IF EXISTS mysql.firewall_group_allowlist;
DROP TABLE IF EXISTS mysql.firewall_groups;
DROP TABLE IF EXISTS mysql.firewall_membership;
DROP TABLE IF EXISTS mysql.firewall_users;
DROP TABLE IF EXISTS mysql.firewall_whitelist;
UNINSTALL PLUGIN MYSQL_FIREWALL;
UNINSTALL PLUGIN MYSQL_FIREWALL_USERS;
UNINSTALL PLUGIN MYSQL_FIREWALL_WHITELIST;
DROP FUNCTION IF EXISTS firewall_group_delist;
DROP FUNCTION IF EXISTS firewall_group_enlist;
DROP FUNCTION IF EXISTS mysql_firewall_flush_status;
DROP FUNCTION IF EXISTS normalize_statement;
DROP FUNCTION IF EXISTS read_firewall_group_allowlist;
DROP FUNCTION IF EXISTS read_firewall_groups;
DROP FUNCTION IF EXISTS read_firewall_users;
DROP FUNCTION IF EXISTS read_firewall_whitelist;
DROP FUNCTION IF EXISTS set_firewall_group_mode;
DROP FUNCTION IF EXISTS set_firewall_mode;
DROP PROCEDURE IF EXISTS mysql.sp_firewall_group_delist;
DROP PROCEDURE IF EXISTS mysql.sp_firewall_group_enlist;
DROP PROCEDURE IF EXISTS mysql.sp_reload_firewall_group_rules;
DROP PROCEDURE IF EXISTS mysql.sp_reload_firewall_rules;
DROP PROCEDURE IF EXISTS mysql.sp_set_firewall_group_mode;
DROP PROCEDURE IF EXISTS mysql.sp_set_firewall_group_mode_and_user;
DROP PROCEDURE IF EXISTS mysql.sp_set_firewall_mode;
DROP PROCEDURE IF EXISTS mysql.sp_migrate_firewall_user_to_group;
8.4.7.3 使用 MySQL 企业防火墙
在使用 MySQL 企业防火墙之前,请根据 Section 8.4.7.2, “安装或卸载 MySQL 企业防火墙”中提供的说明进行安装。
本节描述了如何使用 SQL 语句配置 MySQL 企业防火墙。另外,MySQL Workbench 6.3.4 或更高版本提供了用于防火墙控制的图形界面。参见 MySQL 企业防火墙界面。
-
启用或禁用防火墙
-
分配防火墙权限
-
防火墙概念
-
注册防火墙组配置文件
-
注册防火墙帐户配置文件
-
监控防火墙
-
将帐户配置文件迁移到组配置文件
启用或禁用防火墙
要启用或禁用防火墙,请设置mysql_firewall_mode系统变量。默认情况下,当安装防火墙时,此变量已启用。要明确控制初始防火墙状态,可以在服务器启动时设置该变量。例如,要在选项文件中启用防火墙,请使用以下行:
[mysqld]
mysql_firewall_mode=ON
修改my.cnf后,重新启动服务器以使新设置生效。
或者,要在运行时设置和持久化防火墙设置:
SET PERSIST mysql_firewall_mode = OFF;
SET PERSIST mysql_firewall_mode = ON;
SET PERSIST为正在运行的 MySQL 实例设置一个值。它还保存该值,导致其在后续服务器重新启动时保留。要更改正在运行的 MySQL 实例的值,而不使其在后续重新启动时保留,使用GLOBAL关键字而不是PERSIST。参见 Section 15.7.6.1, “变量赋值的 SET 语法”。
分配防火墙权限
安装防火墙后,向用于管理它的 MySQL 帐户或帐户授予适当的权限。权限取决于帐户应被允许执行哪些防火墙操作:
-
将
FIREWALL_EXEMPT权限(自 MySQL 8.0.27 起可用)授予任何应免于防火墙限制的帐户。例如,对于配置防火墙的数据库管理员来说,这很有用,以避免配置错误导致甚至管理员也被锁定并无法执行语句的可能性。 -
将
FIREWALL_ADMIN权限授予任何应具有完全管理防火墙访问权限的帐户。(某些管理防火墙功能可以由具有FIREWALL_ADMIN或已弃用的SUPER权限的帐户调用,如各个功能描述中所示。) -
将
FIREWALL_USER权限授予任何应仅具有其自身防火墙规则的管理访问权限的帐户。 -
为
mysql系统数据库中的防火墙存储过程授予EXECUTE权限。这些存储过程可能调用管理功能,因此存储过程访问还需要前面所需的用于这些功能的权限。
注意
只能在安装了防火墙时授予FIREWALL_EXEMPT、FIREWALL_ADMIN和FIREWALL_USER权限,因为MYSQL_FIREWALL插件定义了这些权限。
防火墙概念
MySQL 服务器允许客户端连接并接收他们发送的要执行的 SQL 语句。如果启用了防火墙,服务器会将每个未立即因语法错误而失败的传入语句传递给它。根据防火墙是否接受该语句,服务器会执行它或向客户端返回错误。本节描述了防火墙如何完成接受或拒绝语句的任务。
-
防火墙配置文件
-
防火墙语句匹配
-
配置文件操作模式
-
多个配置文件应用时的防火墙语句处理
防火墙配置文件
防火墙使用确定是否允许语句执行的配置文件注册表。配置文件具有以下属性:
-
允许列表。允许列表是定义哪些语句可接受到配置文件的规则集。
-
当前的操作模式。该模式使得可以以不同方式使用配置文件。例如:配置文件可以置于训练模式以建立白名单;白名单可用于限制语句执行或入侵检测;配置文件可以完全禁用。
-
适用范围。范围指示配置文件适用于哪些客户端连接:
-
防火墙支持基于账户的配置文件,使得每个配置文件都匹配特定的客户端账户(客户端用户名和主机名组合)。例如,您可以注册一个账户配置文件,其中白名单适用于源自
admin@localhost的连接,以及另一个账户配置文件,其中白名单适用于源自myapp@apphost.example.com的连接。 -
截至 MySQL 8.0.23 版本,防火墙支持可以有多个账户作为成员的组配置文件,配置文件白名单对所有成员均等适用。组配置文件使得对于需要将给定的一组白名单规则应用于多个账户的部署,管理更加简便且灵活。
-
最初,不存在任何配置文件,因此默认情况下,防火墙接受所有语句,并不影响 MySQL 账户可以执行哪些语句。要应用防火墙的保护功能,需要采取明确的行动:
-
向防火墙注册一个或多个配置文件。
-
通过为每个配置文件建立白名单来训练防火墙;也就是说,配置文件允许客户端执行的语句类型。
-
将训练过的配置文件置于保护模式,以加固 MySQL 防止未经授权的语句执行:
-
MySQL 将每个客户端会话与特定的用户名和主机名组合关联。这个组合就是会话账户。
-
对于每个客户端连接,防火墙使用会话账户来确定哪些配置文件适用于处理客户端发出的语句。
防火墙仅接受适用于适用配置文件白名单的语句。
-
大多数防火墙原则在组配置文件和账户配置文件上都适用。这两种类型的配置文件在以下方面有所不同:
-
账户配置文件白名单仅适用于单个账户。组配置文件白名单适用于会话账户匹配任何属于该组的账户时。
-
使用账户配置文件为多个账户应用白名单时,需要为每个账户注册一个配置文件,并在每个配置文件中复制白名单。这意味着必须单独训练每个账户配置文件,因为每个配置文件必须使用适用于其的单个账户进行训练。
组配置文件白名单适用于多个账户,无需为每个账户重复。组配置文件可以使用任何或所有组成员账户进行训练,或者训练可以限制为任何单个成员。无论哪种方式,白名单都适用于所有成员。
-
帐户配置文件名称基于连接到 MySQL 服务器的客户端取决于特定用户名称和主机名组合。组配置文件名称由防火墙管理员选择,除了长度必须在 1 到 288 个字符之外,没有其他约束。
注意
由于组配置文件比帐户配置文件具有优势,并且因为具有单个成员帐户的组配置文件在逻辑上等同于该帐户的帐户配置文件,建议所有新的防火墙配置文件都创建为组配置文件。从 MySQL 8.0.26 开始,帐户配置文件已被弃用,并且将在未来的 MySQL 版本中被移除。有关转换现有帐户配置文件的帮助,请参阅 Migrating Account Profiles to Group Profiles。
防火墙提供的基于配置文件的保护使得可以实施以下策略:
-
如果应用程序具有独特的保护要求,请配置它使用不用于任何其他目的的帐户,并为该帐户设置组配置文件或帐户配置文件。
-
如果相关应用程序共享保护要求,请将每个应用程序与其自己的帐户关联,然后将这些应用程序帐户添加为同一组配置文件的成员。或者,配置所有应用程序使用相同的帐户,并将它们与该帐户的帐户配置文件关联。
防火墙语句匹配
防火墙执行的语句匹配不使用从客户端接收的 SQL 语句。相反,服务器将传入的语句转换为规范化的摘要形式,防火墙操作使用这些摘要。语句规范化的好处在于它使相似的语句能够被分组并使用单个模式识别。例如,这些语句彼此不同:
SELECT first_name, last_name FROM customer WHERE customer_id = 1;
select first_name, last_name from customer where customer_id = 99;
SELECT first_name, last_name FROM customer WHERE customer_id = 143;
但它们都具有相同的规范化摘要形式:
SELECT `first_name` , `last_name` FROM `customer` WHERE `customer_id` = ?
通过规范化,防火墙白名单可以存储与从客户端接收的许多不同语句匹配的摘要。有关规范化和摘要的更多信息,请参阅第 29.10 节,“性能模式语句摘要和抽样”。
警告
将max_digest_length系统变量设置为零会禁用摘要生成,这也会禁用需要摘要的服务器功能,例如 MySQL Enterprise Firewall。
配置文件操作模式
注册到防火墙的每个配置文件都有自己的操作模式,可以从以下值中选择:
-
OFF:此模式禁用配置文件。防火墙将其视为无效并忽略它。 -
RECORDING:这是防火墙的训练模式。从客户端接收的与配置文件匹配的传入语句被视为配置文件可接受的一部分,并成为其“指纹”的一部分。防火墙记录每个语句的规范化摘要形式,以学习配置文件的可接受语句模式。每个模式都是一个规则,规则的并集是配置文件白名单。组和账户配置文件之间的区别在于,组配置文件的语句记录可以限制为仅接收来自单个组成员(培训成员)的语句。
-
PROTECTING:在此模式下,配置文件允许或阻止语句执行。防火墙将传入的语句与配置文件白名单进行匹配,仅接受与之匹配的语句,并拒绝不匹配的语句。在RECORDING模式下训练配置文件后,将其切换到PROTECTING模式以加固 MySQL 防止被偏离白名单的语句访问。如果启用了mysql_firewall_trace系统变量,防火墙还会将被拒绝的语句写入错误日志。 -
DETECTING:此模式检测但不阻止入侵(与配置文件白名单中没有匹配的语句因为可疑而被拦截)。在DETECTING模式下,防火墙将可疑语句写入错误日志,但接受它们而不拒绝访问。
当配置文件被分配任何前述模式值时,防火墙会将模式存储在配置文件中。防火墙模式设置操作还允许使用RESET模式值,但不会存储此值:将配置文件设置为RESET模式会导致防火墙删除配置文件的所有规则并将其模式设置为OFF。
注意
在DETECTING模式下写入错误日志的消息或因为启用了mysql_firewall_trace而写入的消息被写入为 Notes,这些是信息消息。为确保这些消息出现在错误日志中并且不被丢弃,请确保错误日志的详细程度足以包括信息消息。例如,如果您正在使用基于优先级的日志过滤,如第 7.4.2.5 节,“基于优先级的错误日志过滤(log_filter_internal)”中描述的那样,请将log_error_verbosity系统变量设置为值 3。
当多个配置文件适用时的防火墙语句处理
为简单起见,后续描述如何设置配置文件的部分将从防火墙将客户端传入语句与仅一个配置文件(组配置文件或账户配置文件)匹配的角度进行。但是防火墙操作可能更加复杂:
-
组配置文件可以包括多个账户作为成员。
-
一个账户可以是多个组配置文件的成员。
-
多个配置文件可以匹配给定的客户端。
以下描述涵盖了防火墙在可���有多个配置文件适用于传入语句时的一般操作情况。
正如之前提到的,MySQL 将每个客户端会话与特定的用户名和主机名组合(称为会话账户)关联起来。防火墙将会话账户与注册的配置文件进行匹配,以确定哪些配置文件适用于处理来自会话的传入语句:
-
防火墙会忽略不活动的配置文件(模式为
OFF的配置文件)。 -
会话账户与包含具有相同用户和主机的成员的每个活动组配置文件匹配。可能会有多个这样的组配置文件。
-
会话账户与具有相同用户和主机的活动账户配置文件匹配,如果有的话。最多只有一个这样的账户配置文件。
换句话说,会话账户可以匹配 0 或多个活动组配置文件,以及 0 或 1 个活动账户配置文件。这意味着对于给定会话,防火墙可以适用 0、1 或多个防火墙配置文件,防火墙将处理每个传入语句如下:
-
如果没有适用的配置文件,防火墙不会施加任何限制并接受该语句。
-
如果有适用的配置文件,它们的模式决定语句处理方式:
-
防火墙将语句记录在每个处于
RECORDING模式的适用配置文件的允许列表中。 -
对于每个处于
DETECTING模式的适用配置文件,如果语句可疑(不匹配配置文件允许列表),防火墙将将语句写入错误日志。 -
如果至少有一个适用配置文件处于
RECORDING或DETECTING模式(这些模式接受所有���句),或者如果语句与至少一个处于PROTECTING模式的适用配置文件的允许列表匹配,则防火墙将接受该语句。否则,防火墙将拒绝该语句(如果启用了mysql_firewall_trace系统变量,则将其写入错误日志)。
-
将这个描述记在心中,接下来的部分将回到单个组配置文件或单个账户配置文件适用的简单情况,并介绍如何设置每种类型的配置文件。
注册防火墙组配置文件
MySQL Enterprise Firewall 支持从 MySQL 8.0.23 开始注册组配置文件。组配置文件可以有多个账户作为其成员。要使用防火墙组配置文件来保护 MySQL 免受来自特定账户的传入语句的影响,请按照以下步骤操作:
-
注册组配置文件并将其置于
RECORDING模式。 -
将成员账户添加到组配置文件中。
-
使用成员账户连接到 MySQL 服务器并执行要学习的语句。这将训练组配置文件并建立形成配置文件允许列表的规则。
-
将其他要作为组成员的账户添加到组配置文件中。
-
将组配置文件切换到
PROTECTING模式。当客户端使用组配置文件的任何成员帐户连接到服务器时,配置文件允许列表会限制语句执行。 -
如果需要额外的培训,请将组配置文件再次切换到
RECORDING模式,使用新的语句模式更新其允许列表,然后将其切换回PROTECTING模式。
防火墙相关帐户引用的准则如下:
-
注意帐户引用出现的上下文。为防火墙操作命名帐户时,请将其指定为单引号字符串(
'*user_name*@*host_name*')。这与通常的 MySQL 语句约定不同,例如CREATE USER和GRANT,其中您分别引用帐户名称的用户和主机部分('*user_name*'@'*host_name*')。为防火墙操作命名帐户的要求意味着您不能使用用户名称中嵌入
@字符的帐户。 -
防火墙根据服务器验证的实际用户和主机名称来评估语句。在配置文件中注册帐户时,请勿使用通配符字符或网络掩码:
-
假设存在一个名为
me@%.example.org的帐户,并且客户端使用它从主机abc.example.org连接到服务器。 -
帐户名称包含
%通配符字符,但服务器将客户端验证为具有用户名me和主机名abc.example.com,这就是防火墙看到的内容。 -
因此,用于防火墙操作的帐户名称是
me@abc.example.org而不是me@%.example.org。
-
以下过程显示了如何向防火墙注册组配置文件,训练防火墙了解该配置文件的可接受语句(其允许列表),使用配置文件保护 MySQL 免受不可接受语句执行,并添加和删除组成员。示例使用fwgrp作为组配置文件名称。假定示例配置文件用于访问sakila数据库中的表的应用程序的客户端(可在dev.mysql.com/doc/index-other.html找到)。
使用管理 MySQL 帐户执行此过程中的步骤,除了由防火墙组配置文件的成员帐户执行的步骤。对于由成员帐户执行的语句,默认数据库应为sakila。(您可以通过相应调整指令来使用不同的数据库。)
-
如有必要,请创建要成为
fwgrp组配置文件成员的帐户,并授予它们适当的访问权限。这里显示了一个成员的语句(选择适当的密码):CREATE USER 'member1'@'localhost' IDENTIFIED BY '*password*'; GRANT ALL ON sakila.* TO 'member1'@'localhost'; -
使用
sp_set_firewall_group_mode()存储过程向防火墙注册组配置文件,并将配置文件置于RECORDING(培训)模式:CALL mysql.sp_set_firewall_group_mode('fwgrp', 'RECORDING'); -
使用
sp_firewall_group_enlist()存储过程添加一个初始成员帐户,用于训练组配置文件的允许列表:CALL mysql.sp_firewall_group_enlist('fwgrp', 'member1@localhost'); -
使用初始成员帐户训练组配置文件,从服务器主机连接到服务器,以便防火墙看到
member1@localhost的会话帐户。然后执行一些语句,以便被视为配置文件的合法内容。例如:SELECT title, release_year FROM film WHERE film_id = 1; UPDATE actor SET last_update = NOW() WHERE actor_id = 1; SELECT store_id, COUNT(*) FROM inventory GROUP BY store_id;防火墙接收来自
member1@localhost帐户的语句。因为该帐户是fwgrp配置文件的成员,该配置文件处于RECORDING模式,防火墙将语句解释为适用于fwgrp并将语句的规范化摘要形式记录为fwgrp允许列表中的规则。然后,这些规则适用于所有是fwgrp成员的帐户。注意
直到
fwgrp组配置文件以RECORDING模式接收语句,其允许列表为空,相当于“拒绝所有”。没有语句可以匹配空的允许列表,这带来以下影响:-
组配置文件无法切换到
PROTECTING模式。它会拒绝每个语句,有效地禁止组成员执行任何语句。 -
组配置文件可以切换到
DETECTING模式。在这种情况下,配置文件接受每个语句,但将其记录为可疑。
-
-
此时,组配置文件信息已缓存,包括其名称、成员资格和允许列表。要查看此信息,请查询性能模式防火墙表:
mysql> SELECT MODE FROM performance_schema.firewall_groups WHERE NAME = 'fwgrp'; +-----------+ | MODE | +-----------+ | RECORDING | +-----------+ mysql> SELECT * FROM performance_schema.firewall_membership WHERE GROUP_ID = 'fwgrp' ORDER BY MEMBER_ID; +----------+-------------------+ | GROUP_ID | MEMBER_ID | +----------+-------------------+ | fwgrp | member1@localhost | +----------+-------------------+ mysql> SELECT RULE FROM performance_schema.firewall_group_allowlist WHERE NAME = 'fwgrp'; +----------------------------------------------------------------------+ | RULE | +----------------------------------------------------------------------+ | SELECT @@`version_comment` LIMIT ? | | UPDATE `actor` SET `last_update` = NOW ( ) WHERE `actor_id` = ? | | SELECT `title` , `release_year` FROM `film` WHERE `film_id` = ? | | SELECT `store_id` , COUNT ( * ) FROM `inventory` GROUP BY `store_id` | +----------------------------------------------------------------------+注意
@@version_comment规则来自连接到服务器时由mysql客户端自动发送的语句。重要
根据应用程序使用情况训练防火墙。例如,为了确定服务器特性和功能,给定的 MySQL 连接器可能会在每个会话开始时向服务器发送语句。如果应用程序通常通过该连接器使用,也要使用该连接器训练防火墙。这使得这些初始语句成为与应用程序关联的组配置文件的允许列表的一部分。
-
再次调用
sp_set_firewall_group_mode()将组配置文件切换到PROTECTING模式:CALL mysql.sp_set_firewall_group_mode('fwgrp', 'PROTECTING');重要
将组配置文件从
RECORDING模式切换出来,将其缓存数据同步到提供持久底层存储的mysql系统数据库表中。如果不为正在记录的配置文件切换模式,则缓存数据不会写入持久存储,并且在服务器重新启动时将丢失。 -
将应该成为成员的任何其他帐户添加到组配置文件中:
CALL mysql.sp_firewall_group_enlist('fwgrp', 'member2@localhost'); CALL mysql.sp_firewall_group_enlist('fwgrp', 'member3@localhost'); CALL mysql.sp_firewall_group_enlist('fwgrp', 'member4@localhost');使用
member1@localhost帐户训练的配置文件允许列表现在也适用于其他帐户。 -
要验证更新后的组成员资格,请再次查询
firewall_membership表:mysql> SELECT * FROM performance_schema.firewall_membership WHERE GROUP_ID = 'fwgrp' ORDER BY MEMBER_ID; +----------+-------------------+ | GROUP_ID | MEMBER_ID | +----------+-------------------+ | fwgrp | member1@localhost | | fwgrp | member2@localhost | | fwgrp | member3@localhost | | fwgrp | member4@localhost | +----------+-------------------+ -
使用组中的任何帐户执行一些可接受和不可接受的语句来测试防火墙的组配置文件。防火墙将每个帐户的语句与配置文件的允许列表进行匹配并接受或拒绝:
-
此语句与训练语句不完全相同,但产生的规范化语句与其中一个相同,因此防火墙接受它:
mysql> SELECT title, release_year FROM film WHERE film_id = 98; +-------------------+--------------+ | title | release_year | +-------------------+--------------+ | BRIGHT ENCOUNTERS | 2006 | +-------------------+--------------+ -
这些语句在允许列表中找不到匹配项,因此防火墙会拒绝每个语句并显示错误:
mysql> SELECT title, release_year FROM film WHERE film_id = 98 OR TRUE; ERROR 1045 (28000): Statement was blocked by Firewall mysql> SHOW TABLES LIKE 'customer%'; ERROR 1045 (28000): Statement was blocked by Firewall mysql> TRUNCATE TABLE mysql.slow_log; ERROR 1045 (28000): Statement was blocked by Firewall -
如果启用了
mysql_firewall_trace系统变量,则防火墙还会将被拒绝的语句写入错误日志。例如:[Note] Plugin MYSQL_FIREWALL reported: 'ACCESS DENIED for 'member1@localhost'. Reason: No match in allowlist. Statement: TRUNCATE TABLE `mysql` . `slow_log`'这些日志消息可能有助于识别攻击源,如果有必要的话。
-
-
如果需要从组配置文件中移除成员,请使用
sp_firewall_group_delist()存储过程,而不是sp_firewall_group_enlist():CALL mysql.sp_firewall_group_delist('fwgrp', 'member3@localhost');
防火墙组配置文件现在已经为成员帐户进行了训练。当客户端使用组中的任何帐户连接并尝试执行语句时,配置文件将保护 MySQL 免受未在允许列表中匹配的语句的影响。
刚刚展示的过程在训练允许列表之前仅向组配置文件添加了一个成员。这样做可以通过限制哪些帐户可以向允许列表添加新的可接受语句,从而更好地控制训练期间。如果需要进行额外培训,可以将配置文件切换回RECORDING模式:
CALL mysql.sp_set_firewall_group_mode('fwgrp', 'RECORDING');
然而,这使得组中的任何成员都可以执行语句并将其添加到允许列表中。为了将额外培训限制在单个组成员身上,请调用sp_set_firewall_group_mode_and_user(),它类似于sp_set_firewall_group_mode(),但多接受一个参数,指定哪个帐户被允许以RECORDING模式训练配置文件。例如,要仅允许member4@localhost进行训练,请执行以下操作:
CALL mysql.sp_set_firewall_group_mode_and_user('fwgrp', 'RECORDING', 'member4@localhost');
这使得指定帐户可以进行额外培训,而无需移除其他组成员。他们可以执行语句,但这些语句不会添加到允许列表中。(但请记住,在RECORDING模式下,其他成员可以执行任何语句。)
注意
为了避免指定特定帐户作为组配置文件的训练帐户时出现意外行为,始终确保该帐户是组的成员。
完成额外培训后,将组配置文件设置回PROTECTING模式:
CALL mysql.sp_set_firewall_group_mode('fwgrp', 'PROTECTING');
由sp_set_firewall_group_mode_and_user()建立的训练帐户保存在组配置文件中,因此防火墙会在以后需要更多培训时记住它。因此,如果调用sp_set_firewall_group_mode()(不接受训练帐户参数),则当前配置文件训练帐户member4@localhost保持不变。
如果确实希望启用所有组成员在RECORDING模式下执行训练,则清除训练账户,调用sp_set_firewall_group_mode_and_user()并为账户参数传递NULL值:
CALL mysql.sp_set_firewall_group_mode_and_user('fwgrp', 'RECORDING', NULL);
可以通过将不匹配的语句记录为可疑来检测入侵,而不拒绝访问。首先,将组配置文件设置为DETECTING模式:
CALL mysql.sp_set_firewall_group_mode('fwgrp', 'DETECTING');
然后,使用成员账户执行一个不匹配组配置文件允许列表的语句。在DETECTING模式下,防火墙允许执行不匹配的语句:
mysql> SHOW TABLES LIKE 'customer%';
+------------------------------+
| Tables_in_sakila (customer%) |
+------------------------------+
| customer |
| customer_list |
+------------------------------+
此外,防火墙会将消息写入错误日志:
[Note] Plugin MYSQL_FIREWALL reported:
'SUSPICIOUS STATEMENT from 'member1@localhost'. Reason: No match in allowlist.
Statement: SHOW TABLES LIKE ?'
要禁用组配置文件,请将其模式更改为OFF:
CALL mysql.sp_set_firewall_group_mode(*group*, 'OFF');
要忘记配置文件的所有训练并禁用它,请重置它:
CALL mysql.sp_set_firewall_group_mode(*group*, 'RESET');
重置操作会导致防火墙删除配置文件的所有规则并将其模式设置为OFF。
注册防火墙账户配置文件
MySQL 企业防火墙允许注册与个人账户对应的配置文件。要使用防火墙账户配置文件保护 MySQL 免受来自特定账户的传入语句的影响,请按照以下步骤操作:
-
注册账户配置文件并将其设置为
RECORDING模式。 -
使用账户连接到 MySQL 服务器并执行要学习的语句。这将训练账户配置文件并建立形成配置文件允许列表的规则。
-
将账户配置文件切换到
PROTECTING模式。当客户端使用该账户连接到服务器时,账户配置文件允许列表将限制语句执行。 -
如果需要额外的训练,请再次将账户配置文件切换到
RECORDING模式,使用新的语句模式更新其允许列表,然后将其切换回PROTECTING模式。
遵循以下与防火墙相关的账户引用指南:
-
注意账户引用出现的上下文。要为防火墙操作命名一个账户,请将其指定为单引号字符串(
'*user_name*@*host_name*')。这与通常的 MySQL 语句约定不同,例如CREATE USER和GRANT,其中您分别引用账户名称的用户和主机部分('*user_name*'@'*host_name*')。为防火墙操作命名账户时,要求将账户命名为单引号字符串意味着您不能使用用户名称中嵌入
@字符的账户。 -
防火墙根据服务器验证的实际用户和主机名称对语句进行评估。在配置文件中注册账户时,不要使���通配符字符或网络掩码:
-
假设存在一个名为
me@%.example.org的账户,并且客户端使用它从主机abc.example.org连接到服务器。 -
账户名称包含
%通配符字符,但服务器将客户端验证为具有用户名me和主机名abc.example.com,这就是防火墙看到的内容。 -
因此,用于防火墙操作的账户名称是
me@abc.example.org而不是me@%.example.org。
-
以下过程展示了如何向防火墙注册账户配置文件,训练防火墙了解该配置文件的可接受语句(其允许列表),并使用配置文件保护 MySQL 免受账户执行不可接受语句的影响。假定示例账户fwuser@localhost用于由访问sakila数据库中的表的应用程序(可在dev.mysql.com/doc/index-other.html找到)。
使用管理 MySQL 账户执行此过程中的步骤,除了那些指定由与防火墙注册的账户配置文件对应的fwuser@localhost账户执行的步骤。对于使用此账户执行的语句,默认数据库应为sakila。(您可以通过相应调整指令来使用不同的数据库。)
-
如有必要,创建用于执行语句的账户(选择适当的密码)并为
sakila数据库授予权限:CREATE USER 'fwuser'@'localhost' IDENTIFIED BY '*password*'; GRANT ALL ON sakila.* TO 'fwuser'@'localhost'; -
使用
sp_set_firewall_mode()存储过程向防火墙注册账户配置文件并将配置文件置于RECORDING(训练)模式:CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING'); -
要训练已注册的账户配置文件,请从服务器主机作为
fwuser连接到服务器,以便防火墙看到fwuser@localhost的会话账户。然后使用该账户执行一些被视为配置文件合法的语句。例如:SELECT first_name, last_name FROM customer WHERE customer_id = 1; UPDATE rental SET return_date = NOW() WHERE rental_id = 1; SELECT get_customer_balance(1, NOW());因为配置文件处于
RECORDING模式,防火墙将语句的规范化摘要形式记录为配置文件允许列表中的规则。注意
直到
fwuser@localhost账户配置文件在RECORDING模式下接收语句,其允许列表为空,相当于“拒绝所有”。空的允许列表无法匹配任何语句,这带来以下影响:-
账户配置文件无法切换到
PROTECTING模式。它会拒绝每个语句,有效地禁止账户执行任何语句。 -
账户配置文件可以切换到
DETECTING模式。在这种情况下,配置文件接受每个语句但将其记录为可疑。
-
-
此时,账户配置文件信息已被缓存。要查看此信息,请查询
INFORMATION_SCHEMA防火墙表:mysql> SELECT MODE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS WHERE USERHOST = 'fwuser@localhost'; +-----------+ | MODE | +-----------+ | RECORDING | +-----------+ mysql> SELECT RULE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST WHERE USERHOST = 'fwuser@localhost'; +----------------------------------------------------------------------------+ | RULE | +----------------------------------------------------------------------------+ | SELECT `first_name` , `last_name` FROM `customer` WHERE `customer_id` = ? | | SELECT `get_customer_balance` ( ? , NOW ( ) ) | | UPDATE `rental` SET `return_date` = NOW ( ) WHERE `rental_id` = ? | | SELECT @@`version_comment` LIMIT ? | +----------------------------------------------------------------------------+注意
@@version_comment规则来自连接到服务器时由mysql客户端自动发送的语句。重要
根据应用程序使用情况训练防火墙。例如,为了确定服务器特性和功能,给定的 MySQL 连接器可能会在每个会话开始时向服务器发送语句。如果一个应用程序通常通过该连接器使用,也要使用该连接器来训练防火墙。这样可以使这些初始语句成为与应用程序关联的账户配置的白名单的一部分。
-
再次调用
sp_set_firewall_mode(),这次将账户配置切换到PROTECTING模式:CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING');重要提示
将账户配置从
RECORDING模式切换出来会将其缓存数据同步到提供持久底层存储的mysql系统数据库表中。如果不切换正在记录的配置的模式,则缓存数据不会写入持久存储,并且在服务器重新启动时会丢失。 -
通过使用账户执行一些可接受和不可接受的语句来测试账户配置。防火墙会将来自账户的每个语句与配置白名单进行匹配并接受或拒绝它:
-
该语句与训练语句不完全相同,但产生的规范化语句与其中一个相同,因此防火墙接受它:
mysql> SELECT first_name, last_name FROM customer WHERE customer_id = '48'; +------------+-----------+ | first_name | last_name | +------------+-----------+ | ANN | EVANS | +------------+-----------+ -
这些语句在白名单中找不到匹配项,因此防火墙会拒绝每个语句并显示错误:
mysql> SELECT first_name, last_name FROM customer WHERE customer_id = 1 OR TRUE; ERROR 1045 (28000): Statement was blocked by Firewall mysql> SHOW TABLES LIKE 'customer%'; ERROR 1045 (28000): Statement was blocked by Firewall mysql> TRUNCATE TABLE mysql.slow_log; ERROR 1045 (28000): Statement was blocked by Firewall -
如果启用了
mysql_firewall_trace系统变量,防火墙还会将被拒绝的语句写入错误日志。例如:[Note] Plugin MYSQL_FIREWALL reported: 'ACCESS DENIED for fwuser@localhost. Reason: No match in allowlist. Statement: TRUNCATE TABLE `mysql` . `slow_log`'这些日志消息可能有助于识别攻击源,如果有必要的话。
-
防火墙账户配置现在已经针对fwuser@localhost账户进行了训练。当客户端使用该账户连接并尝试执行语句时,该配置会保护 MySQL 免受未被配置白名单匹配的语句的影响。
可以通过将不匹配的语句记录为可疑来检测入侵,而不拒绝访问。首先,将账户配置置于DETECTING模式:
CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'DETECTING');
然后,使用该账户执行一个不匹配账户配置白名单的语句。在DETECTING模式下,防火墙允许执行不匹配的语句:
mysql> SHOW TABLES LIKE 'customer%';
+------------------------------+
| Tables_in_sakila (customer%) |
+------------------------------+
| customer |
| customer_list |
+------------------------------+
此外,防火墙会将一条消息写入错误日志:
[Note] Plugin MYSQL_FIREWALL reported:
'SUSPICIOUS STATEMENT from 'fwuser@localhost'. Reason: No match in allowlist.
Statement: SHOW TABLES LIKE ?'
要禁用账户配置,请将其模式更改为OFF:
CALL mysql.sp_set_firewall_mode(*user*, 'OFF');
要忘记配置的所有训练并禁用它,请重置它:
CALL mysql.sp_set_firewall_mode(*user*, 'RESET');
重置操作会导致防火墙删除配置的所有规则并将其模式设置为OFF。
监控防火墙
要评估防火墙的活动,请检查其状态变量。例如,在执行早期显示的过程来训练和保护fwgrp组配置后,变量如下所示:
mysql> SHOW GLOBAL STATUS LIKE 'Firewall%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Firewall_access_denied | 3 |
| Firewall_access_granted | 4 |
| Firewall_access_suspicious | 1 |
| Firewall_cached_entries | 4 |
+----------------------------+-------+
变量分别表示被拒绝的语句数、被接受的语句数、被记录为可疑的语句数以及被添加到缓存中的语句数。Firewall_access_granted计数为 4,因为通过注册账户连接时,mysql客户端发送了@@version_comment语句,每次连接都发送了三次,再加上未在DETECTING模式下被阻止的SHOW TABLES语句。
将账户配置文件迁移到组配置文件
在 MySQL 8.0.23 之前,MySQL 企业防火墙仅支持每个应用于单个账户的账户配置文件。从 MySQL 8.0.23 开始,防火墙还支持每个可以应用于多个账户的组配置文件。当需要将相同的允许列表应用于多个账户时,组配置文件能够更轻松地进行管理:不需要为每个账户创建一个账户配置文件并在所有这些配置文件中复制允许列表,只需创建一个组配置文件并将账户作为其成员。然后该组允许列表将应用于所有账户。
一个只有一个成员账户的组配置文件在逻辑上等同于该账户的账户配置文件,因此可以完全使用组配置文件来管理防火墙,而不是混合使用账户和组配置文件。对于新的防火墙安装,通过统一创建新的组配置文件而避免账户配置文件,可以实现这一点。
由于组配置文件提供了更大的灵活性,建议所有新的防火墙配置文件都以组配置文件的形式创建。从 MySQL 8.0.26 开始,账户配置文件已被弃用,并可能在未来的 MySQL 版本中被移除。对于已包含账户配置文件的防火墙安装升级,MySQL 8.0.26 及更高版本的 MySQL 企业防火墙包含一个名为sp_migrate_firewall_user_to_group()的存储过程,帮助您将账户配置文件转换为组配置文件。要使用它,请按照具有FIREWALL_ADMIN权限的用户执行以下过程:
-
运行
firewall_profile_migration.sql脚本来安装sp_migrate_firewall_user_to_group()存储过程。该脚本位于您的 MySQL 安装的share目录中。$> mysql -u root -p < firewall_profile_migration.sql Enter password: *(enter root password here)* -
通过查询信息模式
MYSQL_FIREWALL_USERS表来识别存在哪些账户配置文件。例如:mysql> SELECT USERHOST FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS; +-------------------------------+ | USERHOST | +-------------------------------+ | admin@localhost | | local_client@localhost | | remote_client@abc.example.com | +-------------------------------+ -
对于上一步骤识别出的每个账户配置文件,将其转换为一个组配置文件:
CALL mysql.sp_migrate_firewall_user_to_group('admin@localhost', 'admins'); CALL mysql.sp_migrate_firewall_user_to_group('local_client@localhost', 'local_clients'); CALL mysql.sp_migrate_firewall_user_to_group('remote_client@localhost', 'remote_clients');在每种情况下,账户配置文件必须存在且不能处于
RECORDING模式,并且群组配置文件不能已经存在。生成的群组配置文件以命名的账户作为其唯一的成员,并且也被设置为群组培训账户。群组配置文件的操作模式取自账户配置文件的操作模式。 -
(可选)移除
sp_migrate_firewall_user_to_group():DROP PROCEDURE IF EXISTS mysql.sp_migrate_firewall_user_to_group;
有关sp_migrate_firewall_user_to_group()的更多详细信息,请参见防火墙杂项存储过程。