6.4.5.8 编写审核日志过滤器定义
过滤器定义是JSON个值。有关在 MySQL 中使用JSON数据的信息,请参见第 11.5 节“ JSON 数据类型”。
过滤器定义具有以下形式,其中* actions
*table 示过滤的方式:
{ "filter": actions }
以下讨论描述了过滤器定义中允许的构造。
记录所有事件
要显式启用或禁用所有事件的日志记录,请在过滤器中使用log
元素:
{
"filter": { "log": true }
}
log
的值可以是true
或false
。
前面的过滤器允许记录所有事件。它等效于:
{
"filter": { }
}
记录行为取决于log
值以及是否指定了class
或event
项:
-
指定
log
时,将使用其给定值。 -
如果未指定
log
,则如果未指定class
或event
项,则日志记录为true
,否则为false
(在这种情况下class
或event
可以包括自己的log
项)。
记录特定的事件类
要记录特定类的事件,请在过滤器中使用class
元素,其name
字段 table 示要记录的类的名称:
{
"filter": {
"class": { "name": "connection" }
}
}
name
的值可以是connection
,general
或table_access
来分别记录连接事件,常规事件或 table 访问事件。
通过前面的过滤器,可以记录connection
类中的事件。它等效于以下带有明确显示的log
项的过滤器:
{
"filter": {
"log": false,
"class": { "log": true,
"name": "connection" }
}
}
要启用多个类的日志记录,请将class
值定义为命名这些类的JSON数组元素:
{
"filter": {
"class": [
{ "name": "connection" },
{ "name": "general" },
{ "name": "table_access" }
]
}
}
Note
当给定项目的多个实例出现在过滤器定义中的同一级别时,可以将项目值组合到数组值内该项目的单个实例中。前面的定义可以这样写:
{
"filter": {
"class": [
{ "name": [ "connection", "general", "table_access" ] }
]
}
}
记录特定事件子类
若要选择特定的事件子类,请使用event
项,其中name
项为子类命名。 event
项选择的事件的默认操作是记录它们。例如,此过滤器允许记录命名事件子类:
{
"filter": {
"class": [
{
"name": "connection",
"event": [
{ "name": "connect" },
{ "name": "disconnect" }
]
},
{ "name": "general" },
{
"name": "table_access",
"event": [
{ "name": "insert" },
{ "name": "delete" },
{ "name": "update" }
]
}
]
}
}
event
项还可以包含明确的log
项,以指示是否记录合格事件。 event
项选择多个事件并明确指示它们的日志记录行为:
"event": [
{ "name": "read", "log": false },
{ "name": "insert", "log": true },
{ "name": "delete", "log": true },
{ "name": "update", "log": true }
]
从 MySQL 5.7.20 开始,如果event
项包含abort
项,它也可以指示是否阻止合格事件。有关详细信息,请参见阻止特定事件的执行。
table6.26,“事件类和子类组合”描述了每个事件类的允许子类值。
table6.26 事件类和子类组合
Event Class | Event Subclass | Description |
---|---|---|
connection | connect | 连接启动(成功或失败) |
connection | change_user | 会话期间使用不同的用户/密码进行用户重新认证 |
connection | disconnect | Connection termination |
general | status | 一般操作信息 |
table_access | read | table 读取语句,例如SELECT或插入...选择 |
table_access | delete | table 删除语句,例如DELETE或TRUNCATE TABLE |
table_access | insert | table 插入语句,例如INSERT或REPLACE |
table_access | update | table 更新语句,例如UPDATE |
table6.27,“每个事件类和子类组合的日志和异常特性”描述每个事件子类是否可以记录或中止。
table6.27 每个事件类和子类组合的日志和异常特性
Event Class | Event Subclass | 可以记录 | 可以中止 |
---|---|---|---|
connection | connect | Yes | No |
connection | change_user | Yes | No |
connection | disconnect | Yes | No |
general | status | Yes | No |
table_access | read | Yes | Yes |
table_access | delete | Yes | Yes |
table_access | insert | Yes | Yes |
table_access | update | Yes | Yes |
独占记录
可以以包含或排除模式定义过滤器:
-
包含模式仅记录明确指定的项目。
-
独占模式记录除明确指定的项目以外的所有内容。
要执行包含性日志记录,请全局禁用日志记录并启用特定类的日志记录。此过滤器记录connection
类中的connect
和disconnect
事件,以及general
类中的事件:
{
"filter": {
"log": false,
"class": [
{
"name": "connection",
"event": [
{ "name": "connect", "log": true },
{ "name": "disconnect", "log": true }
]
},
{ "name": "general", "log": true }
]
}
}
要执行独占日志记录,请全局启用日志记录,并禁用特定类的日志记录。此过滤器记录除general
类中的事件以外的所有内容:
{
"filter": {
"log": true,
"class":
{ "name": "general", "log": false }
}
}
此过滤器通过* not *记录其他所有内容,从而记录connection
类中的change_user
事件和table_access
事件:
{
"filter": {
"log": true,
"class": [
{
"name": "connection",
"event": [
{ "name": "connect", "log": false },
{ "name": "disconnect", "log": false }
]
},
{ "name": "general", "log": false }
]
}
}
测试事件字段值
要启用基于特定事件字段值的日志记录,请在log
项中指定一个field
项,以指示字段名称及其期望值:
{
"filter": {
"class": {
"name": "general",
"event": {
"name": "status",
"log": {
"field": { "name": "general_command.str", "value": "Query" }
}
}
}
}
}
每个事件都包含特定于事件类的字段,可以从过滤器内部访问这些字段以执行自定义过滤。
连接事件指示会话期间何时发生与连接有关的活动,例如用户连接到服务器或从服务器断开连接。 table6.28,“连接事件字段”table 示连接事件的允许字段。
table6.28 连接事件字段
Field Name | Field Type | Description |
---|---|---|
status | integer | Event status: |
0: OK Otherwise: Failed | ||
connection_id | 无符号整数 | 连接 ID |
user.str | 字符串 | 认证期间指定的用户名 |
user.length | 无符号整数 | 用户名长度 |
priv_user.str | 字符串 | 授权的用户名(帐户用户名) |
priv_user.length | 无符号整数 | 授权的用户名长度 |
external_user.str | string | 外部用户名(由第三方身份验证插件提供) |
external_user.length | 无符号整数 | 外部用户名长度 |
proxy_user.str | 字符串 | 代理用户名 |
proxy_user.length | 无符号整数 | 代理用户名长度 |
host.str | 字符串 | 连接的用户主机 |
host.length | 无符号整数 | 连接的用户主机长度 |
ip.str | 字符串 | 连接的用户 IP 地址 |
ip.length | 无符号整数 | 连接的用户 IP 地址长度 |
database.str | 字符串 | 在连接时指定的数据库名称 |
database.length | 无符号整数 | 数据库名称长度 |
connection_type | 整数 | 连接类型: 或 "::undefined" :未定义或 "::tcp/ip" :TCP/IP或 "::socket" :套接字或 "::named_pipe" :命名管道或 "::ssl" :具有加密功能的 TCP/IP或 "::shared_memory" :共享内存 |
"::xxx"
值是符号伪常量,可以代替 Literals 数字值来给出。它们必须用字符串引号并且区分大小写。
常规事件指示操作的状态码及其详细信息。 table6.29,“常规事件字段”table 示一般事件的允许字段。
table6.29 常规事件字段
Field Name | Field Type | Description |
---|---|---|
general_error_code | integer | Event status: |
0: OK Otherwise: Failed | ||
general_thread_id | 无符号整数 | 连接/线程 ID |
general_user.str | 字符串 | 认证期间指定的用户名 |
general_user.length | 无符号整数 | 用户名长度 |
general_command.str | 字符串 | 命令名称 |
general_command.length | 无符号整数 | 命令名称长度 |
general_query.str | 字符串 | SQL 语句文本 |
general_query.length | 无符号整数 | SQL 语句文本长度 |
general_host.str | 字符串 | 主机名 |
general_host.length | 无符号整数 | 主机名长度 |
general_sql_command.str | 字符串 | SQL 命令类型名称 |
general_sql_command.length | 无符号整数 | SQL 命令类型名称长度 |
general_external_user.str | string | 外部用户名(由第三方身份验证插件提供) |
general_external_user.length | 无符号整数 | 外部用户名长度 |
general_ip.str | 字符串 | 连接的用户 IP 地址 |
general_ip.length | 无符号整数 | 连接用户 IP 地址长度 |
general_command.str
table 示命令名称:Query
,Execute
,Quit
或Change user
。
general_command.str
字段设置为Query
或Execute
的一般事件包含general_sql_command.str
设置为一个值,该值指定 SQL 命令的类型:alter_db
,alter_db_upgrade
,admin_commands
等。这些值可以视为此语句显示的性能模式工具的最后一个组件:
mysql> SELECT NAME FROM performance_schema.setup_instruments
WHERE NAME LIKE 'statement/sql/%' ORDER BY NAME;
+---------------------------------------+
| NAME |
+---------------------------------------+
| statement/sql/alter_db |
| statement/sql/alter_db_upgrade |
| statement/sql/alter_event |
| statement/sql/alter_function |
| statement/sql/alter_instance |
| statement/sql/alter_procedure |
| statement/sql/alter_server |
...
table 访问事件提供有关特定 table 访问的信息。 table6.30,“table 访问事件字段”table 示 table 访问事件的允许字段。
table6.30table 访问事件字段
Field Name | Field Type | Description |
---|---|---|
connection_id | unsigned integer | 事件连接 ID |
sql_command_id | integer | SQL 命令 ID |
query.str | string | SQL 语句文本 |
query.length | unsigned integer | SQL 语句文本长度 |
table_database.str | string | 与事件关联的数据库名称 |
table_database.length | unsigned integer | 数据库名称长度 |
table_name.str | string | 与事件关联的 table 名 |
table_name.length | unsigned integer | table 名长度 |
以下列 table 显示哪些语句产生哪些 table 访问事件:
-
read
事件: -
SELECT
-
INSERT ... SELECT
(用于SELECT
子句中引用的 table) -
REPLACE ... SELECT
(用于SELECT
子句中引用的 table) -
UPDATE ... WHERE
(用于WHERE
子句中引用的 table) -
HANDLER ... READ
-
-
delete
事件: -
DELETE
TRUNCATE TABLE
-
insert
事件: -
INSERT
-
INSERT ... SELECT
(用于INSERT
子句中引用的 table) -
REPLACE
-
REPLACE ... SELECT
(用于REPLACE
子句中引用的 table -
LOAD DATA
-
LOAD XML
-
-
update
事件: -
UPDATE
UPDATE ... WHERE
(用于UPDATE
子句中引用的 table)
阻止执行特定事件
从 MySQL 5.7.20 开始,event
项可以包含abort
项,指示是否防止执行限定事件。例如,abort
允许编写阻止特定 SQL 语句执行的规则。
abort
项必须出现在event
项中。例如:
"event": {
"name": qualifying event subclass names
"abort": condition
}
对于name
项选择的事件子类,abort
动作是 true 还是 false,取决于* condition
*评估。如果条件评估为真,则事件被阻止。否则,事件将 continue 执行。
condition
*规范可以像true
或false
一样简单,也可以更复杂,以便评估取决于事件 Feature。
{
"filter": {
"class": {
"name": "table_access",
"event": {
"name": [ "insert", "update", "delete" ],
"abort": true
}
}
}
}
这个更复杂的过滤器将阻止相同的语句,但仅针对特定的 table(finances.bank_account
):
{
"filter": {
"class": {
"name": "table_access",
"event": {
"name": [ "insert", "update", "delete" ],
"abort": {
"and": [
{ "field": { "name": "table_database.str", "value": "finances" } },
{ "field": { "name": "table_name.str", "value": "bank_account" } }
]
}
}
}
}
}
过滤器匹配和阻止的语句向 Client 端返回错误:
ERROR 1045 (28000): Statement was aborted by an audit log filter
并非所有事件都可以被阻止(请参阅table6.27,“每个事件类和子类组合的日志和异常特性”)。对于无法处理的事件,审核日志会将警告写入错误日志,而不是阻止警告。
如果试图定义一个过滤器,其中abort
项出现在event
项之外的其他位置,则会发生错误。
Logical Operators
逻辑运算符(and
,or
,not
)可用于log
个项目。这允许构建更高级的过滤配置:
{
"filter": {
"class": {
"name": "general",
"event": {
"name": "status",
"log": {
"or": [
{
"and": [
{ "field": { "name": "general_command.str", "value": "Query" } },
{ "field": { "name": "general_command.length", "value": 5 } }
]
},
{
"and": [
{ "field": { "name": "general_command.str", "value": "Execute" } },
{ "field": { "name": "general_command.length", "value": 7 } }
]
}
]
}
}
}
}
}
引用 sched 义变量
要在log
条件下引用 sched 义变量,请使用variable
项目,该项目针对给定值测试是否相等:
{
"filter": {
"class": {
"name": "general",
"event": {
"name": "status",
"log": {
"variable": {
"name": "audit_log_connection_policy_value", "value": "::none"
}
}
}
}
}
}
每个 sched 义变量对应于一个系统变量。通过编写用于测试 sched 义变量的过滤器,您可以通过设置相应的系统变量来修改过滤器操作,而不必重新定义过滤器。例如,通过编写测试audit_log_connection_policy_value
sched 义变量的值的过滤器,可以通过更改audit_log_connection_policy系统变量的值来修改过滤器操作。
audit_log_xxx_policy
系统变量用于旧模式审核日志(请参见第 6.4.5.9 节“旧模式审核日志过滤”)。使用基于规则的审核日志过滤时,这些变量保持可见(例如,使用SHOW VARIABLES),但是除非您编写包含引用它们的构造的过滤器,否则对它们的更改将无效。
以下列 table 描述了variable
个项目的允许 sched 义变量:
audit_log_connection_policy_value
此变量对应于audit_log_connection_policy系统变量的值。该值是无符号整数。 table6.31,“ audit_log_connection_policy_value 值”显示允许的值和相应的audit_log_connection_policy值。
table6.31 audit_log_connection_policy_value 的值
Value | 对应的 audit_log_connection_policy 值 |
---|---|
0 或"::none" | NONE |
1 或"::errors" | ERRORS |
2 或"::all" | ALL |
"::xxx"
值是符号伪常量,可以代替 Literals 数字值来给出。它们必须用字符串引号并且区分大小写。
audit_log_policy_value
此变量对应于audit_log_policy系统变量的值。该值是无符号整数。 table6.32,“ audit_log_policy_value 值”显示允许的值和相应的audit_log_policy值。
table6.32 audit_log_policy_value 的值
Value | 对应的 audit_log_policy 值 |
---|---|
0 或"::none" | NONE |
1 或"::logins" | LOGINS |
2 或"::all" | ALL |
3 或"::queries" | QUERIES |
"::xxx"
值是符号伪常量,可以代替 Literals 数字值来给出。它们必须用字符串引号并且区分大小写。
audit_log_statement_policy_value
此变量对应于audit_log_statement_policy系统变量的值。该值是无符号整数。 table6.33,“ audit_log_statement_policy_value 值”显示允许的值和相应的audit_log_statement_policy值。
table6.33 audit_log_statement_policy_value 的值
Value | 对应的 audit_log_statement_policy 值 |
---|---|
0 或"::none" | NONE |
1 或"::errors" | ERRORS |
2 或"::all" | ALL |
"::xxx"
值是符号伪常量,可以代替 Literals 数字值来给出。它们必须用字符串引号并且区分大小写。
引用 sched 义函数
要在log
条件下引用 sched 义函数,请使用function
项,该项采用name
和args
值分别指定函数名称及其参数:
{
"filter": {
"class": {
"name": "general",
"event": {
"name": "status",
"log": {
"function": {
"name": "find_in_include_list",
"args": [ { "string": [ { "field": "user.str" },
{ "string": "@"},
{ "field": "host.str" } ] } ]
}
}
}
}
}
}
name
项中指定的函数只能是函数名称,不能带括号或参数列 table。 args
项中的参数(如果有)必须按功能说明中列出的 Sequences 给出。参数可以引用 sched 义的变量,事件字段或字符串或数字常量。
前面的过滤器根据是否在audit_log_include_accounts系统变量中找到当前用户来确定是否记录general
类status
事件。该用户是使用事件中的字段构造的。
以下列 table 描述了function
个项目允许的 sched 义功能:
audit_log_exclude_accounts_is_null()
检查audit_log_exclude_accounts系统变量是否为NULL
。当定义与旧审计日志实现相对应的过滤器时,此功能可能会很有帮助。
Arguments:
None.
audit_log_include_accounts_is_null()
检查audit_log_include_accounts系统变量是否为NULL
。当定义与旧审计日志实现相对应的过滤器时,此功能可能会很有帮助。
Arguments:
None.
debug_sleep(millisec)
睡眠指定的毫秒数。在性能测量期间使用此功能。
debug_sleep()
仅适用于调试版本。
Arguments:
-
millisec
*:一个无符号整数,指定要睡眠的毫秒数。
-
find_in_exclude_list(account)
检查审核日志排除列 table 中是否存在帐户字符串(audit_log_exclude_accounts系统变量的值)。
Arguments:
-
account
*:指定用户帐户名称的字符串。
-
find_in_include_list(account)
检查审核日志包含列 table(audit_log_include_accounts系统变量的值)中是否存在帐户字符串。
Arguments:
-
account
*:指定用户帐户名称的字符串。
-
string_find(text, substr)
检查substr
值是否包含在text
值中。此搜索区分大小写。
Arguments:
-
text
*:要搜索的文本字符串。
-
substr
:要在text
*中搜索的子字符串。
替换用户过滤器
在某些情况下,可以动态更改过滤器定义。为此,请在现有的filter
中定义filter
配置。例如:
{
"filter": {
"id": "main",
"class": {
"name": "table_access",
"event": {
"name": [ "update", "delete" ],
"log": false,
"filter": {
"class": {
"name": "general",
"event" : { "name": "status",
"filter": { "ref": "main" } }
},
"activate": {
"or": [
{ "field": { "name": "table_name.str", "value": "temp_1" } },
{ "field": { "name": "table_name.str", "value": "temp_2" } }
]
}
}
}
}
}
}
当子过滤器中的activate
元素的值为true
时,将激活一个新的过滤器。不允许在顶级filter
中使用activate
。
通过使用子过滤器中的ref
项来引用原始过滤器id
,可以用原始过滤器替换新的过滤器。
所示过滤器的操作如下:
-
main
过滤器 awaittable_access
事件,即update
或delete
。 -
如果
temp_1
或temp_2
table 上发生了update
或delete
table_access
事件,则将过滤器替换为内部过滤器(没有id
,因为不需要显式引用它)。 -
如果发出命令结束的 signal(
general
/status
事件),则会将一个条目写入审核日志文件,并将该过滤器替换为main
过滤器。
该过滤器对于记录更新或删除temp_1
或temp_2
table 中的内容的语句很有用,例如:
UPDATE temp_1, temp_3 SET temp_1.a=21, temp_3.a=23;
该语句生成多个table_access
事件,但是审核日志文件将仅包含general
/status
条目。
Note
定义中使用的任何id
值仅针对该定义进行评估。它们与audit_log_filter_id系统变量的值无关。