数据库高安全—审计追踪:传统审计统一审计

书接上文数据库高安全—角色权限:权限管理&权限检查,从权限管理和权限检查方面解读了高斯数据库的角色权限,本篇将从传统审计统一审计两方面对高斯数据库的审计追踪技术进行解读。

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审计日志执行完成。

                            以上内容从传统审计和统一审计两方面对高斯数据库的审计追踪技术进行解读,下篇将从数据动态脱敏方面对高斯数据库的数据保护技术进行解读,敬请期待~

                            本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/68206.shtml

                            如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

                            相关文章

                            第三个Qt开发实例:利用之前已经开发好的LED驱动在Qt生成的界面中控制LED2的亮和灭

                            前言 上一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145459006 中,我们是直接利用GPIO子系统控制了LED2的亮和灭,这篇博文中我们利用之前写好的LED驱动程序在Qt的生成的界面中控制LED2的亮和灭。 之前已经在下面两篇博文中实现了LED驱动…

                            deepseek来讲lua

                            Lua 是一种轻量级、高效、可嵌入的脚本语言,广泛应用于游戏开发、嵌入式系统、Web 服务器等领域。以下是 Lua 的主要特点和一些基本概念: 1. 特点 轻量级:Lua 的核心非常小,适合嵌入到其他应用程序中。高效:Lua 的执…

                            (动态规划 leetcode377)组合求和IV

                            确立状态转移方程需要深入理解问题,合理定义子问题,找到边界条件(比如dp[0]),分析状态之间的转移关系(dp和dp之间的关系),并进行验证。 递归是自顶向下,而dp是自下而上 这里是i作为目标值&…

                            解决aspose将Excel转成PDF中文变成方框的乱码问题

                            原文网址:解决aspose将Excel转成PDF中文变成方框的乱码问题_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何解决aspose将Excel转成PDF中文变成方框的乱码问题。 问题描述 用aspose将word、excel等转成PDF后,英文展示正常,但中文全部变成了…

                            Netty 核心原理与高并发场景实践

                            在当今的网络编程领域,随着互联网应用的不断发展,对高并发、高性能网络通信的需求日益增长。Netty 作为一款基于 Java 的异步事件驱动的网络应用框架,凭借其卓越的性能和丰富的功能,成为了实现高并发网络应用的首选工具。无论是在…

                            问题大集04-浏览器阻止从 本地 发起的跨域请求,因为服务器的响应头 Access-Control-Allow-Origin 设置为通配符 *

                            1、问题 localhost/:1 Access to XMLHttpRequest at xxx(请求) from origin http://localhost:xxx(本地) has been blocked by CORS policy: The value of the Access-Control-Allow-Origin header in the response must not be t…

                            判断192.168.1.0/24网络中,当前在线的ip有哪些

                            需求:判断192.168.1.0/24网络中,当前在线的ip有哪些,并编写脚本打印出来。 [rootopenEuler ~]# cat 1.sh #!/bin/bash for ip in $(seq 1 254); do ping -c 1 -W 1 "192.168.1.$ip" > /dev/null 2>&1 if [ $? …

                            vue-vite axios bug

                            axios-bug http proxy error Error: write ECONNABORTED 代码写法 一般baseURL不是单写前缀就可以了吗,为何要写死就不会出现以上错误,求解。

                            【Spring】_SpringBoot配置文件

                            目录 1.Spring Boot配置文件 1.1 Spring Boot 的配置文件类型及命名 1.2 properties和yml的优先级 2. properties配置文件 1.1 properties语法格式 1.2 自定义配置及配置文件的读取 1.3 properties的缺点 3. yml配置文件 3.1 yml语法格式 3.2 自定义配置及配置文件的…

                            实操给触摸一体机接入大模型语音交互

                            本文以CSK6 大模型开发板串口触摸屏为例,实操讲解触摸一体机怎样快速增加大模型语音交互功能,使用户能够通过语音在一体机上查询信息、获取智能回答及实现更多互动功能等。 在本文方案中通过CSK6大模型语音开发板采集用户语音,将语音数据传输…

                            深入解析 FFmpeg 的 AAC 编解码过程

                            深入解析 FFmpeg 的 AAC 编解码过程 —— 技术详解与代码实现 AAC(Advanced Audio Coding) 是一种高效的有损音频压缩格式,因其高压缩效率和良好的音质而被广泛应用于流媒体、广播和音频存储等领域。FFmpeg 是一个强大的多媒体处理工具,支持 AAC 的编码和解码。本文将详细…

                            RabbitMQ 从入门到精通:从工作模式到集群部署实战(一)

                            #作者:闫乾苓 文章目录 RabbitMQ简介RabbitMQ与VMware的关系架构工作流程RabbitMQ 队列工作模式及适用场景简单队列模式(Simple Queue)工作队列模式(Work Queue)发布/订阅模式(Publish/Subscribe&#xff…

                            探索 Spring Cloud Alibaba:开启微服务架构新时代

                            一、引言 在当今数字化浪潮中,软件系统的规模和复杂度不断攀升,传统的单体架构逐渐难以满足快速迭代、高并发处理以及灵活扩展的需求。微服务架构应运而生,它将一个大型的应用拆分成多个小型、自治的服务,每个服务专注于特定的业务…

                            Linux基础命令之Nginx中的rewrite功能(重新)

                            一、什么是Rewrite Rewrite也称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程。 1. URL Rewrite最常见的应用是URL伪静态化,是将动态页面显示为静态页面方式的一种技术。比如http://www.123.com/news/index.php?id123 使…

                            anaconda使用

                            anaconda配置镜像源: 引用:https://zhuanlan.zhihu.com/p/17776864328 # 显示所有的镜像源 conda config --show channels # 设置镜像源 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add c…

                            DeepSeek 阐述 2025年前端发展趋势

                            预测2025年前端的发展趋势。首先,我需要考虑当前的前端 技术发展情况,以及近几年的变化趋势。比如,框架方面,React、Vue、Angular这些主流框架的更新方向和社区活跃度。可能用户想知道未来哪些技术会更流行,或者需要学…

                            RK3568平台开发系列讲解(ConfigFS篇)ConfigFS核心数据结构

                            🚀返回专栏总目录 文章目录 一、数据结构二、结构体关系三、案例3.1、configfs_subsystem 实例3.2、config_group 实例化四、属性和方法五、config_item实例化沉淀、分享、成长,让自己和他人都能有所收获!😄 理解 ConfigFS 的核心数据结构对于深入使用和定制 ConfigFS 非…

                            【实战篇】巧用 DeepSeek,让 Excel 数据处理更高效

                            一、为何选择用 DeepSeek 处理 Excel 在日常工作与生活里,Excel 是我们频繁使用的工具。不管是统计公司销售数据、分析学生成绩,还是梳理个人财务状况,Excel 凭借其强大的功能,如数据排序、筛选和简单公式计算,为我们提供了诸多便利。但当面对复杂的数据处理任务,比如从…

                            微信小程序案例1——制作猫眼电影底部标签导航栏

                            文章目录 一、项目步骤1 新建一个无AppID的movie项目2将准备好的底部标签导航图标拷贝到movie项目下面(将图标文件夹image放到项目文件夹里)3 打开App.json配置文件,在pages数组里添加4个页面路径:电影“pages/movie/movie”、影院“pages/cinema/cinema…

                            CSS 伪类(Pseudo-classes)的详细介绍

                            CSS 伪类详解与示例 在日常的前端开发中,CSS 伪类可以帮助我们非常精准地选择元素或其特定状态,从而达到丰富页面表现的目的。本文将详细介绍以下伪类的使用: 表单相关伪类 :checked、:disabled、:enabled、:in-range、:invalid、:optional、…