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

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

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驱动…

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

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

                            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大模型语音开发板采集用户语音,将语音数据传输…

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

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

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

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

                            微信小程序案例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、…

                            Elasticsearch 开放推理 API 增加了 Azure AI Studio 支持

                            作者:来自 Elastic Mark Hoy Elasticsearch 开放推理 API 现已支持 Azure AI Studio。在此博客中了解如何将 Azure AI Studio 功能与 Elasticsearch 结合使用。 作为我们持续致力于为 Microsoft Azure 开发人员提供他们选择的工具的一部分,我们很高兴地宣…

                            JUC学习笔记02

                            文章目录 JUC笔记2练习题:手写线程池代码解释:AdvancedThreadPool 类:WorkerThread 内部类:AdvancedThreadPoolExample 类: 线程池的思考CPU密集型IO密集型 练习题:手写自动重试机练习题:手写定…

                            baigeiRSA

                            baigeiRSA 打开附件有两个: 1.import libnumfrom Crypto.Util import numberfrom secret import flag​size 128e 65537p number.getPrime(size)q number.getPrime(size)n p*q​m libnum.s2n(flag)c pow(m, e, n)​print(n %d % n)print(c %d % c)​​2.n…

                            【csp-j学习完C++语法后,如何进阶学习C++算法和数据结构?】

                            在掌握了 CSP - J 的 C 语法基础后,接下来的进阶学习需要系统地掌握各类算法和数据结构知识,并通过大量练习来巩固和提高应用能力。以下是一份详细的进阶学习规划: 第一阶段:基础算法学习(1 - 2 个月) 排…

                            QT中解决使用QCustomplot绘制高速大量数据时频谱图卡顿问题

                            [!!!核心方法!!!] 使用带参数的replot()函数绘制m_pCustomPlot>replot(QCustomPlot::rpQueuedReplot) 1. replot() 方法 void QCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority rp…

                            【AI】卷积神经网络CNN

                            不定期更新,建议关注收藏点赞。 目录 零碎小组件经验总结早期的CNN 零碎小组件 全连接神经网络 目前已经被替代。 每个神经元都有参与,但由于数据中的特征点变化大,全连接神经网络把所有数据特征都学习了,故效果不好。感受野&…

                            微信小程序~电器维修系统小程序

                            博主介绍:✌程序猿徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

                            LLAMA-Factory安装教程(解决报错cannot allocate memory in static TLS block的问题)

                            步骤一: 下载基础镜像 # 配置docker DNS vi /etc/docker/daemon.json # daemon.json文件中 { "insecure-registries": ["https://swr.cn-east-317.qdrgznjszx.com"], "registry-mirrors": ["https://docker.mirrors.ustc.edu.c…

                            Java高频面试之SE-18

                            hello啊,各位观众姥爷们!!!本baby今天又来了!哈哈哈哈哈嗝🐶 BIO NIO AIO的区别? 在 Java 网络编程中,BIO、NIO 和 AIO 是三种不同的 I/O 模型,它们的核心区别在于 阻塞…

                            蓝桥杯刷题DAY3:Horner 法则 前缀和+差分数组 贪心

                            所谓刷题,最重要的就是细心 📌 题目描述 在 X 进制 中,每一数位的进制不固定。例如: 最低位 采用 2 进制,第二位 采用 10 进制,第三位 采用 8 进制, 则 X 进制数 321 的十进制值为&#xff…

                            BUU24 [GXYCTF2019]BabyUpload 1

                            开局上传文件 上传muma.php 上传.htaccess文件也被打回 再次求助互联网,才发现这提示给的多么明显,上传.htaccess文件是检查文件类型(Contnet-Type),上传muma.php是检查后缀里头有没有ph ,检查文件类型那…