GaussDB(DWS)数据库安全守护者之审计日志
GaussDB(DWS)数据库安全守护者之审计日志
1.前言
适用版本:【8.1.0(及以上)】
数据库安全对数据库系统来说至关重要,而数据库审计日志是数据库安全的重要一环。GaussDB(DWS)将用户的所有操作写入审计日志。数据库安全管理员可以利用这些日志信息,重现导致数据库现状的一系列事件,找出非法操作的用户、时间和内容等。
2.背景简介
GaussDB(DWS)的审计日志通过日志文件来承载,默认目录为$GAUSSLOG/pg_audit。其中,存在多个审计文件和一个index_table,index_table中标识了现有的文件数量、文件大小、文件时间等详细信息,根据该内容可对审计日志进行老化、新增、分裂、查询索引等操作。经过了多次演进,审计日志中记录的内容已经日益全面,且具有很强的配置性。不同版本之间审计日志新增内容简介如下:
版本 | 实现或优化内容 | 字段数 | 备注 |
---|---|---|---|
8.0.0 | 最初版审计日志,支持审计DML、存储过程、copy操作 | 12 | 审计雏形,保证语句级记录 |
8.1.1 | 全面覆盖对各操作类型的审计,同时将命令执行失败场景也纳入系统审计 | 17 | 优化审计选项,场景覆盖全面 |
8.2.1 | DML操作和部分DDL操作中对于列的操作纳入审计,并记录返回行数 | 20 | 增加审计细粒度 |
3. 审计日志配置介绍
关于审计功能的配置,需要清楚审计开关的设计。审计的开关可配置性较多,灵活性较强,以下将介绍其中重要的开关选项。
3.1 审计日志记录配置
- audit_enabled:审计总开关,为布尔型开关,默认值为on,表示开启审计功能。审计总开关的开启和关闭也会被记录到审计日志中。
- audit_inner_tool:内部维护工具对应的审计开关,控制是否对来自内部维护工具的操作进行审计;为布尔型开关,默认值为off,表示关闭对来自内部维护工具的操作进行审计。内部维护工具包括:cm_agent、gs_clean、OM、gs_roach、gs_redis、wlm、gs_ctl、gs_rewind等。
- audit_operation_exec:执行成功操作对应的审计开关,支持对各操作类型进行配置,只有审计类型被配置,对应的操作执行成功时才会被记录到审计日志中。
- audit_operation_error:执行失败操作对应的审计开关,支持对各操作类型进行配置,只有审计类型被配置,对应的操作执行失败时才会被记录到审计日志中。
- audit_system_object:控制DDL操作对象的审计开关,数据库的DDL(CREATE,ALTER,DROP,表对象还包含TRUNCATE)操作的对象较多,通过该配置参数在操作对象维度上对审计进行更细粒度的控制。
- audit_object_details:控制object_details字段是否对语句中的表名、列名以及列使用的类型以json格式进行审计;其中字段记录的场景有:SELECT、DELETE、UPDATE、INSERT、MERGE、CREATE TABLE AS SELECT,GRANT、DECLARE CURSOR,其中对于执行失败的GRANT语句不予记录(8.2.1版本及以上)
- audit_object_name_format:控制审计日志object_name字段所显示的对象名的格式。其中选项为single时,表示object_name字段显示单个对象名,且为目标对象的名称。选项为all,表示object_name字段显示多个对象名称,并以json格式展示。(8.2.0版本及以上)
通常情况下,为保证审计日志中内容不会重复记录,默认仅会开启CN上的audit_enabled开关,从而使日志均记录在CN上,并且如果为非客户端下发语句而是从其他CN上下发的语句,也不做记录。
3.2 审计日志维护配置
- audit_directory:审计文件的存储目录。一个相对于数据目录data的路径,可自行指定,默认值为pg_audit。如果指定,也只能指定在$GAUSSLOG下
- audit_space_limit:审计文件占用的磁盘空间总量。取值范围为1024KB~1024GB
- audit_file_remain_threshold:审计目录下审计文件个数的最大值。默认值为1048576
- audit_data_format:审计日志文件的格式。当前仅支持二进制格式。
- audit_rotation_interval:指定创建一个新审计日志文件的时间间隔。当现在的时间减去上次创建一个审计日志的时间超过了此参数值时,服务器将生成一个新的审计日志文件。
- audit_rotation_size:指定审计日志文件的最大容量。当审计日志消息的总量超过此参数值时,服务器将生成一个新的审计日志文件。
- audit_resource_policy:控制审计日志的保存策略,以空间还是时间限制为优先策略。如果开启了以时间限制为优先,存储的审计日志所占磁盘空间达到audit_space_limit,此时也会对审计日志做老化操作。
- audit_file_remain_time:表示需记录审计日志的最短时间要求,该参数audit_resource_policy在为off时生效。
以上参数中,如果需要控制审计日志的存储空间和时间,最好使用audit_resource_policy、audit_space_limit和audit_file_remain_time参数进行控制。
**注:**9.1.0以前版本,audit_space_limit参数有大变小调整范围过大时,审计线程会一直执行老化操作,可能会导致业务语句无法处理和记录。因此建议该参数由大变小时每次调整10G。9.1.0版本对此做了优化,每次对于审计日志的老化最多老化10个,当在业务空闲期再对审计日志进行老化操作。
4 审计日志参数具体配置及记录范围
4.1审计开关audit_operation_exec的配置
audit_operation_exec的默认配置项为:login, logout, database_process, user_lock, grant_revoke, select, set, transaction, cursor
表示对用户登录、注销、数据库启动\停止\切换\恢复、用户锁定\解锁、权限授予\收回、SET操作、事务操作、游标操作的成功场景进行审计。
如需要增加审计操作,支持的配置项如下:
配置项 | 描述 |
---|---|
none | 表示未配置审计项,如果同时配置了其他任何审计项,则none失效 |
all | 表示对所有操作成功的场景进行审计。如果同时配置了其他任何审计项,则覆盖所有其他审计项的配置。需要注意,即使配置为all,也不表示对所有的DDL操作进行审计,仍然需要结合audit_system_object,对DDL操作的对象级别进行控制 |
login | 表示对用户登录成功的场景进行审计,默认配置 |
logout | 表示对用户退出进行审计,默认配置 |
database_process | 表示对数据库启动、停止、切换、恢复操作进行审计,默认配置 |
user_lock | 表示对用户锁定和解锁成功的场景进行审计,默认配置 |
grant_revoke | 表示对用户权限授予和回收成功的场景进行审计,默认配置 |
ddl | 表示对DDL操作成功的场景进行审计,因为DDL操作由会根据操作对象进行更细粒度控制,仍然沿用审计开关audit_system_object,即由audit_system_object控制对哪些对象的DDL操作进行审计(此处不配置ddl,只要配置了audit_system_object,审计也会生效) |
select | 表示对select操作成功的场景进行审计 |
copy | 表示对copy操作成功的场景进行审计 |
userfunc | 表示对用户自定义函数、存储过程、匿名块操作成功的场景进行审计 |
set | 表示对set操作成功的场景进行审计,默认配置 |
transaction | 表示对事务操作成功的场景进行审计 |
vacuum | 表示对vacuum操作成功的场景进行审计 |
analyze | 表示对analyze操作成功的场景进行审计 |
explain | 表示对explain操作成功的场景进行审计 |
specialfunc | 表示对特殊函数调用操作成功的场景进行审计,包括:pg_terminate_backend、pg_cancel_backend等强制终止业务函数 |
insert | 表示对insert操作成功的场景进行审计 |
update | 表示对update操作成功的场景进行审计 |
delete | 表示对delete操作成功的场景进行审计 |
merge | 表示对merge操作成功的场景进行审计 |
show | 表示对show操作成功的场景进行审计 |
checkpoint | 表示对checkpoint操作成功的场景进行审计 |
barrier | 表示对barrier操作成功的场景进行审计 |
cluster | 表示对cluster操作成功的场景进行审计 |
comment | 表示对comment操作成功的场景进行审计 |
cleanconn | 表示对clean connection操作成功的场景进行审计 |
prepare | 表示对PREPARE、EXECUTE、DEALLOCATE操作成功的场景进行审计 |
constraints | 表示对constraints操作成功的场景进行审计 |
cursor | 表示对游标操作成功的场景进行审计 |
4.2审计开关audit_operation_error的配置
audit_operation_error的默认配置项为:login表示对登录失败的场景进行审计;
支持的配置项如下:
配置项 | 描述 |
---|---|
none | 表示未配置审计项,如果同时配置了其他任何审计项,则none失效 |
syn_success | 表示同步audit_operation_exec的配置,即配置了某操作执行成功场景的审计,则对应的执行失败场景也记入审计。需注意,配置了syn_success后,仍可以继续配置其他操作执行失败场景的审计;如果audit_operation_exec配置为all,则所有的失败场景均记入审计;如果audit_operation_exec配置为none,则syn_success等同于none,即未配置审计项 |
parse | 表示对用户输入命令解析失败场景进行审计,包含等待命令超时的失败场景 |
login | 表示对用户登录失败的场景进行审计,默认配置 |
user_lock | 表示对用户锁定和解锁失败的场景进行审计 |
violation | 表示对用户访问存在越权的场景进行审计 |
grant_revoke | 表示对用户权限授予和回收失败的场景进行审计 |
ddl | 表示对DDL操作失败的场景进行审计,因为DDL操作由会根据操作对象进行更细粒度控制,仍然需要结合audit_system_object的配置情况,所以此处配置ddl后,将对audit_system_object指定类型的DDL失败场景进行审计 |
select | 表示对SELECT操作失败的场景进行审计 |
copy | 表示对COPY操作失败的场景进行审计 |
userfunc | 表示对用户自定义函数、存储过程、匿名块操作失败的场景进行审计 |
set | 表示对SET操作失败的场景进行审计 |
transaction | 表示对事务操作失败的场景进行审计 |
vacuum | 表示对VACUUM操作失败的场景进行审计 |
analyze | 表示对ANALYZE操作失败的场景进行审计 |
explain | 表示对EXPLAIN操作失败的场景进行审计 |
specialfunc | 表示对特殊函数调用操作失败的场景进行审计,包括:pg_terminate_backend、pg_cancel_backend等强制终止业务函数 |
insert | 表示对INSERT操作失败的场景进行审计 |
update | 表示对UPDATE操作失败的场景进行审计 |
delete | 表示对DELETE操作失败的场景进行审计 |
merge | 表示对MERGE操作失败的场景进行审计 |
show | 表示对SHOW操作失败的场景进行审计 |
checkpoint | 表示对CHECKPOINT操作失败的场景进行审计 |
barrier | 表示对BARRIER操作失败的场景进行审计 |
cluster | 表示对CLUSTER操作失败的场景进行审计 |
comment | 表示对COMMENT操作失败的场景进行审计 |
cleanconn | 表示对CLEAN CONNECTION操作失败的场景进行审计 |
prepare | 表示对PREPARE、EXECUTE、DEALLOCATE操作失败的场景进行审计 |
constraints | 表示对CONSTRAINTS操作失败的场景进行审计 |
cursor | 表示对游标操作失败的场景进行审计 |
blacklist | 表示对黑名单操作的执行失败进行审计 |
4.3审计开关audit_system_object的配置
audit_system_object的值由22个二进制位的组合求出,这22个二进制位分别代表GaussDB(DWS)的22类数据库对象。
每一位可以取值0或1,取值的含义为:
- 取值为0:表示不审计对应的数据库对象的DDL操作;
- 取值为1:表示审计对应的数据库对象的DDL操作;
例如:默认值为12295,对应的二进制为0011 0000 0000 0111(高位在前,低位在后),表示打开第0位、第1位、第2位、第12位、第13位对应对象的DDL操作的审计,具体对应DATABASE、SCHEMA、USER、DATA SOURCE、NODE GROUP这五个对象。
如需要增加审计table类型的DDL操作,可以通过以下方式进行设置:
-
table在第3位,对应的十进制为8
-
在原有12295的基础上加上8,得12303
-
将audit_system_object的值设置为12303即可,如下:
gs_guc reload -Z coordinator -Z datanode -N all -I all -c "audit_system_object = 12303"
这22个二进制位代表的具体含义如下:
二进制位 | 含义说明 |
---|---|
第0位 | 是否审计DATABASE对象的CREATE、DROP、ALTER操作 |
第1位 | 是否审计SCHEMA对象的CREATE、DROP、ALTER操作 |
第2位 | 是否审计USER对象的CREATE、DROP、ALTER操作 |
第3位 | 是否审计TABLE对象的CREATE、DROP、ALTER、TRUNCATE操作 |
第4位 | 是否审计INDEX对象的CREATE、DROP、ALTER操作 |
第5位 | 是否审计VIEW对象的CREATE、DROP、ALTER操作 |
第6位 | 是否审计TRIGGER对象的CREATE、DROP、ALTER操作 |
第7位 | 是否审计PROCEDURE/FUNCTION对象的CREATE、DROP、ALTER操作 |
第8位 | 是否审计TABLESPACE对象的CREATE、DROP、ALTER操作 |
第9位 | 是否审计RESOURCE POOL对象的CREATE、DROP、ALTER操作 |
第10位 | 是否审计WORKLOAD对象的CREATE、DROP、ALTER操作 |
第11位 | 是否审计SERVER FOR HADOOP对象的CREATE、DROP、ALTER操作 |
第12位 | 是否审计DATA SOURCE对象的CRAETE、DROP、ALTER操作 |
第13位 | 是否审计NODE GROUP对象的CREATE、DROP、ALTER操作 |
第14位 | 是否审计ROW LEVEL SECURITY对象的CREATE、DROP、ALTER操作 |
第15位 | 是否审计TYPE对象的CREATE、DROP、ALTER操作 |
第16位 | 是否审计TEXT SEARCH对象(CONFIGURATION和DICTIONARY)的CREATE、DROP、ALTER操作 |
第17位 | 是否审计DIRECTORY对象的CREATE、DROP、ALTER操作 |
第18位 | 是否审计SYNONYM对象的CREATE、DROP、ALTER操作 |
第19位 | 是否审计REDACTION POLICY对象的CREATE、DROP、ALTER操作 |
第20位 | 是否审计SEQUENCE对象的CREATE、DROP、ALTER操作 |
第21位 | 是否审计NODE对象的CREATE、DROP、ALTER操作 |
**注:**事务操作具有一定的特殊性,一个事务块涉及到多个语句的执行。如果在事务块进行中,对事务审计配置项(transaction)进行动态修改,将导致该事务块的审计记录不完整的问题。事务审计部分对这种情况按如下约定方式处理:
- 事务进行中事务配置项开启(无头有尾),不审计后续操作(无头有尾不记尾)
- 事务进行中事务配置项关闭(有头无尾),审计后续操作直到事务end(有头无尾不掉尾)
- 事务进行中,事务开关保持开启,但审计总开关开启(开总闸),因事务块的部分语句已经执行完毕,无法记录,所以不审计改事务块的后续操作(无头有尾不记尾)
- 事务进行中,事务开关保持开启,但审计总开关关闭(断总闸),因事务块部分操作已经被记录,为保证事务记录的完整性,审计线程将继续运行,直到该事务块的end被审计后审计线程才退出(有头无尾不掉尾)
- 事务进行中,事务开关保持开启,会话结束,记录事务回滚(未提交事务必回滚)
5. 审计日志查看
只有拥有AUDITADMIN属性的用户才可以查看审计记录。
审计日志需通过以下数据库接口
- pg_query_audit(timestamptz startime,timestamptz endtime, audit_log):查看当前CN的审计日志,可以指定需要读取审计日志的目录,默认从$GAUSSHOME/audit_directory中读取。
- pgxc_query_audit(timestamptz startime,timestamptz endtime):查看所有CN的审计日志
- pg_query_audit_details(timestamptz startime,timestamptz endtime, text node_mode):查看审计日志并将审计日志中的object_name和object_details字段由json格式解析出来;其中node_mode字段选项为current表示查询当前CN节点的审计日志,all表示查询所有CN节点的审计日志。
以上三个函数中,最开始的startime和endtime分别表示审计记录的开始时间和结束时间,满足审计条件的记录为startime ≤ 单条审计信息记录的结束时间 < endtime;
审计日志查看结果解析(821版本),各字段含义如下:
字段 | 含义 |
---|---|
begintime | 执行操作的开始时间(811版本新增) |
endtime | 执行操作的结束时间,查看审计日志是根据此时间判断的 |
operation_type | 操作类型(811版本新增) |
audit_type | 审计类型 |
result | 执行操作的结果 |
username | 执行操作的用户名 |
database | 数据库名称 |
client_conninfo | 客户端信息 |
object_name | 操作对象的名称 |
object_details | 对语句中的表名、列名以及列使用的类型以json格式进行审计(821版本新增) |
command_text | 执行操作的命令(811版本新增) |
detail_info | 执行操作详细信息 |
transaction_xid | 事务id(811版本新增) |
query_id | query id(811版本新增) |
node_name | 节点名称 |
thread_id | 线程id |
local_port | 本地节点 |
remote_port | 远端节点 |
result_rows | 执行成功时的返回行(821版本新增) |
error_code | 执行失败时的错误码(821版本新增) |
设置GUC参数,执行SELECT语句,查看审计日志记录,查询结果如下:
1.设置GUC参数
gs_guc reload -Z coordinator -Z datanode -N all -I all -c "audit_operation_exec='login, logout, database_process, user_lock, grant_revoke, set, transaction, cursor,select'"
gs_guc reload -Z coordinator -Z datanode -N all -I all -c "audit_object_details=on'"
gs_guc reload -Z coordinator -Z datanode -N all -I all -c "audit_object_name_format='all'"
2.执行select
postgres=# select * from t1 left join t2 on t1.a = t2.a;
a | b | c | a | b | c
---+---+---+---+---+---
1 | 1 | 1 | | |
(1 row)
3.查看审计日志记录
postgres=# select * from pg_query_audit(sysdate-0.1,sysdate) order by begintime desc, endtime desc limit 1;
-[ RECORD 3 ]---+-------------------------------------------------------------------------------------------------
begintime | 2024-01-23 10:34:56.972+08
endtime | 2024-01-23 10:34:56.985+08
operation_type | dml
audit_type | dml_action_select
result | ok
username | w00804127
database | postgres
client_conninfo | gsql@[local]
object_name | ["public.t1","public.t2"]
object_details | {"public.t1":[{"a":"22"},{"b":"2"},{"c":"2"}],"public.t2":[{"a":"22"},{"b":"2"},{"c":"2"}]}
command_text | select * from t1 left join t2 on t1.a = t2.a;
detail_info |
transaction_xid | 0
query_id | 72339069014638717
node_name | coordinator1
session_id | 1705976808.140052286080432.coordinator1
local_port | 37100
remote_port |
result_rows | 1
error_code |
postgres=# select * from pg_query_audit_details(sysdate-0.1,sysdate,'current') where command_text like 'select * from t1 left join%' and query_id = 72339069014638717 order by begintime desc, endtime desc limit 4;
-[ RECORD 1 ]---+----------------------------------------------
begintime | 2024-01-23 10:34:56.972+08
endtime | 2024-01-23 10:34:56.985+08
operation_type | dml
audit_type | dml_action_select
result | ok
username | w00804127
database | postgres
client_conninfo | gsql@[local]
transaction_xid | 0
query_id | 72339069014638717
node_name | coordinator1
session_id | 1705976808.140052286080432.coordinator1
local_port | 37100
remote_port |
object_name | public.t1
column_name | a
type_of_use | 22
use_type | Access,Conditional,Outer join
command_text | select * from t1 left join t2 on t1.a = t2.a;
-[ RECORD 2 ]---+----------------------------------------------
begintime | 2024-01-23 10:34:56.972+08
endtime | 2024-01-23 10:34:56.985+08
operation_type | dml
audit_type | dml_action_select
result | ok
username | w00804127
database | postgres
client_conninfo | gsql@[local]
transaction_xid | 0
query_id | 72339069014638717
node_name | coordinator1
session_id | 1705976808.140052286080432.coordinator1
local_port | 37100
remote_port |
object_name | public.t1
column_name | b
type_of_use | 2
use_type | Access
command_text | select * from t1 left join t2 on t1.a = t2.a;
-[ RECORD 3 ]---+----------------------------------------------
begintime | 2024-01-23 10:34:56.972+08
endtime | 2024-01-23 10:34:56.985+08
operation_type | dml
audit_type | dml_action_select
result | ok
username | w00804127
database | postgres
client_conninfo | gsql@[local]
transaction_xid | 0
query_id | 72339069014638717
node_name | coordinator1
session_id | 1705976808.140052286080432.coordinator1
local_port | 37100
remote_port |
object_name | public.t1
column_name | c
type_of_use | 2
use_type | Access
command_text | select * from t1 left join t2 on t1.a = t2.a;
-[ RECORD 4 ]---+----------------------------------------------
begintime | 2024-01-23 10:34:56.972+08
endtime | 2024-01-23 10:34:56.985+08
operation_type | dml
audit_type | dml_action_select
result | ok
username | w00804127
database | postgres
client_conninfo | gsql@[local]
transaction_xid | 0
query_id | 72339069014638717
node_name | coordinator1
session_id | 1705976808.140052286080432.coordinator1
local_port | 37100
remote_port |
object_name | public.t2
column_name | a
type_of_use | 22
use_type | Access,Conditional,Outer join
command_text | select * from t1 left join t2 on t1.a = t2.a;
6.总结
GaussDB(DWS)审计日志作为GaussDB(DWS)集群数据安全运维的重要支撑手段,记录着数据库的启动和停止、用户的登录和退出、各种各样的语句的执行情况、访问越权操作、事务操作等等,可以提供合规审计依据,支持审计数据转储以满足对审计数据保存期限的要求,可以记录、分析、追踪数据库安全事件,可以进行问题定位等。本文详细介绍了审计日志的版本发展历程,并总结了现有规格,标明了审计中常常遇到的问题及具体解决方案。
7.参考文献
- GaussDB(DWS)数据库安全守护者之审计日志 https://bbs.huaweicloud.com/blogs/253698
- 【如何保证你的DWS数据更安全】GaussDB(DWS) 8.2.1版本审计日志新增功能介绍 https://bbs.huaweicloud.com/blogs/407529
- 点赞
- 收藏
- 关注作者
评论(0)