数据库高安全—审计追踪:传统审计统一审计
书接上文数据库高安全—角色权限:权限管理&权限检查,从权限管理和权限检查方面解读了高斯数据库的角色权限,本篇将从传统审计和统一审计两方面对高斯数据库的审计追踪技术进行解读。
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_ok
pgaudit_system_start_ok
pgaudit_system_stop_ok
pgaudit_user_login
pgaudit_user_logout
pgaudit_system_switchover_ok
pgaudit_user_no_privileges
pgaudit_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审计日志执行完成。
以上内容从传统审计和统一审计两方面对高斯数据库的审计追踪技术进行解读,下篇将从数据动态脱敏方面对高斯数据库的数据保护技术进行解读,敬请期待~
相关文章:

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

机器学习 - 需要了解的条件概率、高斯分布、似然函数
似然函数是连接数据与参数的桥梁,通过“数据反推参数”的逆向思维,成为统计推断的核心工具。理解它的关键在于区分“参数固定时数据的概率”与“数据固定时参数的合理性”,这种视角转换是掌握现代统计学和机器学习的基础。 一、在学习似然函…...

Spring Boot Web 入门
目录 Spring Boot Web 是 Spring Boot 框架的一个重要模块,它简化了基于 Spring 的 Web 应用程序的开发过程。以下是一个 Spring Boot Web 项目的入门指南,涵盖了项目创建、代码编写、运行等关键步骤。 1. 项目创建 使用 Spring Initializr 使用 IDE …...

神经网络|(八)概率论基础知识-二项分布及python仿真
【1】引言 前序已经学习了古典概型、条件概率、全概率公式和贝叶斯公式,它们作为基础,解释了事件发生及其概率的对应关系,相关文章链接为: 神经网络|(四)概率论基础知识-古典概型-CSDN博客 神经网络|(五)概率论基础知识-条件概…...
【面试场景】MySQL分布式主键选取
文章目录 一. MySQL的自增主键二. UUID三. 雪花ID(推荐) 我的博客地址 一. MySQL的自增主键 适合单表的情况, 在分布式分库分表下可能会有一些问题 主键冲突问题 在分布式系统中,多个数据库节点独立生成自增主键,很容易出现重复的主键值。例如ÿ…...
执行git stash drop stash@{x} 时出现error: unknown switch `e‘ 的解决方式
原因: 在 PowerShell 或某些 Shell 中,{} 是特殊符号,stash{0} 会被解析成 stash 0,而 后的字符可能被误认为选项(如 -e),使 Git 收到意外的 -e 参数,导致报错 unknown switch ‘e’。 解决方…...

链表和 list
一、单链表的模拟实现 1.实现方式 链表的实现方式分为动态实现和静态实现两种。 动态实现是通过 new 申请结点,然后通过 delete 释放结点的形式构造链表。这种实现方式最能体 现链表的特性; 静态实现是利用两个数组配合来模拟链表。一个表示数据域&am…...
windows 蓝牙驱动开发-传输总线驱动程序常见问题
以下是驱动程序开发人员在开发总线驱动程序以支持蓝牙功能时可能会遇到的一些常见问题和方案。 我的串行总线驱动程序遇到了一些错误。 它意味着什么? 代码 10-49:设备管理器生成的错误代码。 代码 51:当串行总线驱动程序具有相关的控制器…...

Qt修仙之路2-1 炼丹初成
widget.cpp #include "widget.h" #include<QDebug> //实现槽函数 void Widget::login1() {QString userusername_input->text();QString passpassword_input->text();//如果不勾选无法登入if(!check->isChecked()){qDebug()<<"xxx"&…...

【含开题报告+文档+PPT+源码】基于SpringBoot+Vue宠物预约上门服务预约平台
开题报告 本研究论文旨在构建并阐述一个基于 SpringBoot 和 Vue 技术栈开发的宠物上门服务预约平台的设计与实现。该平台集成了丰富的功能模块,为用户提供一体化的便捷服务体验。首先,用户能够通过注册并登录系统,享受个性化的服务流程。在平…...
无线AP之详解(Detailed Explanation of Wireless AP)
无线AP是什么? 市场上的AP基本上分为两大类:单纯型AP和扩展型AP。扩展型AP除了基本的AP功能之外,还可能带有若干以太网交换口、路由、NAT、DHCP、打印服务器等功能。 无线AP也就是一个无线交换机 无线路由器就是一个带路由功能的无线AP&am…...
Spring Boot Actuator与JMX集成实战
在微服务架构中,监控和管理应用的运行状态是至关重要的。Spring Boot Actuator 提供了一种便捷的方式来监控和管理 Spring Boot 应用,而 JMX(Java Management Extensions)则是一种用于管理 Java 应用的标准技术。本文将通过一个实…...

mac环境下,ollama+deepseek+cherry studio+chatbox本地部署
春节期间,deepseek迅速火爆全网,然后回来上班,我就浅浅的学习一下,然后这里总结一下,我学习中,总结的一些知识点吧,分享给大家。具体的深度安装部署,这里不做赘述,因为网…...

camera光心检测算法
1.概要 光心检测算法,基于opencv c实现,便于模组厂快速集成到软件工具中,适用于camera模组厂算法评估组装制程镜头与sensor的偏心程度,便于工程师了解制程的问题找出改善方向。 2.技术介绍 下图为camera模组厂抓取的bayer-raw经过…...
【MySQL】向后兼容设计规范(无回滚场景)
MySQL 向后兼容设计规范(无回滚场景) 在 不支持数据库回滚 且需保证 长期向后兼容性 的系统中,需通过 架构设计 和 流程管控 规避风险。以下是关键设计规范: 一、变更流程规范 变更分类分级 变更类型风险评估等级审批流程测试要求…...

还搞不透stm32单片机启动过程?一篇文章几百字让你彻底看懂!
1.stm32启动 1.1 msp和pc的初始值,第一步: 2.boot的值就被锁定了 可以根据实际绑定的值变动, 这里补充一点boot1和0的原理: 1.2来点刺激的: 这里我插入一个链接: 【明解STM32】一文搞明白STM32芯片存储…...

无界构建微前端?NO!NO!NO!多系统融合思路!
文章目录 微前端理解1、微前端概念2、微前端特性3、微前端方案a、iframeb、qiankun --> 使用比较复杂 --> 自己写对vite的插件c、micro-app --> 京东开发 --> 对vite支持更拉跨d、EMP 方案--> 必须使用 webpack5 --> 很多人感觉不是微前端 --> 去中心化方…...

DeepSeek辅助段落扩写的能力怎么样?
DeepSeek-R1在学术写作的诸多细节层面展现出了显著的应用价值。接下来我们将通过一系列具体案例,深入探讨该工具如何在扩写、翻译、发表以及内容改进等关键环节为学术写作提供有力支持。在提问环节,DeepSeek-R1能够高效地简化提示词,并精准地…...

分形的魅力:数学与艺术的完美结合
分形的魅力:数学与艺术的完美结合 分形(Fractal)是一种神奇的数学结构,它以其无限的复杂性和自相似性吸引了无数科学家、艺术家和数学爱好者。分形不仅仅是数学中的一个概念,它还广泛应用于自然科学、计算机图形学和艺…...

如何通过工业智能网关进行数控机床数据采集?
数控机床数据采集过程是一个从物理连接到数据处理的完整链条,涉及设备连接、数据采集、预处理和传输的复杂过程,包含通信协议匹配、设备配置、数据采集设置、数据预处理和传输等多个环节。天拓四方自主研发的TDE工业智能网关作为这一过程中的核心设备&am…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...