mysql 360百科_mysql上云

更多腾讯海量技术文章,请关注云加社区:https://cloud.tencent/developer

作者:腾讯云数据库内核团队

什么是数据库审计

对于一个仓库,如果要防盗, 常见做法是出入口全装上监控,一旦有问题了,调监控查找异常情况。对数据库来说也类似,数据库也有出入口,对所有连接出入口监控,记录下所有动作,一旦有问题了,查询历史动作,找到关键信息。如果仓库中的东西价值高,损失已经造成,监控只是事后诸葛,所以往往请专业人士在巡逻防盗,防止偷盗发生。同样数据库审计也有更专业的手段,sql阻断,在动作发生前,对动作行为分析,如果判断符合预先设置的高危动作,直接中止执行,防止对数据造成破坏。

审计定义:能够实时记录网络上的数据库活动,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断

常见的审计方式

应用层审计

在应用系统中直接审计,语句还没往数据库后台发就先做了审计,不影响数据库性能,对底层用的是什么数据库也不关心,但对应用系统压力比较大,并且应用系统需要解析语句,有一定复杂度。

传输层审计

往往抓包解析实现,对上下层都没什么影响,但同样要解析语句,有一定复杂度,并且如果传输层是通过加密通讯,将无法解析。

插件审计

对于开源数据库,通常都有提供插件方式增加功能。审计可以以插件直接嵌在内核上,当然会对数据库性能有一定影响,但同样因为直接嵌在内核,很多一手信息能直接拿到,比方说上面没办法回避的语法解析就不用做,而且还能直接拿更多的运行态信息,能开发功能强大又灵活的审计功能。

内核审计

直接在内核上实现,所有功能都能实现,也能将性能影响降到最低,但是对后台稳定性会有影响,对开发人员要求高,不管是开源还是非开源数据库,都会非常慎重考虑直接在内核上支持审计。

oracle审计简介

谈到数据库审计,不能不提oracle,oracle 数据库的审计功能有10多年甚至更长的历史了,对数据库sql审计功能影响深远,几乎任何数据库审计都会参考,下面我们简单了解下oracle审计。Oracle中审计总体上可分为“标准审计”和“细粒度审计”,标准审计包含语句审计,权限审计,对象审计,细粒度审计也称为“基于政策的审计”:

审 计 类 型

说 明

语句审计

按照语句类型审计SQL语句.而不论访问何种特定的模式对象。也可以在数据库中指定一个或多个用户,针对特定的语句审计这些用户

权限审计

审计系统权限,例如GRANT。和语句审计一样,权限审计可以指定一个或多个特定的用户作为审计的目标

对象审计

审计特定模式对象上运行的特定语句(例如,DEPARTMENTS表上的UPDATE语句)。模式对象审计总是应用于数据库中的所有用户

细粒度的审计

根据访问对象的内容来审计表访问和权限。使用程序包DBMS_FGA来建立特定表上的策略

默认情况下审计是关闭的,因为开启性能影响大,需要设置一些参数打开它,审计记录结果既可以放文件也可以放系统表中。那么怎么配置需要审计的内容呢?oracle提供了一套审计配置语法来做这事,audit/noaudit,审计和取消审计,是互逆的,如下所示:

图1

图2

示例如下:

// 审计u1.t2这个表的update 不成功的语句

audit update on u1.t2 by access whenever not successful;

// 审计u1.t2这个表的update 成功的语句

audit update on u1.t2 by access whenever successful;

运算式:f+s=a 连续运行上面两个配置语句,等价审计全部

// 审计u1.t2表update全部语句,全部包括两种,成功和失败

audit update on u1.t2 by access;

// 不审计u1.t2表update成功的语句

noaudit update on u1.t2 by access whenever successful;

运算式:a-s=f 连续运行上面两个配置语句,等价只审计失败语句

a:all,全部

f:fail,失败

s:success,成功

这就是oracle审计配置语法用法,配置完成后就能审计到相应的语句,它的成功、失败、全部是存在运算关系的。如何查询比较简单,直接查询相关表就行,不再介绍。

mysql审计插件

前文提到,插件是数据库实现审计功能的常见手段,mysql上也有不少审计插件,比较有名的Macfee插件,官方audit plugin,mariadb audit plugin,Percona audit plugin。

从功能上来说,这几个插件大同小异,只是展示的审计内容和格式略有差异。从性能上来说,除了macfee插件外,其它几个性能相差不多,宣称都是15%左右影响,macfee则可能达到50%或更多。实际上,确定一个测试性能损失的标准场景是需要商榷的,跑非常简单的语句,几十万Qps,性能影响肯定大,审计性能消耗和语句量直接关联,跑OLAP查询,几秒甚至几十秒执行一个语句,审计性能影响可以说没有,所以审计性能损失得看具体场景。

从实现方式来说,这几个插件也差不太多,从thd对象中取到所需要的属性,按一定规则过滤,按某种策略存盘,以json或xml等格式展示审计结果。

mysql审计接口详细分析

从5.5开始,mysql内核中已经增加了一套的对服务器操作的审计机制的接口,添加了额外的审计流程来对我们所关心的地方进行事件捕获,如果要对服务器进行审计,只要基于这些完善一个插件即可。mysql审计接口官方第一次是提交到代码是2009年底,历史也比较悠久了,修改和增加的文件并不多,几个关键点介绍下。

在plugin.h中增加一个新的宏 MYSQL_AUDIT_PLUGIN 用来标识一类全新的插件类型:AUDIT插件

增加了一个新的头文件:plugin_audit.h,里面有审计相关的关键的结构体及一些宏定义,如下: mysql_event_general结构,query信息结构,对应非登陆相关的动作,如执行一个语句select或一个命令exit。

struct mysql_event_general{unsigned int event_subclass; //子事件类型int general_error_code; //错误码 unsigned long general_thread_id; //线程号const char *general_user; //用户名unsigned int general_user_length; //长度const char *general_command; //命令,如connect,query,shutdown等,error类型存错误,其它为nullunsigned int general_command_length;const char *general_query; //sql语句 unsigned int general_query_length;struct charset_info_st *general_charset; //字符集unsigned long long general_time; //时间戳unsigned long long general_rows; //行计数器MYSQL_LEX_STRING general_host; //来自主机,如localhostMYSQL_LEX_STRING general_sql_command; //操作类型,如selectMYSQL_LEX_STRING general_external_user; // external 用户MYSQL_LEX_STRING general_ip; //ip地址};mysql_event_connection,连接信息结构,对应登陆登出动作

struct mysql_event_connection{unsigned int event_subclass;int status; //错误码unsigned long thread_id;const char *user;unsigned int user_length;const char *priv_user;unsigned int priv_user_length;const char *external_user;unsigned int external_user_length;const char *proxy_user;unsigned int proxy_user_length;const char *host;unsigned int host_length;const char *ip;unsigned int ip_length;const char *database; //数据库名unsigned int database_length;};所有动作都可以用这两个结构来描述,但是并不是说就能满足全部需求,比方说,对general动作,我想知道语句是针对哪些表的,执行了多长时间,无法得到,对于connect动作,我想知道是什么时间发生的,无从得知,这肯定是不够的,仍需我们去继续丰富功能点。

几个关键的宏定义:

#define MYSQL_AUDIT_GENERAL_CLASS 0 //general动作#define MYSQL_AUDIT_GENERAL_LOG 0 //log时,语句execute前#define MYSQL_AUDIT_GENERAL_ERROR 1 //error时,反馈用户前 #define MYSQL_AUDIT_GENERAL_RESULT 2 //结果集返回后#define MYSQL_AUDIT_GENERAL_STATUS 3 //审计流程结束状态#define MYSQL_AUDIT_CONNECTION_CLASS 1 //connect动作#define MYSQL_AUDIT_CONNECTION_CONNECT 0 //连接#define MYSQL_AUDIT_CONNECTION_DISCONNECT 1 //断开#define MYSQL_AUDIT_CONNECTION_CHANGE_USER 2 //切换用户3. 核心功能实现代码:sql_auditc.h,sql_audit.cc,初始化,回收,以及最重要的取出thd对象有效值等一系列动作均在此完成。

在sql_auditc.h中,定义了两个内联函数和三个宏,功能是获取到thd对象中有用值,如用户名,数据库名,时间,sql内容等所需要信息,以参数的形式传给下一层接口。每个动作,都会从这里获取原始信息,会频繁调用这几个函数,所以使用了宏和内联函数来提高性能。

在sql_audit.cc中,除了审计插件初始化,回收外,最重要的功能获得操作原始信息,在这里实现了函数获得上面sql_auditc.h中通过参数形式传入的有用信息,并存入mysql_event_general和mysql_event_connection结构。

4. mysql其它一些连接、插入、解析、日志等接口也增加了审计入口函数。如mysqld.cc、sql_parse.cc等文件中函数增加了审计入口。

审计执行流程简介

登陆登出流程

#0 audit_null_notify (thd=0x7fdcc7ff6000, event_class=0, event=0x7fdd45440cb0) at /mysql56/plugin/audit_null/audit_null.c:99#1 0x0000000000683f22 in plugins_dispatch (thd=0x7fdcc7ff6000, event_subtype=, ap=) at /mysql56/sql/sql_audit.cc:455#2 event_class_dispatch (thd=0x7fdcc7ff6000, event_subtype=, ap=) at /mysql56/sql/sql_audit.cc:491#3 general_class_handler(THD *, uint, typedef __va_list_tag __va_list_tag *) (thd=0x7fdcc7ff6000, event_subtype=, ap=)at /mysql56/sql/sql_audit.cc:90#4 0x00000000006841b1 in mysql_audit_notify (thd=0x7fdcc7ff6000, event_class=0, event_subtype=0) at /mysql56/sql/sql_audit.cc:217#5 0x000000000063e7cb in mysql_audit_general_log (thd=0x7fdcc7ff6000, cmd=0xc76b64 "Connect", cmdlen=7, query_str=, query_len=)at /mysql56/sql/sql_audit.h:125#6 0x000000000063ea5a in log_command (thd=, command=, format=0xc6d27b "%s@%s on %s") at /mysql56/sql/log.cc:2094#7 general_log_print (thd=, command=, format=0xc6d27b "%s@%s on %s") at /mysql56/sql/log.cc:2122#8 0x0000000000682030 in acl_authenticate (thd=0x7fdcc7ff6000, com_change_user_pkt_len=) at /mysql56/sql/sql_acl.cc:11244#9 0x00000000006a8ad0 in check_connection (thd=0x7fdcc7ff6000) at /mysql56/sql/sql_connect.cc:685#10 0x00000000006a8d97 in login_connection (thd=0x7fdcc7ff6000) at /mysql56/sql/sql_connect.cc:754#11 thd_prepare_connection (thd=0x7fdcc7ff6000) at /mysql56/sql/sql_connect.cc:914#12 0x00000000006a9119 in do_handle_one_connection (thd_arg=) at /mysql56/sql/sql_connect.cc:983#13 0x00000000006a91c2 in handle_one_connection (arg=) at /mysql56/sql/sql_connect.cc:906#14 0x0000000000939337 in pfs_spawn_thread (arg=0x7fdccb3be840) at /mysql56/storage/perfschema/pfs.cc:1860#15 0x00007fdd46a249d1 in start_thread () from /lib64/libpthread.so.0#16 0x00007fdd459a38fd in clone () from /lib64/libc.so.6登陆如上所示,登陆时在do_handle_one_connection 中循环等待连接,有请求过来时再到准备连接,再到权限认证检查,最在log_command中进入审计接口,准备审计相关动作。

#0 audit_null_notify (thd=0x7fdcc7eb0000, event_class=1, event=0x7fdd46ca0b40) at /mysql56/plugin/audit_null/audit_null.c:99#1 0x0000000000684402 in plugins_dispatch (thd=0x7fdcc7eb0000, event_subclass=, ap=) at /mysql56/sql/sql_audit.cc:455#2 event_class_dispatch (thd=0x7fdcc7eb0000, event_subclass=, ap=) at /mysql56/sql/sql_audit.cc:491#3 connection_class_handler(THD *, uint, typedef __va_list_tag __va_list_tag *) (thd=0x7fdcc7eb0000, event_subclass=, ap=)at /mysql56/sql/sql_audit.cc:114#4 0x00000000006841b1 in mysql_audit_notify (thd=0x7fdcc7eb0000, event_class=1, event_subtype=1) at /mysql56/sql/sql_audit.cc:217#5 0x000000000057bb53 in close_connection (thd=0x7fdcc7eb0000, sql_errno=0) at /mysql56/sql/mysqld.cc:2634#6 0x00000000006a90b2 in do_handle_one_connection (thd_arg=) at /mysql56/sql/sql_connect.cc:996#7 0x00000000006a91c2 in handle_one_connection (arg=) at /mysql56/sql/sql_connect.cc:906#8 0x0000000000939337 in pfs_spawn_thread (arg=0x7fdccb3be7a0) at /mysql56/storage/perfschema/pfs.cc:1860#9 0x00007fdd46a249d1 in start_thread () from /lib64/libpthread.so.0#10 0x00007fdd459a38fd in clone () from /lib64/libc.so.6登出时相对简单,在close_connection中增加了审计动作。

query审计流程执行前

#0 audit_null_notify (thd=0x7fdcc7ff6000, event_class=0, event=0x7fdd45440da0) at /mysql56/plugin/audit_null/audit_null.c:99#1 0x0000000000683f22 in plugins_dispatch (thd=0x7fdcc7ff6000, event_subtype=, ap=) at /mysql56/sql/sql_audit.cc:455#2 event_class_dispatch (thd=0x7fdcc7ff6000, event_subtype=, ap=) at /mysql56/sql/sql_audit.cc:491#3 general_class_handler(THD *, uint, typedef __va_list_tag __va_list_tag *) (thd=0x7fdcc7ff6000, event_subtype=, ap=)at /mysql56/sql/sql_audit.cc:90#4 0x00000000006841b1 in mysql_audit_notify (thd=0x7fdcc7ff6000, event_class=0, event_subtype=0) at /mysql56/sql/sql_audit.cc:217#5 0x000000000063e7cb in mysql_audit_general_log (thd=0x7fdcc7ff6000, cmd=0xc76b19 "Query", cmdlen=5, query_str=, query_len=)at /mysql56/sql/sql_audit.h:125#6 0x000000000063e93e in log_command (thd=0x7fdcc7ff6000, com...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值