# 架构原理
#### 核心原理
**传统审计**
传统审计的记录对象是由GUC参数控制的，GUC参数及对应对象如[表1]所示。
 表1审计GUC开关及描述 
| 审计GUC开关                      | 功能                                                   | 设置建议               |
|:---|:---|:---|
| audit_system_object        | 该参数表示是否对数据库对象的CREATE、DROP、ALTER等操作进行审计                | 建议保持默认参数值，按需开启     |
| audit_dml_state            | 该参数表示是否对所有表的INSERT、UPDATE、DELETE、MERGE操作进行审计          | 高频操作，不建议开启，影响性能   |
| audit_dml_state_select     | 该参数表示是否对SELECT操作进行审计                                 | 高频操作，不建议开启，影响性能    |
| audit_function_exec         | 该参数表示在执行存储过程、匿名块或自定义函数（不包括系统自带函数）时是否记录审计信息              | 建议保持默认参数值，按需开启     |
| audit_system_function_exec | 该参数表示在执行白名单内的系统函数时是否记录审计日志                            | 建议保持默认参数值，按需开启    |
| audit_copy_exec            | 该参数表示是否对COPY操作进行审计                                    | 建议保持默认参数值           |
| audit_set_parameter        | 该参数表示是否对SET操作进行审计                                    | 高频操作，不建议开启，影响性能    |
| audit_xid_info             | 该参数表示是否在审计日志字段detail_info中记录SQL语句的事务ID               | 建议保持默认参数值，按需开启      |
| audit_login_logout           | 该参数表示是否开启用户登录、退出的审计功能                                 | 安全类型操作，建议保持默认参数值  |
| audit_database_process    | 该参数表示是否开启数据库启动、停止、恢复和切换的审计功能。                        | 安全类型操作，建议保持默认参数值 |
| audit_user_locked           | 该参数表示是否开启审计用户锁定和解锁功能                                  | 安全类型操作，建议保持默认参数值   |
| audit_user_violation      | 该参数表示是否开启用户越权操作审计功能                                  | 安全类型操作，按需开启       |
| audit_grant_revoke         | 该参数表示是否开启审计用户权限授予和回收功能                               | 安全类型操作，建议保持默认参数值    |
| audit_internal_event       | 该参数表示是否对内部工具cm_agent、gs_clean、WDRXdb的登录或者退出登录及操作进行审计 | 建议保持默认参数值，按需开启       |
   
传统审计采用记录到OS文件中（即审计日志）的方式来保存审计结果，审计日志文件夹受操作系统权限保护。日志文件的存储目录由audit_directory参数指定。
审计日志每条记录包括time、type、result、userid、username、database、client_conninfo、object_name、detail_info、node_name、thread_id、local_port、remote_port共13个字段。包含上述信息的语法树结构体通过执行器执行结束接口传递到审计信息处理模块，审计信息处理模块填充要记录的审计对象信息的buffer，将该包含审计日志的buffer发送到共享内存中，再由后台审计线程通过共享内存取出审计日志，并定时批量写入audit_directory指定的目录下的日志文件中。交互流程如[图1]所示。
图1审计日志写入流程   
![](https://support.huaweicloud.com/bestpractice-gaussdb/figure/zh-cn_image_0000002590206056.png "点击放大")
审计模块提供对用户发起的SQL行为审计和追踪能力，支持针对DDL、DML语句和关键行为（登录、登出、系统启动、恢复）的审计。在每个工作线程初始化阶段把审计模块加载至线程中，其审计的执行原理是把审计函数赋给SQL生命周期不同阶段的Hook，当线程执行至SQL处理流程的特定阶段后会进行审计执行判定逻辑。审计还提供许多其他钩子函数供工作线程调用以记录审计事件，例如：
- audit_system_recovery_ok记录数据库恢复成功行为。
- audit_system_start_ok记录数据库启动成功行为。
- audit_system_stop_ok记录数据库停止成功行为。
- audit_system_switchover_ok记录数据库切换成功行为。
- audit_user_login记录用户登录行为。
- audit_user_logout记录用户登出行为。
- audit_user_no_privileges记录无权限操作行为。
- audit_lock_or_unlock_user记录用户锁定、解锁行为。
- audit_grant_or_revoke_role记录授权、撤销权限的行为。
- audit_security_label记录安全标签的创建、删除和应用操作。
对于审计文件，审计日志采用文件的方式存储在指定目录中，文件结构请参考[图2]。日志主要包括两类文件：形如0_adt的审计日志文件以及名为index_table的审计索引文件。
图2审计文件结构   
![](https://support.huaweicloud.com/bestpractice-gaussdb/figure/zh-cn_image_0000002620725555.png "点击放大")
审计日志文件的管理由审计线程进行，主要是写入、老化和轮转，相关的配置如[表2]所示。
 表2审计日志文件管理GUC参数 
| 配置项                         | 含义               | 默认值              |
|:---|:---|:---|
| audit_directory            | 审计日志文件的存储目录。    | pg_audit         |
| audit_resource_policy      | 审计日志的保存策略。        | on（表示使用空间配置策略） |
| audit_space_limit          | 审计日志文件占用的磁盘空间总量。 | 1GB             |
| audit_file_remain_time   | 审计日志文件的最小保存时间。    | 90               |
| audit_file_remain_threshold | 审计目录下审计日志文件的最大数量。 | 1048576        |
| audit_rotation_interval    | 创建一个新审计日志文件的时间间隔  | 1d（1440min）       |
| audit_rotation_size       | 审计日志文件的最大容量       | 10MB（10240kB）   |
   
支持通过时间优先或空间优先的方式对审计日志的保存进行管理，用户可以通过audit_resource_policy参数自行选择以哪种方式进行管理。默认情况下通过空间优先的方式进行管理。
与空间优先管理方式相关的参数有：
- audit_space_limit：审计日志文件占用的磁盘空间总量，若超过此值，则审计线程自动将现有最早的审计日志文件删除以保证空间满足要求。
- audit_rotation_size：单个审计日志文件的最大容量，当审计日志文件的大小达到该值时，审计线程生成一个新的审计日志文件继续记录。
- audit_file_remain_threshold：审计目录下审计日志文件个数最大值，超过此值，则审计线程自动将现有最早的审计日志文件删除以保证文件个数满足要求。
与时间优先管理方式相关的参数有：
- audit_file_remain_time：审计日志文件保留的时间，默认审计日志文件保留90天。
- audit_rotation_interval：创建一个新的审计日志文件的时间间隔，默认为1天。
审计日志管理在审计线程的主循环中实现，根据用户设置的策略，持续判断审计日志文件空间/时间是否满足策略，并做出相应的处理。
目前支持根据时间和空间策略进行审计日志的轮转和老化，仅有审计主线程会进行老化动作。日志的写入和轮转所有审计线程都会进行。
审计日志的轮转是指audit_rotation_interval到期或audit_rotation_size容量到配置参数大小，审计线程会创建新的审计日志文件并写入审计日志，同时修改审计index_file，添加新的文件索引。
审计日志的老化是指日志文件占用空间达到audit_space_limit配置值或审计日志保留时间达到audit_file_remain_time配置值或审计日志文件数量达到audit_file_remain_threshold上限值，审计线程会删除过期的审计日志文件，同时修改审计index_file，删除旧的文件索引。
审计记录查询接口为gs_query_audit函数，该函数为数据库内置函数，可供审计管理员直接调用，调用形式为：
```
SELECT * FROM gs_query_audit (timestamptz starttime,timestamptz endtime, audit_log);
```
入参为需要查询审计记录的起始时间和终止时间以及审计日志文件所在的物理路径（可选）。当不指定audit_log时，默认查看连接当前实例的审计日志信息。该函数通过遍历指定物理路径或当前实例的审计日志中指定时间段内的审计记录来实现查询功能，并且将结果按时间、操作类型、操作结果、用户ID、用户名、数据库、客户端信息、访问对象名称、细节信息、节点名称、线程ID、本地端口、远程端口等字段以表结构返回。审计管理员可以通过where子句对查询结果进行过滤，也可以通过ORDER BY子句对查询结果进行排序。
执行语句示例：查询2023-06-29 17:30:00到2023-06-29 17:44:00之间登录成功类型的审计记录，并将结果按照时间由早到晚顺序输出。
```
SELECT * FROM gs_query_audit('2023-06-29 17:30:00','2023-06-29 17:44:00') WHERE type like 'login_success' ORDER BY time;
```
审计记录的删除接口为gs_delete_audit函数，该函数为数据库内置函数，可供审计管理员直接调用，调用形式为：
```
SELECT * FROM gs_delete_audit (timestamptz starttime,timestamptz endtime);
```
入参为需要被删除审计记录的起始时间和终止时间。该函数通过调用gs_delete_audit将审计日志文件中，starttime与endtime之间的审计记录标记为AUDIT_TUPLE_DEAD，达到删除审计日志的效果，而不实际删除审计记录的物理数据。也即执行该函数，审计日志文件大小不会减少。
执行语句示例：删除2023-06-29 17:30:00到2023-06-29 17:44:00之间的审计记录。
```
SELECT * FROM gs_delete_audit('2023-06-29 17:30:00','2023-06-29 17:44:00');
```
**统一审计**
统一审计特性在数据库内部记录针对特定行为的审计策略，当用户执行的数据库语句关联到相关的审计策略后，生成对应的审计行为。通过这种内部有选择性执行有效的审计，来简化数据库管理，提高数据库生成审计数据的安全性。相比于传统审计，统一审计可以针对特定的Label对象或者特性的filter（用户、访问源IP、访问源APP）进行约束。
现阶段支持的审计操作类型（action列）及对象（object列）如[表3]所示，表中未列出的操作及对象暂时不支持。
 表3SQL类型支持操作和对象类型 
| 类型 | 支持操作和对象类型                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
|:---|:---|
| **PRIVILEGES**                  | 操作：ALL、ALTER、ANALYZE/VACUUM、COMMENT、CREATE、DROP、GRANT、REVOKE、SET、SHOW 对象：DATABASE、SCHEMA、FUNCTION/PROCEDURE、TRIGGER、TABLE、SEQUENCE、FOREIGN_SERVER、FOREIGN_TABLE、TABLESPACE、ROLE/USER/GROUP、INDEX、VIEW、DATA_SOURCE、WEAK PASSWORD DICTIONARY、AUDIT POLICY、MASKING POLICY、RESOURCE LABEL、MATERIALIZED VIEW/INCREMENTAL MATERIALIZED VIEW。 注：对不支持的对象类型统一审计日志均标记为UNKNOWN。 |
| **ACCESS**                       | 操作：ALL、COPY、DEALLOCATE、DELETE_P、EXECUTE、REINDEX、INSERT、PREPARE、SELECT、TRUNCATE、UPDATE。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
   
统一审计的实现主要包括三个部分：资源标签、统一审计策略维护和统一审计记录。
资源标签（LABEL）用于在数据库内部标记数据库资源，标签定义者指定目标资源并归为一组相关集合，这种有选择的"分类"可以简化数据库管理和相关安全策略的制定，降低策略配置的复杂性，提升执行效率。标签是基本对象集合，定义在该集合中的资源（表、视图、列等）将会被统一以集合的形式应用统一审计策略中，目前定义标签所支持的范围仅包括TABLE（不支持临时表）、COLUMN、SCHEMA、VIEW、FUNCTION。高斯数据库中提供标签定义接口，使数据管理者能够统一地对数据库资源进行集中管理。系统表gs_policy_label用于存储已配置的标签信息，系统视图gs_labels显示标签配置。
统一审计策略维护包括统一审计策略的增、删、改、查等操作，通过定义策略来生成审计线程需要记录的操作行为，是实现统一审计功能的重要配置信息。统一审计策略的主体信息均记录在[表4]中，每条记录对应一个设计策略。需要有系统管理员或安全策略管理员权限才可以访问此系统表。
 表4GS_AUDITING_POLICY 
| 名称        | 类型                           | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
|:---|:---|:---|
| oid          | oid                            | 行标识符（隐含属性，必须明确选择）。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| polname    | name                        | 策略名称，需要唯一，不可重复。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| polcomments | name                       | 策略描述字段，记录策略相关的描述信息，通过COMMENTS关键字体现。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| modifydate  | timestamp without time zone | 策略创建或修改的最新时间戳。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| polenabled | boolean                      | 用来表示策略启动开关。 - t（true）：表示策略启动。  - f（false）：表示策略没有启动。   |
   
跟policy紧密相关的access、privileges以及filter信息则分别记录在gs_auditing_policy_access、gs_auditing_policy_privileges以及gs_auditing_policy_filter系统表中。当策略信息发生变更时，通过policy的Oid信息进行关联，并相应地更新诸如privileges、access以及filter的信息。策略信息的更新通过Remove和Add两个步骤来实现，并记录至系统表。
关于privileges和access系统表信息部分，labelname表示当前语句的作用范围。modify_date则记录了最新一次发生变更的时间。详细流程请参考[图3]。
图3统一审计策略创建流程   
![](https://support.huaweicloud.com/bestpractice-gaussdb/figure/zh-cn_image_0000002590365978.png "点击放大")
统一审计的记录主要是对用户或者系统触发的可审计事件应用审计策略并生成统一审计记录。统一审计的记录线程通过Plugin的机制来实现，在接口函数中，依据获取的QueryDesc首先对作用的对象范围进行筛选，仅当统一审计策略中存在相关的对象时进行记录。然后根据当前QueryDesc中的语句进行与统一审计策略的行为进行匹配，并逐个地对不同的操作行为进行日志拼接。详细流程请参考[图4]。
图4统一审计记录流程   
![](https://support.huaweicloud.com/bestpractice-gaussdb/figure/zh-cn_image_0000002620645683.png "点击放大")
设计日志记录接口gs_audit_issue_syslog_message，日志的记录一共有三种方式：
- 通过调用send_sys_log接口将日志记录于rsyslog中，供数据库用户查看。
- 通过调用audit_report，写入审计二进制文件中。
- 如果当前已经对接了ElasticSearch系统，则通过curl传送审计数据，ES系统的IP和端口通过gaussdb.conf进行配置。
日志格式当前设计如下：
- 记录rsyslog的日志格式 Rsyslog日志：\|事件类型\|用户名\|触发客户端\|客户端IP\|操作类型\|策略ID\|执行结果\|
  
- 记录到审计日志文件格式
  统一审计日志记录到审计日志文件，通过系统函数gs_query_unified_audit查询返回结果字段说明如[表5]所示。
   表5统一审计日志参数 
  | 名称                  | 描述         |
  |:---|:---|
  | time                | 操作时间。     |
  | type               | 操作类型。      |
  | result             | 操作结果。     |
  | userid             | 用户ID。   |
  | username             | 执行操作的用户名。  |
  | database             | 数据库名称。     |
  | client_conninfo    | 客户端连接信息。  |
  | object_name        | 操作对象名称。    |
  | detail_info         | 执行操作详细信息。 |
  | node_name           | 节点名称。     |
  | thread_id           | 线程ID。     |
  | local_port          | 本地端口。    |
  | remote_port           | 远端端口。     |
  | policy_id          | 统一审计策略ID。 |
  | unified_audit_type  | 统一审计策略类型。 |
  | unified_audit_policy | 统一审计策略信息。 |
     
  
- 对接ElasticSearch系统日志格式 对接ES系统日志: \|数据类型\|执行结果\|执行用户\|数据库\|客户端信息\|执行语句\|节点信息\|线程\|端口\|时间\|ES系统信息。
  
 
#### 方案优势
审计功能通过策略定制化（统一审计）与参数精细化（传统审计）平衡了安全需求与系统性能，技术实现覆盖策略引擎、日志管理及实时分析。业务价值聚焦于合规举证、安全防护、运维效率、数据治理四大核心场景，尤其适合金融、政务等强监管行业。[表6]从各个角度对比了传统审计和统一审计。
 表6传统审计和统一审计对比 
| 维度     | 传统审计功能                                         | 统一审计功能                                 |
|:---|:---|:---|
| 技术架构  | 基于GUC参数开关                                     | 基于策略引擎（Resource Label标签化配置）           |
| 审计对象   | 全局或库级操作（无细粒度控制）                                | 表/列/用户/IP/操作类型级精准控制                 |
| 策略灵活性  | 低（预定义参数，如audit_login_logout）                  | 高（自定义策略，支持条件过滤）                      |
| 性能影响  | 506.1版本之前较高（全量审计时资源消耗大），506.1版本通过共享内存优化性能有较大提升 | 较低（按需审计，避免无效日志）                       |
| 权限要求    | SYSADMIN用户配置参数，AUDITADMIN查询权限                  | POLADMIN/SYSADMIN创建策略                  |
| 日志存储 | audit_directory配置的本地二进制文件                      | rsyslog配置的文件，或audit_directory配置的本地二进制文件 |
   
因此，用户可通过实际使用场景，选择合适的审计功能实现对数据访问和变更的可见性、可追溯性和控制力。
