数据库

PGAudit:Postgres 审计


PGAudit 扩展了 Postgres 内置的日志记录功能。它可以用来选择性地跟踪数据库内的活动。

这有助于你

  • 合规性:满足法规要求的审计需求
  • 安全性:检测可疑的数据库活动
  • 故障排除:识别和修复数据库问题

启用扩展#

  1. 转到仪表板中的 数据库 页面。
  2. 在侧边栏中单击 扩展
  3. 搜索 pgaudit 并启用该扩展。

配置扩展#

PGAudit 可以配置为具有不同的精度级别。

PGAudit 日志记录精度

  • 会话 记录连接内的活动,例如 psql 连接。
  • 用户 记录特定数据库用户(例如,anonpostgres)的活动。
  • 全局 记录整个数据库的活动。
  • 对象 记录与特定数据库对象(例如,auth.users 表)相关的事件。

虽然会话、用户和全局模式在精度上有所不同,但它们都被认为是 会话模式 的变体,并使用相同的输入类别进行配置。

会话模式类别#

这些模式可以监控数据库操作的预定义类别

类别它记录的内容描述
read数据检索 (SELECT, COPY)跟踪正在访问的数据。
write数据修改 (INSERT, DELETE, UPDATE, TRUNCATE, COPY)跟踪对数据库所做的更改。
functionFUNCTION、PROCEDURE 和 DO/END 块执行跟踪例程/函数执行
role用户管理操作 (对用户和权限的 CREATE、DROP、ALTER)跟踪用户权限和访问权限的更改。
ddl模式更改 (CREATE、DROP、ALTER 语句)监控对数据库结构(表、索引等)的修改。
misc不太常见的命令 (FETCH, CHECKPOINT)捕获晦涩的操作,以便在需要时进行更深入的分析。
all以上所有内容全面的日志记录,用于完整的审计跟踪。

以下是一个将 PGAudit 分配给监控特定类别的有限示例。

1
-- log all CREATE, ALTER, and DROP events
2
... pgaudit.log = 'ddl';
3
4
-- log all CREATE, ALTER, DROP, and SELECT events
5
... pgaudit.log = 'read, ddl';
6
7
-- log nothing
8
... pgaudit.log = 'none';

会话日志记录#

当你在会话环境中连接时,例如 psql 连接,你可以配置 PGAudit 以记录会话内发起的事件。

在会话中,默认情况下,PGAudit 不会记录任何内容

1
-- returns 'none'
2
show pgaudit.log;

在会话中,你可以 set pgaudit.log 变量来记录事件

1
-- log CREATE, ALTER, and DROP events
2
set pgaudit.log = 'ddl';
3
4
-- log all CREATE, ALTER, DROP, and SELECT events
5
set pgaudit.log = 'read, ddl';
6
7
-- log nothing
8
set pgaudit.log = 'none';

用户日志记录#

在某些情况下,你可能希望监控数据库用户的操作。例如,假设你将数据库连接到 Zapier 并为其创建了一个自定义角色

1
create user "zapier" with password '<new password>';

你可能希望记录由 zapier 发起的所有操作,可以使用以下命令来完成

1
alter role "zapier" set pgaudit.log to 'all';

要删除设置,请执行以下代码

1
-- disables role's log
2
alter role "zapier" set pgaudit.log to 'none';
3
4
-- check to make sure the changes are finalized:
5
select
6
rolname,
7
rolconfig
8
from pg_roles
9
where rolname = 'zapier';
10
-- should return a rolconfig path with "pgaudit.log=none" present

全局日志记录#

以下 SQL 将配置 PGAudit 以记录与 postgres 角色关联的所有事件。由于它具有广泛的权限,这实际上会监控所有数据库活动。

1
alter role "postgres" set pgaudit.log to 'all';

要检查 postgres 角色是否正在审计,请执行以下命令

1
select
2
rolname,
3
rolconfig
4
from pg_roles
5
where rolname = 'postgres';
6
-- should return a rolconfig path with "pgaudit.log=all" present

要删除设置,请执行以下代码

1
alter role "postgres" set pgaudit.log to 'none';

对象日志记录#

要微调 PGAudit 将记录的对象事件,你必须创建一个权限有限的自定义数据库角色

1
create role "some_audit_role" noinherit;

没有其他 Postgres 用户可以假定或通过此角色登录。它仅存在于安全地定义 PGAudit 将记录的内容。

创建角色后,你可以通过将其分配给 pgaudit.role 变量来指示 PGAudit 进行日志记录

1
alter role "postgres" set pgaudit.role to 'some_audit_role';

然后,你可以将角色分配给仅监控批准的对象事件,例如包含特定表的 select 语句

1
grant select on random_table to "some_audit_role";

授予此权限后,PGAudit 将记录所有引用 random_table 的 select 语句,无论 什么 实际发起了该事件。所有可分配的权限都可以在 Postgres 文档 中查看。

如果你不再想使用对象日志记录,你需要取消分配 pgaudit.role 变量

1
-- change pgaudit.role to no longer reference some_audit_role
2
alter role "postgres" set pgaudit.role to '';
3
4
-- view if pgaudit.role changed with the following command:
5
select
6
rolname,
7
rolconfig
8
from pg_roles
9
where rolname = 'postgres';
10
-- should return a rolconfig path with "pgaudit.role="

解释审计日志#

PGAudit 旨在将日志存储为具有以下标题的 CSV 文件

标题描述
AUDIT_TYPESESSION 或 OBJECT
STATEMENT_ID此会话的唯一语句 ID。即使某些语句未记录,也是顺序的。
SUBSTATEMENT_ID主语句中每个子语句的顺序 ID。即使某些语句未记录,也是连续的。
CLASS..., READ, ROLE (参见 pgaudit.log)。
COMMAND..., ALTER TABLE, SELECT。
OBJECT_TYPETABLE、INDEX、VIEW 等。适用于 SELECT、DML 和大多数 DDL 语句。
OBJECT_NAME完全限定的对象名称(例如,public.account)。适用于 SELECT、DML 和大多数 DDL。
STATEMENT在后端执行的语句。
PARAMETER如果设置了 pgaudit.log_parameter,则此字段包含用引号分隔的 CSV 格式的语句参数,或者 <none>。否则,为 <not logged>。

由以下 create 语句生成的日志

1
create table account (
2
id int primary key,
3
name text,
4
description text
5
);

仪表板的 Postgres 日志 中生成以下日志

1
AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.account,create table account(
2
id int,
3
name text,
4
description text
5
); <not logged>

查找和过滤审计日志#

PGAudit 生成的日志可以在 Postgres 日志 中找到。要查找特定日志,可以使用日志资源管理器。以下是一个提取引用 CREATE TABLE 事件的日志的基本示例

1
select
2
cast(t.timestamp as datetime) as timestamp,
3
event_message
4
from
5
postgres_logs as t
6
cross join unnest(metadata) as m
7
cross join unnest(m.parsed) as p
8
where event_message like 'AUDIT%CREATE TABLE%'
9
order by timestamp desc
10
limit 100;

实用示例#

监控 API 事件#

要监控由 PostgREST API 角色发起的所有写入

1
alter role "authenticator" set pgaudit.log to 'write';
2
3
-- the above is the practical equivalent to:
4
-- alter role "anon" set pgaudit.log TO 'write';
5
-- alter role "authenticated" set pgaudit.log TO 'write';
6
-- alter role "service_role" set pgaudit.log TO 'write';

监控 auth.users#

在最坏的情况下,如果特权角色的密码泄露,你可以使用 PGAudit 监控 auth.users 表是否被针对。应该指出的是,API 请求已经在 API Edge 网络 中监控,这更多的是关于提供关于数据库级别发生的事情的更清晰的信息。

应该以对象模式记录 auth.user,并且需要一个自定义角色

1
-- create logging role
2
create role "auth_auditor" noinherit;
3
4
-- give role permission to observe relevant table events
5
grant select on auth.users to "auth_auditor";
6
grant delete on auth.users to "auth_auditor";
7
8
-- assign auth_auditor to pgaudit.role
9
alter role "postgres" set pgaudit.role to 'auth_auditor';

使用上述代码,涉及读取或删除 auth.users 表的任何查询都将被记录。

最佳实践#

禁用过多的日志记录#

如果未仔细配置,PGAudit 会记录所有数据库事件,包括后台任务。这可能会在几个小时内生成大量不必要的日志。

解决此问题的第一步是确定 PGAudit 正在观察哪些数据库用户

1
-- find all users monitored by pgaudit
2
select
3
rolname,
4
rolconfig
5
from pg_roles
6
where
7
exists (
8
select
9
1
10
from UNNEST(rolconfig) as c
11
where c like '%pgaudit.role%' or c like '%pgaudit.log%'
12
);

要阻止 PGAudit 监控有问题角色,你需要将他们的 pgaudit.log 值更改为 nonepgaudit.role 值更改为 空引号 ''

1
-- Use to disable object level logging
2
alter role "<role name>" set pgaudit.role to '';
3
4
-- Use to disable global and user level logging
5
alter role "<role name>" set pgaudit.log to 'none';

常见问题解答#

使用 PGAudit 调试数据库函数#

从技术上讲,是的,但这不是最好的方法。最好查看我们的 函数调试指南

下载数据库日志#

日志仪表板 中,你可以将日志下载为 CSV 文件。

记录观察到的表行#

默认情况下,PGAudit 记录查询,但不记录返回的行。你可以使用 pgaudit.log_rows 变量修改此行为

1
--enable
2
alter role "postgres" set pgaudit.log_rows to 'on';
3
4
-- disable
5
alter role "postgres" set pgaudit.log_rows to 'off';

除非你绝对 确定这是你的用例所必需的,否则你不应该这样做。它可能会将敏感值暴露给你的日志,而这些值理想情况下不应该被保留。此外,如果过度使用,可能会明显降低数据库性能。

记录函数参数#

我们目前不支持配置 pgaudit.log_parameter,因为它可能会记录加密列中的密钥,如果你正在使用 pgsodiumVault

你可以通过 此功能请求 投票,并提供你的用例,如果你希望取消此限制。

PGAudit 是否支持系统范围的配置?#

PGAudit 允许将设置应用于 3 个不同的数据库范围

范围描述配置文件/命令
系统整个服务器ALTER SYSTEM 命令
数据库特定数据库ALTER DATABASE 命令
角色特定用户/角色ALTER ROLE 命令

Supabase 对文件系统和数据库变量的全权限有限制,这意味着 PGAudit 修改只能在角色级别进行。将 PGAudit 分配给 postgres 角色可以赋予其几乎完全的数据库可见性,因此在角色级别进行调整是配置数据库或系统级别的实用替代方案。

PGAudit 的 官方文档 侧重于系统和数据库级别的配置,但其文档也正式支持角色级别配置。

资源#