编写审核日志过滤器定义
过滤器定义是JSON值。有关JSON在MySQL中使用数据的信息,请参见“ JSON数据类型”。
过滤器定义具有以下形式,其中 ctions指示了如何进行过滤:
{ "filter": ctions }
以下讨论描述了过滤器定义中允许的构造。
- 记录所有事件
- 记录特定事件类
- 记录特定事件子类
- 包容性日志和独占日志
- 测试事件字段值
- 阻止特定事件的执行
- 逻辑运算符
- 引用预定义变量
- 引用预定义函数
- 更换用户过滤器
记录所有事件
要显式启用或禁用所有事件的日志记录,请log在过滤器中使用一个元素:
{
"filter": { "log": true }
}
该log值可以是true或false。
前面的过滤器可以记录所有事件。它等效于:
{
"filter": { }
}
登录行为取决于log价值,以及是否class或event指定项目:
- 随着log指定,则使用其给定值。
- 如果未log指定,则日志记录为true未指定class或未event指定项目,false否则为日志记录(在这种情况下,class或者event可以包括自己的log项目)。
记录特定事件类
要记录特定类的事件,请class在过滤器中使用一个元素,该元素的name字段表示要记录的类的名称:
{
"filter": {
"class": { "name": "connection" }
}
}
该name值可以是connection,general或table_access分别记录连接事件,常规事件或表访问事件。
前面的过滤器允许记录connection类中的事件。它等效于以下过滤器,其中包含log明确显示的项目:
{
"filter": {
"log": false,
"class": { "log": true,
"name": "connection" }
}
}
要启用多个类的日志记录,请将class值定义为JSON命名类的数组元素:
{
"filter": {
"class": [
{ "name": "connection" },
{ "name": "general" },
{ "name": "table_access" }
]
}
}
注意当给定项目的多个实例出现在过滤器定义中的同一级别时,这些项目值可以合并到该数组值内该项目的单个实例中。前面的定义可以这样写:
{ "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 }
]
如果该event项目包含一个 bort项目,它还可以指示是否阻止资格赛。有关详细信息,请参见阻止特定事件的执行。
表6.29“事件类和子类组合”描述了每个事件类的允许子类值。
表6.29事件类和子类组合
| 活动班 | 事件子类 | 描述 | 
|---|---|---|
| connection | connect | 连接启动(成功或失败) | 
| connection | change_user | 会话期间使用不同的用户/密码进行用户重新认证 | 
| connection | disconnect | 连接终止 | 
| general | status | 一般操作信息 | 
| message | internal | 内部生成的消息 | 
| message | user | 讯息产生者  udit_api_message_emit_udf() | 
| table_access | read | 表读取语句,例如 SELECT或INSERT INTO ... SELECT | 
| table_access | delete | 表删除语句,例如 DELETE或TRUNCATE TABLE | 
| table_access | insert | 表插入语句,例如 INSERT或REPLACE | 
| table_access | update | 表更新语句,例如 UPDATE | 
表6.30“每个事件类和子类组合的日志和异常特性”描述了每个事件子类是否可以记录或中止。
表6.30每个事件类和子类组合的日志和中止特性
| 活动班 | 事件子类 | 可以记录 | 可以中止 | 
|---|---|---|---|
| connection | connect | 是 | 没有 | 
| connection | change_user | 是 | 没有 | 
| connection | disconnect | 是 | 没有 | 
| general | status | 是 | 没有 | 
| message | internal | 是 | 是 | 
| message | user | 是 | 是 | 
| table_access | read | 是 | 是 | 
| table_access | delete | 是 | 是 | 
| table_access | insert | 是 | 是 | 
| table_access | update | 是 | 是 | 
包容性日志和独占日志
可以以包含或排除模式定义过滤器:
- 包含模式仅记录明确指定的项目。
- 独占模式记录除明确指定的项目以外的所有内容。
要执行包含性日志记录,请全局禁用日志记录并启用特定类的日志记录。此过滤器过滤类中的日志connect和disconnect事件,以及connection类中的事件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 }
}
}
此过滤器将change_user事件记录在connection类,message事件和table_access事件中:
{
"filter": {
"log": true,
"class": [
{
"name": "connection",
"event": [
{ "name": "connect", "log": false },
{ "name": "disconnect", "log": false }
]
},
{ "name": "general", "log": false }
]
}
}
测试事件字段值
要基于特定事件字段值启用日志记录,请field在该log项目内指定一个指示字段名称及其期望值的项目:
{
"filter": {
"class": {
"name": "general",
"event": {
"name": "status",
"log": {
"field": { "name": "general_command.str", "value": "Query" }
}
}
}
}
}
每个事件都包含特定于事件类的字段,可以从过滤器内部访问这些字段以执行自定义过滤。
连接事件指示会话期间何时发生与连接有关的活动,例如用户连接到服务器或从服务器断开连接。表6.31“连接事件字段”指示连接事件的允许字段。
表6.31连接事件字段
| 栏位名称 | 栏位类型 | 描述 | 
|---|---|---|
| status | 整数 | 活动状态: 0:好 否则:失败 | 
| connection_id | 无符号整数 | 连接ID | 
| user.str | string | 认证期间指定的用户名 | 
| user.length | 无符号整数 | 用户名长度 | 
| priv_user.str | string | 经过身份验证的用户名(帐户用户名) | 
| priv_user.length | 无符号整数 | 经过身份验证的用户名长度 | 
| external_user.str | string | 外部用户名(由第三方身份验证插件提供) | 
| external_user.length | 无符号整数 | 外部用户名长度 | 
| proxy_user.str | string | 代理用户名 | 
| proxy_user.length | 无符号整数 | 代理用户名长度 | 
| host.str | string | 连接的用户主机 | 
| host.length | 无符号整数 | 连接的用户主机长度 | 
| ip.str | string | 连接的用户IP地址 | 
| ip.length | 无符号整数 | 连接的用户IP地址长度 | 
| database.str | string | 连接时指定的数据库名称 | 
| database.length | 无符号整数 | 数据库名称长度 | 
| connection_type | 整数 | 连接类型: 或 或 或 或 或 或 | 
这些值是符号伪常数,可以代替文字数字值给出。它们必须用字符串引号并且区分大小写。"::xxx"
常规事件指示操作的状态码及其详细信息。表6.32“常规事件字段”指示常规事件的允许字段。
表6.32常规事件字段
| 栏位名称 | 栏位类型 | 描述 | 
|---|---|---|
| general_error_code | 整数 | 活动状态: 0:好 否则:失败 | 
| general_thread_id | 无符号整数 | 连接/线程ID | 
| general_user.str | string | 认证期间指定的用户名 | 
| general_user.length | 无符号整数 | 用户名长度 | 
| general_command.str | string | 指令名称 | 
| general_command.length | 无符号整数 | 命令名称长度 | 
| general_query.str | string | SQL语句文本 | 
| general_query.length | 无符号整数 | SQL语句文本长度 | 
| general_host.str | string | 主机名 | 
| general_host.length | 无符号整数 | 主机名长度 | 
| general_sql_command.str | string | SQL命令类型名称 | 
| general_sql_command.length | 无符号整数 | SQL命令类型名称长度 | 
| general_external_user.str | string | 外部用户名(由第三方身份验证插件提供) | 
| general_external_user.length | 无符号整数 | 外部用户名长度 | 
| general_ip.str | string | 连接的用户IP地址 | 
| general_ip.length | 无符号整数 | 连接用户IP地址长度 | 
general_command.str表示命令名:Query,Execute,Quit,或Change user。
与一般的事件general_command.str字段设置为Query或Execute包含general_sql_command.str设置为一个值,该值指定SQL命令的类型: lter_db, lter_db_upgrade, dmin_commands,等等。这些值可以视为此语句显示的性能模式工具的最后一个组件:
mysql>SELECT NAME FROM performance_schem .setup_instrumentsWHERE 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 | ...
表访问事件提供有关特定表访问的信息。表6.33“表访问事件字段”指示表访问事件的允许字段。
表6.33表访问事件字段
| 栏位名称 | 栏位类型 | 描述 | 
|---|---|---|
| connection_id | 无符号整数 | 事件连接ID | 
| sql_command_id | 整数 | SQL命令ID | 
| query.str | string | SQL语句文本 | 
| query.length | 无符号整数 | SQL语句文本长度 | 
| table_database.str | string | 与事件关联的数据库名称 | 
| table_database.length | 无符号整数 | 数据库名称长度 | 
| table_name.str | string | 与事件关联的表名 | 
| table_name.length | 无符号整数 | 表名长度 | 
以下列表显示哪些语句产生哪些表访问事件:
- read事件:- SELECT
- INSERT ... SELECT(对于在- SELECT条款中引用的表)
- REPLACE ... SELECT(对于在- SELECT条款中引用的表)
- UPDATE ... WHERE(对于在- WHERE条款中引用的表)
- HANDLER ... READ
 
- delete事件:- DELETE
- TRUNCATE TABLE
 
- insert事件:- INSERT
- INSERT ... SELECT(对于在- INSERT条款中引用的表)
- REPLACE
- REPLACE ... SELECT(对于在- REPLACE条款中引用的表
- LOAD DATA
- LOAD XML
 
- update事件:- UPDATE
- UPDATE ... WHERE(对于在- UPDATE条款中引用的表)
 
阻止特定事件的执行
event项目可以包括一个 bort项目,该项目指示是否阻止资格事件的执行。例如, bort启用编写阻止特定SQL语句执行的规则。
该 bort项目必须出现在一个event项目内。例如:
"event": {
"name": qualifying event subclass names
"abort": condition
}
对于name项目选择的事件子类, bort操作是对还是错,取决于condition评估。如果条件评估为true,则事件被阻止。否则,事件将继续执行。
所述condition规范可以是一样简单true或false,或者它可以是更复杂的,使得评价取决于事件特性。
该过滤块INSERT,UPDATE和DELETE语句:
{
"filter": {
"class": {
"name": "table_access",
"event": {
"name": [ "insert", "update", "delete" ],
"abort": true
}
}
}
}
这个更复杂的过滤器会阻止相同的语句,但只针对特定的表(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" } }
]
}
}
}
}
}
过滤器匹配并阻止的语句向客户端返回错误:
ERROR 1045 (28000): Statement was aborted by an audit log filter
并非所有事件都可以被阻止(请参见表6.30,“每个事件类和子类组合的日志和异常特性”)。对于无法处理的事件,审核日志会将警告写入错误日志,而不是阻止警告。
如果试图定义一个使 bort项目出现在event项目以外的地方的过滤器,则会发生错误。
逻辑运算符
逻辑运算符( nd,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 } }
]
}
]
}
}
}
}
}
引用预定义变量
要在log条件中引用预定义变量,请使用一个variable项目,该项目针对给定值测试是否相等:
{
"filter": {
"class": {
"name": "general",
"event": {
"name": "status",
"log": {
"variable": {
"name": "audit_log_connection_policy_value", "value": "::none"
}
}
}
}
}
}
每个预定义变量对应于一个系统变量。通过编写用于测试预定义变量的过滤器,您可以通过设置相应的系统变量来修改过滤器操作,而不必重新定义过滤器。例如,通过编写一个测试 udit_log_connection_policy_value预定义变量值的过滤器,可以通过更改 udit_log_connection_policy系统变量的值来修改过滤器操作。
该系统变量用于遗留模式审计日志(见第6.4.5.8,“传统模式下的审计日志过滤”)。使用基于规则的审核日志过滤时,这些变量保持可见(例如,使用),但是除非您编写包含引用它们的构造的过滤器,否则对它们的更改将无效。 udit_log_xxx_policySHOW VARIABLES
以下列表描述了允许的variable项目预定义变量:
- udit_log_connection_policy_value- 该变量对应于 - udit_log_connection_policy系统变量的值。该值是无符号整数。表6.34“ audit_log_connection_policy_value的值”显示了允许的值和相应的- udit_log_connection_policy值。- 表6.34 audit_log_connection_policy_value的值 - 值 - 对应的audit_log_connection_policy值 - 0要么- "::none"- NONE- 1要么- "::errors"- ERRORS- 2要么- "::all"- ALL- 这些值是符号伪常数,可以代替文字数字值给出。它们必须用字符串引号并且区分大小写。 - "::xxx"
- udit_log_policy_value- 该变量对应于 - udit_log_policy系统变量的值。该值是无符号整数。表6.35“ audit_log_policy_value的值”显示了允许的值和相应的- udit_log_policy值。- 表6.35 audit_log_policy_value的值 - 值 - 对应的audit_log_policy值 - 0要么- "::none"- NONE- 1要么- "::logins"- LOGINS- 2要么- "::all"- ALL- 3要么- "::queries"- QUERIES- 这些值是符号伪常数,可以代替文字数字值给出。它们必须用字符串引号并且区分大小写。 - "::xxx"
- udit_log_statement_policy_value- 该变量对应于 - udit_log_statement_policy系统变量的值。该值是无符号整数。表6.36“ audit_log_statement_policy_value值”显示了允许的值和相应的- udit_log_statement_policy值。- 表6.36 audit_log_statement_policy_value的值 - 值 - 对应的audit_log_statement_policy值 - 0要么- "::none"- NONE- 1要么- "::errors"- ERRORS- 2要么- "::all"- ALL- 这些值是符号伪常数,可以代替文字数字值给出。它们必须用字符串引号并且区分大小写。 - "::xxx"
引用预定义函数
要在log条件中引用预定义的函数,请使用一个function项目,该项目采用name和 rgs值分别指定函数名称及其参数:
{
"filter": {
"class": {
"name": "general",
"event": {
"name": "status",
"log": {
"function": {
"name": "find_in_include_list",
"args": [ { "string": [ { "field": "user.str" },
{ "string": "@"},
{ "field": "host.str" } ] } ]
}
}
}
}
}
}
name项目中指定的函数应仅是函数名称,不带括号或参数列表。该 rgs项目中的参数(如果有)必须按功能说明中列出的顺序给出。参数可以引用预定义的变量,事件字段或字符串或数字常量。
前面的过滤器根据是否在系统变量中找到当前用户来确定是否记录general类status事件 udit_log_include_accounts。该用户是使用事件中的字段构造的。
下表描述了允许使用的function项目预定义功能:
- udit_log_exclude_accounts_is_null()- 检查 - udit_log_exclude_accounts系统变量是否为- NULL。当定义与旧审计日志实现相对应的过滤器时,此功能将很有帮助。- 参数: - 没有。 
- udit_log_include_accounts_is_null()- 检查 - udit_log_include_accounts系统变量是否为- NULL。当定义与旧审计日志实现相对应的过滤器时,此功能将很有帮助。- 参数: - 没有。 
- debug_sleep(millisec)- 睡眠指定的毫秒数。在性能评估期间使用此功能。 - debug_sleep()仅适用于调试版本。- 参数: - millisec:一个无符号整数,它指定要休眠的毫秒数。
 
- find_in_exclude_list(account)- 检查审核日志排除列表中是否存在帐户字符串( - udit_log_exclude_accounts系统变量的值)。- 参数: - ccount:一个字符串,用于指定用户帐户名称。
 
- find_in_include_list(account)- 检查审核日志包含列表( - udit_log_include_accounts系统变量的值)中是否存在帐户字符串。- 参数: - ccount:一个字符串,用于指定用户帐户名称。
 
- string_find(text, substr)- 检查 - substr值中是否包含该- text值。此搜索区分大小写。- 参数: - 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" } }
]
}
}
}
}
}
}
当子过滤器中的 ctivate元素的值为时,将激活一个新的过滤器true。不允许 ctivate在顶层使用filter。
通过使用子ref过滤器内的一项来引用原始过滤器,可以用原始过滤器替换新的过滤器id。
显示的过滤器的运行方式如下:
- 该main过滤器等待table_access的事件,无论是update或delete。
- 如果updateordeletetable_access事件发生在temp_1ortemp_2表上,则将过滤器替换为内部过滤器(不带id,因为无需显式引用它)。
- 如果发出命令结束的信号(general/status事件),则会将一个条目写入审核日志文件,然后将过滤器替换为main过滤器。
过滤器对于记录更新或删除temp_1或temp_2表中的任何内容的语句很有用,例如:
UPDATE temp_1, temp_3SET temp_1. =21, temp_3. =23;
该语句生成多个table_access事件,但是审核日志文件将仅包含general/status条目。
注意
id定义中使用的任何值仅针对该定义进行评估。它们与udit_log_filter_id系统变量的值无关。
