书接上文数据库高安全—脚色权限:权限管理&权限检查,从权限管理和权限检查方面解读了高斯数据库的脚色权限,本篇将从传统审计和同一审计两方面对高斯数据库的审计追踪技能进行解读。
4 审计追踪
4.1 传统审计
审计内容的记录方式通常有两种:记录到数据库的表中、记录到OS文件中。openGauss接纳记录到OS文件中(即审计日志)的方式来生存审计结果,审计日志文件夹受操纵体系权限保护,默认只有初始化用户可以读写,从数据库安全角度出发,包管了审计结果的可靠性。日志文件的存储目次由audit_directory参数指定。
openGauss审计日志每条记录包罗time、type、result、userid、username、database、client_conninfo、object_name、detail_info、node_name、thread_id、local_port、remote_port共13个字段。图1为审计日志的单条记录示例。
图1 审计记录示例
对审计日志文件进行读写的函数紧张位于pgaudit.cpp文件中,其中紧张包罗两类函数:审计文件的读、写、更新函数;审计记录的增、删、查接口。
起首我们介绍审计文件的数据布局。
openGauss的审计日志接纳文件的方式存储在指定目次中。通过查看目次,我们发现日志紧张包罗两类文件:形如0_adt的审计文件以及名为index_table索引文件。
图2 审计文件布局
以adt结尾的审计文件中,每一条审计记录对应一个AuditData布局体。
数据布局AuditData:
- typedef struct AuditData {
-
- AuditMsgHdr header; // 记录文件头,存储记录的标识、大小等信息 AuditType type; // 审计类型 AuditResult result; // 执行结果 char varstr[1]; // 二进制格式存储的具体审计信息 } AuditData;
复制代码 其中AuditMsgHdr记录着审计记录的标识信息,其布局如下:
数据布局 AuditMsgHdr:
- typedef struct AuditMsgHdr {
-
- char signature[2]; // 审计记录标识,目前固定为AUDIT前两个字符’A’和’U’ uint16 version; // 版本信息,目前固定为0 uint16 fields; // 审计记录字段数,目前为13 uint16 flags; // 记录有效性标识,如果被删除则标记为DEAD pg_time_t time; // 审计记录创建时间 uint32 size; // 审计信息占字节长度 } AuditMsgHdr;
复制代码 AuditData的其他布局存储着审计记录的审计信息,AuditType为审计范例,目前有38种范例。AuditResult为执行的结果,有AUDIT_UNKNOWN、AUDIT_OK、AUDIT_FAILED三种结果。其余的各项信息,均通过二进制的方式写入到varstr中。
审计日志有关的另一个文件为索引文件index_table,其中记录着审计文件的数量、审计日志文件编号、审计文件修改日期等信息。
数据布局 AuditIndexTable:
- typedef struct AuditIndexTable {
-
- uint32 maxnum; // 审计目录下审计文件个数的最大值 uint32 begidx; // 审计文件开始编号 uint32 curidx; // 当前使用的审计文件编号 uint32 count; // 当前审计文件的总数 pg_time_t last_audit_time; // 最后一次写入审计记录的时间 AuditIndexItem data[1]; // 审计文件指针 } AuditIndexTable;
复制代码 索引文件中每一个AuditIndexItem对应一个审计文件,其布局如下:
数据布局 AuditIndexTable:
- typedef struct AuditIndexItem {
-
- pg_time_t ctime; // 审计文件创建时间 uint32 filenum; // 审计文件编号 uint32 filesize; // 审计文件占空间大小 } AuditIndexItem;
复制代码 审计文件的读、写类函数如auditfile_open、auditfile_rotate等函数实现较简朴,读者可以直接阅读源码。
下面紧张介绍日志文件的布局和日志记录的增、删、查接口。
审计记录的写入接口为audit_report函数。该函数的原型为:
- void audit_report(AuditType type, AuditResult result, const char* object_name, const char* detail_info);
复制代码 其中入参type、result、object_name、detail_info分别对应审计日志记录中的相应字段,审计日志中的其余9个字段均为函数在执行时从全局变量中获取。
audit_report函数的执行紧张分为3个部分,起首会检查审计的各项开关,判定是否需要审计该操纵。然后根据传入的参数、全局变量中的参数以及当前时间,生成审计日志所需的信息并拼接成字符串。末了调用审计日志文件读写接口,将审计日志写入文件中。
审计记录查询接口为pg_query_audit函数,该函数为数据库内置函数,可供用户直接调用,调用情势为:
- SELECT * FROM pg_query_audit (timestamptz startime,timestamptz endtime, audit_log);
复制代码 入参为需要查询审计记录的起始时间和终止时间以及审计日志文件所在的物理路径。当不指定audit_log时,默认查看毗连当前实例的审计日志信息。
审计记录的删除接口为pg_delete_audit函数,该函数为数据库内置函数,可供用户直接调用,调用情势为:
- SELECT * FROM pg_delete_audit (timestamptz startime,timestamptz endtime);
复制代码 入参为需要被删除审计记录的起始时间和终止时间。该函数通过调用pgaudit_delete_file来将审计日志文件中,startime与endtime之间的审计记录标记为AUDIT_TUPLE_DEAD,到达删除审计日志的效果,而不实际删除审计记录的物理数据。也即执行该函数,审计日志文件大小不会减小。
4.2 同一审计
1. 执行原理
审计机制是openGauss的内置安全能力之一,openGauss提供对用户发起的SQL行为审计和追踪能力,支持针对DDL、DML语句和关键行为(登录、登出、体系启动、规复)的审计。在每个工作线程初始化阶段把审计模块加载至线程中,其审计的执行原理是把审计函数赋给SQL生命周期差异阶段的Hook,当线程执行至SQL处置惩罚流程的特定阶段后会进行审计执行判定逻辑,审计模块加载关键代码如下:
- void pgaudit_agent_init(void) {
-
- … // DDL、DML语句审计hook赋值, 赋值结束后标识审计模块已在此线程加载 prev_ExecutorEnd = ExecutorEnd_hook; ExecutorEnd_hook = pgaudit_ExecutorEnd; prev_ProcessUtility = ProcessUtility_hook; ProcessUtility_hook = (ProcessUtility_hook_type)pgaudit_ProcessUtility; u_sess->exec_cxt.g_pgaudit_agent_attached = true;}
复制代码 SQL语句在执行到ProcessUtility_hook 和 ExecutorEnd_hook函数指针时,会分别进入到已预置好的审计流程中,这两个函数指针的位置在SQL进入执行器执行之前,具体关系如图3所示。
图3 审计执行关系图
如图3所示,在线程初始化阶段,审计模块已加载完毕,SQL经过优化器得到筹划树,此时审计模块pgaudit_ExecutorEnd和pgaudit_ProcessUtility函数分别进行DML和DDL语句的分析,如果和已设置审计策略相匹配,则会调用审计日志接口,生成对应的审计日志,对于体系变更类的审计直接内置于相应行为的内核代码中。
2. 关键执行流程
1) 体系变更类审计执行:
- pgaudit_system_recovery_okpgaudit_system_start_okpgaudit_system_stop_okpgaudit_user_loginpgaudit_user_logoutpgaudit_system_switchover_okpgaudit_user_no_privilegespgaudit_lock_or_unlock_user
复制代码 以上为openGauss支持体系变更类的审计执行函数,对于此类审计函数均嵌入内核相应调用流程中,以审计用户登入登出pgaudit_user_login为例说明其主体流程。
图4 登入审计执行流程
图4为服务端校验客户端登入时的紧张流程,以登录失败场景为例,起首根据设置文件和客户端IP和用户信息确认接纳的认证方式(包罗sha256和SSL认证等),然后根据差异的认证方式接纳差异的认证流程和客户端进行交互完成认证身份流程,如果认证失败,则线程退出报错给客户端,pgaudit_user_login即在认证失败的时候调用,获取当前访问数据库名称和具体信息,调用审计日志接口记录于审计日志中供审计管理员查看,关键代码如下:
- /* 拼装登入口失败时候的详细信息,包括数据库名称和用户名 */rc = snprintf_s(details,PGAUDIT_MAXLENGTH, PGAUDIT_MAXLENGTH - 1, "login db(%s)failed,authentication for user(%s)failed", port->database_name, port->user_name); securec_check_ss(rc, "\0", "\0");// 调用登入审计函数,记录审计日志pgaudit_user_login(FALSE, port->database_name, details);// 退出当前线程ereport(FATAL, (errcode(errcode_return), errmsg(errstr, port->user_name)))
复制代码 登入审计日志接口pgaudit_user_login则紧张完成审计日志记录接口需要参数的拼接:
- void pgaudit_user_login(bool login_ok, const char* object_name, const char* detaisinfo){
-
- AuditType audit_type; AuditResult audit_result; Assert(detaisinfo); // 审计类型和审计结果拼装 if (login_ok) {
-
- audit_type = AUDIT_LOGIN_SUCCESS; audit_result = AUDIT_OK; } else { audit_type = AUDIT_LOGIN_FAILED; audit_result = AUDIT_FAILED; } // 直接调用审计日志记录接口 audit_report(audit_type, audit_result, object_name, detaisinfo);}
复制代码 2) DDL、DML语句审计执行
依据审计日志执行原理,DDL、DML语句的执行分别由于pgaudit_ProcessUtility、pgaudit_ExecutorEnd来承载,起首介绍函数pgaudit_ProcessUtility,其主体布局如下:
DDL审计执行函数关键入参parsetree用于识别审计日志范例(create/drop/alter等操纵),入参queryString生存原始执行SQL语句,用于记录审计日志,略去非关键流程,此函数紧张根据判定nodeTag所归属的DDL操纵范例,进入差异的审计执行逻辑,以T_CreateStmt为例,识别当前语句create table则进入pgaudit_ddl_table逻辑进行审计日志执行并最终记录审计日志。
图5 DDL审计执行流程
如图5所示,起首从当前SQL语句中获取执行对象类别校验其相应的审计开关是否开启,当前支持开启的全量对象如下,可以通过GUC参数audit_system_object控制:
- typedef enum { DDL_DATABASE = 0,DDL_SCHEMA, DDL_USER,DDL_TABLE,DDL_INDEX,DDL_VIEW,DDL_TRIGGER,DDL_FUNCTION,DDL_TABLESPACE,DDL_RESOURCEPOOL,DDL_WORKLOAD,DDL_SERVERFORHADOOP,DDL_DATASOURCE,DDL_NODEGROUP,DDL_ROWLEVELSECURITY,DDL_TYPE,DDL_TEXTSEARCH,DDL_DIRECTORY,DDL_SYNONYM} DDLType;
复制代码 如果DDL操纵的对象审计已开启则进行审计日志记录流程,在调用审计日志记录函数audit_report之前需要对包罗暗码的SQL语句进行脱敏处置惩罚,即将包罗暗码的语句中(create role/user)暗码替换成‘********’用于隐藏敏感信息,至此针对create DDL语句的审计执行完成,其他范例DDL语句主体流程一致,不做赘述。
下面介绍针对DML语句审计执行逻辑pgaudit_ExecutorEnd,团体调用流程如下图6所示。
图6 DML审计执行流程
起首判定SQL查询语句所归属的查询范例,以CMD_SELECT范例为例,先获取查询对象的object_name用于审计日志记录中访问对象的记录,然后调用pgaudit_dml_table:
- case CMD_SELECT:object_name = pgaudit_get_relation_name(queryDesc->estate->es_range_table);pgaudit_dml_table_select(object_name, queryDesc->sourceText);
复制代码 和DDL的记录一样,同样会对敏感信息进行脱敏后调用审计日志记录接口audit_report,DML审计日志执行完成。
以上内容从传统审计和同一审计两方面对高斯数据库的审计追踪技能进行解读,下篇将从数据动态脱敏方面对高斯数据库的数据保护技能进行解读,敬请等待~
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |