LightDB审计扩展(ltaudit)通过标准的LightDB日志记录功能提供详细的会话和/或对象审计日志记录。
ltaudit的目标是为LightDB用户提供能力,以产生经常需要遵守政府、金融或ISO认证的审计日志。
审计是对个人或组织账户的官方检查,通常由独立机构进行。ltaudit收集的信息称为审计跟踪或审计日志。本文档中使用术语审计日志。
标准日志记录设施可以提供基本的语句日志记录,使用 log_statement = all
。这对于监控和其他用途是可以接受的,但不能提供通常需要进行审核所需的详细级别。仅有一个对数据库执行的所有操作列表是不够的,还必须能够找到审计员感兴趣的特定语句。标准日志记录设施显示用户请求的内容,而ltaudit专注于数据库在满足请求时发生的详细信息。
例如,审计员可能希望验证特定表是否在已记录的维护窗口内创建。这似乎是grep的简单工作,但如果你被呈现出像这个(有意混淆)的例子,怎么办呢:
DO $$ BEGIN EXECUTE 'CREATE TABLE import' || 'ant_table (id INT)'; END $$;
标准日志记录将提供以下内容:
LOG: 语句: DO $$ BEGIN EXECUTE 'CREATE TABLE import' || 'ant_table (id INT)'; END $$;
在表是动态创建的情况下,似乎需要对代码有一些了解才能找到感兴趣的表。这并不理想,因为最好只搜索表名。这就是ltaudit的作用。对于相同的输入,它将在日志中产生以下输出:
AUDIT: SESSION,33,1,FUNCTION,DO,,,"DO $$ BEGIN EXECUTE 'CREATE TABLE import' || 'ant_table (id INT)'; END $$;" AUDIT: SESSION,33,2,DDL,CREATE TABLE,TABLE,public.important_table,CREATE TABLE important_table (id INT)
不仅记录了DO
块,而且子语句2包含了完整的CREATE TABLE
文本,带有语句类型、对象类型和完全合格的名称,以便进行简单的搜索。
在记录SELECT
和DML
语句时,ltaudit可以被配置为为语句中引用的每个关系记录一个单独的条目。不需要解析来查找所有涉及特定表的语句。实际上,目标是提供语句文本主要用于深入的取证,而不是对于审计必须。
根据设置,ltaudit可能会生成大量的日志记录。请仔细确定在您的环境中需要审计记录的内容,以避免记录过多。
例如,在OLAP环境中工作时,可能不明智地审计记录插入到大型事实表中。由于日志文件是以文本形式表示的,因此日志文件的大小可能是插入的实际数据大小的几倍。由于日志通常与操作系统一起存储,这可能会导致磁盘空间很快被耗尽。在无法将审计日志限制为某些表的情况下,请确保在测试时评估性能影响并在日志卷上分配足够的空间。这对于OLTP环境也可能是正确的。即使插入数量不高,审计日志记录的性能影响仍可能明显影响延迟。
为了限制记录SELECT
和DML
语句的关系数量,请考虑使用对象审计日志(请参见
对象审计
)。对象审计日志允许选择要记录的关系,从而减少总日志量。但是,当添加新关系时,必须将它们显式添加到对象审计日志中。在这种情况下,从日志记录中排除指定的表并包含所有其他表的程序化解决方案可能是一个好选择。
只有超级用户可以修改设置。允许普通用户更改其设置将使审计日志失去意义。
可以在全局范围(在lightdb.conf
或使用ALTER SYSTEM ... SET
)、在数据库级别(使用ALTER
DATABASE ... SET
)或在角色级别(使用ALTER ROLE ... SET
)指定设置。请注意,设置不通过正常角色继承进行继承,SET
ROLE
不会更改用户的ltaudit设置。这是角色系统的限制,而不是ltaudit固有的。
ltaudit扩展必须在
shared_preload_libraries中加载。否则,加载时会引发错误,不会发生审计日志记录。此外,在设置ltaudit.log
之前,必须调用CREATE EXTENSION ltaudit
。如果删除了ltaudit
扩展并需要重新创建,则必须首先取消设置
ltaudit.log
,否则会引发错误。
指定会话审计日志记录哪些语句类别。可能的值为:
读取:
当源是关系或查询时,SELECT
和COPY
。
写入:
当目标是关系时,INSERT
、UPDATE
、DELETE
、TRUNCATE
和COPY
。
函数:函数调用和DO
块。
角色:与角色和权限相关的语句:GRANT
、REVOKE
、
CREATE/ALTER/DROP ROLE
。
DDL:不包含在角色类中的所有DDL
。
其他:杂项命令,例如DISCARD
、FETCH
、
CHECKPOINT
、VACUUM
、SET
。
其他_SET:杂项SET
命令,例如SET ROLE
。
全部:包括上述所有。
可以使用逗号分隔的列表提供多个类别,并且可以通过在类别前面加上-
符号来减去类别(请参见
会话审计日志记录)。
默认值为none
。
指定在语句中的所有关系都在pg_catalog中时应启用会话日志记录。禁用此设置将减少像ltsql和LightDB Studio(for dbeaver)这样的工具从目录中查询产生的日志噪音。
默认值为on
。
指定日志消息是否对客户端进程(如psql)可见。通常应禁用此设置,但可能对调试或其他目的有用。
请注意,只有在ltaudit.log_client
为on
时才启用ltaudit.log_level
。
默认值为off
。
指定用于日志条目的日志级别(请参见
消息级别以获取有效的级别),但请注意,不允许使用ERROR
、
FATAL
和PANIC
。此设置用于回归测试,对于测试或其他用途,也可能对最终用户有用。
请注意,只有在ltaudit.log_client
为on
时才启用ltaudit.log_level
;否则将使用默认值。
默认值为log
。
指定审计日志记录应包括与语句一起传递的参数。当参数存在时,它们将在语句文本之后以CSV
格式包含在内。
默认值为off
。
指定会话审计日志记录是否应为在SELECT
或DML
语句中引用的每个关系(TABLE
、VIEW
等)创建单独的日志条目。这是一种有用的快捷方式,可在不使用对象审计日志记录的情况下进行详尽的日志记录。
默认值为off
。
指定日志记录是否将语句文本和参数与语句/子语句组合的第一个日志条目或每个条目一起记录。禁用此设置将导致日志记录不太详细,但可能会使确定生成日志条目的语句更加困难,尽管语句/子语句对以及进程ID应足以标识先前记录的语句文本。
默认值为off
。
指定用于对象审计日志记录的主角色。可以通过将它们授予主角色来定义多个审计角色。这允许多个组负责审核日志记录的不同方面。
没有默认值。
指定application_name的黑名单,不记录指定客户端的审计日志。可以使用逗号分隔的列表提供多个客户端名。
没有默认值。
指定application_name的白名单,只记录指定客户端的审计日志。可以使用逗号分隔的列表提供多个客户端名。
没有默认值。
指定对象的黑名单,不记录指定对象的审计日志。
对象的配置格式必须是schema.relation_name
,
可以使用逗号分隔的列表提供多个对象,
可以使用*
替换schema
和relation_name
,表示所有。
没有默认值。
指定对象的白名单,只记录指定对象的审计日志。
对象的配置格式必须是schema.relation_name
,
可以使用逗号分隔的列表提供多个对象,
可以使用*
替换schema
和relation_name
,表示所有。
没有默认值。
会话审计日志记录提供有关用户在后端执行的所有语句的详细日志记录。
通过设置 ltaudit.log启用会话日志记录。
启用所有DML
和DDL
的会话日志记录,并记录DML
语句中的所有关系:
set ltaudit.log = 'write, ddl'; set ltaudit.log_relation = on;
启用除MISC
之外的所有命令的会话日志记录,并将审计日志消息提升为NOTICE
:
set ltaudit.log = 'all, -misc'; set ltaudit.log_level = notice;
在此示例中,会话审计日志记录用于记录DDL
和SELECT
语句。请注意,插入语句未被记录,因为未启用WRITE
类。
SQL:
set ltaudit.log = 'read, ddl'; create table account ( id int, name text, password text, description text ); insert into account (id, name, password, description) values (1, 'user1', 'HASH1', 'blah, blah'); select * from account;
日志输出:
AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.account,create table account ( id int, name text, password text, description text );,<not logged> AUDIT: SESSION,2,1,READ,SELECT,,,select * from account,,<not logged>
对象审计日志记录记录影响特定关系的语句。仅支持SELECT
、INSERT
、UPDATE
和
DELETE
命令,TRUNCATE
不包括在对象审计日志记录中。
对象审计日志记录旨在作为ltaudit.log = 'read, write'
的细粒度替代。因此,可能没有必要将它们与其他设置同时使用,但一个可能的情况是使用会话日志记录来捕获每个语句,然后使用对象日志记录来获取有关特定关系的更多详细信息。
对象级审计日志记录通过角色系统实现。设置
ltaudit.role定义用于审计日志记录的角色。当审计角色具有执行命令的权限或从其他角色继承权限时,关系(TABLE
、VIEW
等)将被记录审计日志。这使您可以在任何上下文中实际上拥有多个审计角色,即使只有一个主角色。
将
ltaudit.role设置为auditor
,并授予account
表的
SELECT
和DELETE
权限。现在,对account
表的任何SELECT
或DELETE
语句都将被记录日志:
set ltaudit.role = 'auditor'; grant select, delete on public.account to auditor;
本示例使用对象审计日志记录来说明如何对SELECT
和DML
语句进行细粒度的日志记录。请注意,对account
表的日志记录受列级权限控制,而对account_role_map
表的日志记录则受表级权限控制。
SQL:
set ltaudit.role = 'auditor'; create table account ( id int, name text, password text, description text ); grant select (password) on public.account to auditor; select id, name from account; select password from account; grant update (name, password) on public.account to auditor; update account set description = 'yada, yada'; update account set password = 'HASH2'; create table account_role_map ( account_id int, role_id int ); grant select on public.account_role_map to auditor; select account.password, account_role_map.role_id from account inner join account_role_map on account.id = account_role_map.account_id
日志输出:
AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.account,select password from account,<not logged> AUDIT: OBJECT,2,1,WRITE,UPDATE,TABLE,public.account,update account set password = 'HASH2',<not logged> AUDIT: OBJECT,3,1,READ,SELECT,TABLE,public.account,select account.password, account_role_map.role_id from account inner join account_role_map on account.id = account_role_map.account_id,<not logged> AUDIT: OBJECT,3,1,READ,SELECT,TABLE,public.account_role_map,select account.password, account_role_map.role_id from account inner join account_role_map on account.id = account_role_map.account_id,<not logged>
审计条目将被写入标准日志记录设施,并以逗号分隔格式包含以下列。仅当删除每个日志条目的日志行前缀部分时,输出才符合CSV格式。
AUDIT_TYPE - SESSION
或OBJECT
。
STATEMENT_ID - 此会话的唯一语句ID。每个语句ID表示一个后端调用。即使某些语句未记录,语句ID也是连续的。当记录了多个关系时,可能会有多个与语句ID相关的条目。
SUBSTATEMENT_ID - 主语句内每个子语句的顺序ID。例如,在查询中调用函数。即使某些子语句未记录,子语句ID也是连续的。当记录了多个关系时,可能会有多个与子语句ID相关的条目。
CLASS - 例如:READ
,ROLE
(请参见
ltaudit.log)。
COMMAND - 例如:ALTER TABLE
,SELECT
。
OBJECT_TYPE - TABLE
,INDEX
,
VIEW
等。可用于SELECT
,DML
和大多数DDL
语句。
OBJECT_NAME - 完全限定的对象名称(例如public.account)。可用于SELECT
,
DML
和大多数DDL
语句。
STATEMENT - 在后端执行的语句。
PARAMETER - 如果设置了ltaudit.log_parameter
,则此字段将包含用引号括起来的CSV格式的语句参数,如果没有参数,则为<none>
。否则,该字段为<未记录>
。
使用
log_line_prefix添加满足您的审计日志要求所需的任何其他字段。典型的日志行前缀可能是'%m %u %d [%p]: '
,它将为每个审计日志提供日期/时间、用户名、数据库名称和进程ID。
对象重命名将在它们被重命名的名称下记录。例如,重命名表将产生以下结果:
ALTER TABLE test RENAME TO test2; AUDIT: SESSION,36,1,DDL,ALTER TABLE,TABLE,public.test2,ALTER TABLE test RENAME TO test2,<not logged>
可能会将一个命令记录多次。例如,在创建表时指定主键时,主键的索引将独立记录,并且在创建条目下将为索引进行其他审计日志记录。但是,多个条目将包含在一个语句ID中。
自动清理(Autovacuum)和自动分析(Autoanalyze)不会记录日志。
在事务进入中止状态之后执行的语句将不会被审计日志记录。但是,导致错误的语句以及在中止事务中执行的任何后续语句将由标准日志记录设施记录为错误。