安全审计

数据库审计是对数据库操作进行细粒度审计的合规性管理,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断。它通过对用户访问数据库行为进行记录、分析和汇报,可以用来帮助用户事后生成合规报告、事故追根溯源,同时加强内外部数据库网络行为记录,提高数据资产安全。

YMatrix 审计方式可以通过log_XXX 和 pgAudit 两种方式进行:

log_XXX

log_xxx 系列参数用于配置日志记录的行为,帮助监控和调试数据库的运行情况。将所有的数据库操作行为记录到数据库运行日志里,然后分析日志进行危险行为预警处理。

配置参数

logging_collector     --是否开启日志收集开关,默认off,推荐on
log_destination       --日志记录类型,默认是stderr,只记录错误输出,推荐csvlog,总共包含:stderr, csvlog, syslog, and eventlog,
log_directory          --日志路径,默认是$PGDATA/pg_log, 
log_filename            --日志名称,默认是postgresql-%Y-%m-%d_%H%M%S.log
log_file_mode           --日志文件类型,默认为0600
log_truncate_on_rotation  --默认为off,设置为on的话,文件内容覆盖方式:off后面附加,on:清空再加
log_rotation_age      --保留单个文件的最大时长,默认是1d,也有1h,1min,1s
log_rotation_size       --保留单个文件的最大尺寸,默认是10MB
log_error_verbosity    --默认为default,verbose表示冗长的
log_connections    --用户session登陆时是否写入日志,默认off,推荐为on
log_disconnections --用户session退出时是否写入日志,默认off,推荐为on
log_statement    --记录用户登陆数据库后的各种操作 
    none,即不记录
    ddl(记录create,drop和alter)
    mod(记录ddl+insert,delete,update和truncate)
    all(mod+select)
log_min_duration_statement = 2s   --记录超过2秒的SQL
log_checkpoints = on
log_lock_waits = on
deadlock_timeout = 1s

配置示例

以下是一个配置示例,将这些参数添加到 postgresql.conf 文件中:

注意!
修改 postgresql.conf 文件后,需要重启 YMatrix 服务以使配置生效。

logging_collector = on
log_directory = 'stderr'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_rotation_size = 10MB
log_truncate_on_rotation = off

log_statement = 'all'
log_min_duration_statement = 100

log_connections = on
log_disconnections = on
log_lock_waits = on

pgAudit

引入 pgAudit 扩展进行更加精细的审计。pgAudit 会提供会话和对象两种审计模式。数据库会存在如下可配置参数。

配置参数

pgaudit.log     -- 指定会话审计日志记录将记录哪些类语句,默认 none。取值包括如下:
    READ (select, copy from)
    WRITE (insert, update, delete, truncate, copy to)
    FUNCTION (function calls and DO blocks)
    ROLE (grant, revoke, create/alter/drop role)
    DDL (all DDL except those in ROLE)
    MISC (discard, fetch, checkpoint, vacuum)
    MISC_SET (Miscellaneous SET commands, e.g. SET ROLE.)
    ALL (Include all of the above.)
pgaudit.log_catalog    -- 控制是否审计 pg_catalog 模式下的表的变动,默认 on。
pgaudit.log_client     -- 是否记录客户端的应用程序类型,默认 off。
pgaudit.log_level      -- 审计日志记录的记录级别,默认 log。
pgaudit.log_parameter  -- 控制审计日志是否记录会话级别的参数设置行为,默认 off。
pgaudit.log_parameter_max_size  -- 审计参数设置的最大值,单位是byte,默认 0。
pgaudit.log_relation   -- 控制会话审计时,是否为每个表都记录一条日志,默认 off。
pgaudit.log_rows       -- 控制是否记录语句的影响记录数,默认 off。   
pgaudit.log_statement  -- 控制是否记录语句信息,默认 on。
pgaudit.log_statement_once     -- 控制一组语句执行是否只在第一个审计条目里记录明细信息,默认 off。
pgaudit.role           -- 指定用于对象审计日志记录的主角色,无默认值

配置示例

会话审计 会话审计日志记录提供用户在后端执行的所有语句的详细日志。使用 pgaudit.log 设置启用会话日志记录。

-- 1. 配置会话审计
set pgaudit.log = 'read, ddl'; --记录读操作和 DDL 操作

-- 2.执行操作 
-- 2.1 创建表
create table account
(
    id int,
    name text,
    password text,
    description text
);

-- 2.2 插入数据
insert into account (id, name, password, description)
             values (1, 'user1', 'HASH1', 'blah, blah');

-- 2.3查询数据
select *
    from account;

-- 3.查看日志
-- 由于未启用 WRITE 类,因此未记录插入语句
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 命令。对象级审计日志记录是通过角色系统实现的。pgaudit.role 设置定义了将用于审计日志记录的角色。当审计角色对执行的命令具有权限或从另一个角色继承权限时,将对关系(TABLE、VIEW等)进行审计日志记录。

在本示例中,这个例子展示了如何通过 pgAudit 扩展记录特定角色(auditor)对特定表和列的操作日志。请注意,account 表上的日志记录由列级权限控制,而 account_role_map 表上的日志记录是表级的。

-- 1. 配置对象审计
-- 设置审计角色
set pgaudit.role = 'auditor';

-- 2.执行操作
-- 2.1 创建表
create table account
(
    id int,
    name text,
    password text,
    description text
);

-- 2.2 授予审计角色对表的权限
grant select (password)
   on public.account
   to auditor;

-- 2.3 查询数据
select id, name
  from account;

select password
  from account;

-- 2.4 授予审计角色更新权限
grant update (name, password)
   on public.account
   to auditor;

-- 2.5 更新数据
update account
   set description = 'yada, yada';

update account
   set password = 'HASH2';

-- 2.6 创建关联表
create table account_role_map
(
    account_id int,
    role_id int
);

-- 2.7 授予查询权限
grant select
   on public.account_role_map
   to auditor;

-- 2.8 联合查询
select account.password,
       account_role_map.role_id
  from account
       inner join account_role_map
            on account.id = account_role_map.account_id

-- 3.日志输出
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>

对象审计与会话审计 对象审计日志记录旨在成为 pgaudit.log='read,write' 的更细粒度的替代品,将它们简单结合使用可能没有意义,但一种可能的情况是使用会话日志记录来捕获每个语句,然后使用对象日志记录来补充以获取有关特定关系的更多详细信息。

-- 1.配置会话会话审计
SET pgaudit.log = 'write, ddl'; -- 记录写操作和DDL操作
SET pgaudit.log_relation = on; -- 启用对象级别的审计

-- 2. 配置对象审计
GRANT SELECT, DELETE ON public.account TO auditor; -- 授予审计角色对表的权限
SET pgaudit.role = 'auditor'; -- 设置审计角色

-- 3.执行操作
-- 3.1创建表
CREATE TABLE account (
    id INT PRIMARY KEY,
    name TEXT,
    password TEXT,
    description TEXT
);

-- 3.2 插入数据
INSERT INTO account (id, name, password, description)
        VALUES (1, 'user1', 'HASH1', 'blah, blah');

-- 3.3 查询数据
SELECT * FROM account;

-- 3.4 删除数据
DELETE FROM account
WHERE id = 1;

-- 4. 查看日志
AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.account,CREATE TABLE account (
    id INT PRIMARY KEY,
    name TEXT,
    password TEXT,
    description TEXT
);,<not logged>
AUDIT: SESSION,2,1,WRITE,INSERT,TABLE,public.account,INSERT INTO account (id, name, password, description)
    VALUES (1, 'user1', 'HASH1', 'blah, blah');,<not logged>
AUDIT: OBJECT,3,1,READ,SELECT,TABLE,public.account,SELECT * 
    FROM account;,<not logged>
AUDIT: SESSION,4,1,WRITE,DELETE,TABLE,public.account,DELETE 
    FROM account WHERE id = 1;<not logged>
AUDIT: OBJECT,4,1,WRITE,DELETE,TABLE,public.account,DELETE 
    FROM account WHERE id = 1;<not logged>