PGAudit:Postgres 审计
PGAudit 扩展了 Postgres 内置的日志记录功能。它可以用来选择性地跟踪数据库内的活动。
这有助于你
- 合规性:满足法规要求的审计需求
- 安全性:检测可疑的数据库活动
- 故障排除:识别和修复数据库问题
启用扩展#
- 转到仪表板中的 数据库 页面。
- 在侧边栏中单击 扩展。
- 搜索
pgaudit并启用该扩展。
配置扩展#
PGAudit 可以配置为具有不同的精度级别。
PGAudit 日志记录精度
- 会话: 记录连接内的活动,例如 psql 连接。
- 用户: 记录特定数据库用户(例如,
anon或postgres)的活动。 - 全局: 记录整个数据库的活动。
- 对象: 记录与特定数据库对象(例如,auth.users 表)相关的事件。
虽然会话、用户和全局模式在精度上有所不同,但它们都被认为是 会话模式 的变体,并使用相同的输入类别进行配置。
会话模式类别#
这些模式可以监控数据库操作的预定义类别
| 类别 | 它记录的内容 | 描述 |
|---|---|---|
read | 数据检索 (SELECT, COPY) | 跟踪正在访问的数据。 |
write | 数据修改 (INSERT, DELETE, UPDATE, TRUNCATE, COPY) | 跟踪对数据库所做的更改。 |
function | FUNCTION、PROCEDURE 和 DO/END 块执行 | 跟踪例程/函数执行 |
role | 用户管理操作 (对用户和权限的 CREATE、DROP、ALTER) | 跟踪用户权限和访问权限的更改。 |
ddl | 模式更改 (CREATE、DROP、ALTER 语句) | 监控对数据库结构(表、索引等)的修改。 |
misc | 不太常见的命令 (FETCH, CHECKPOINT) | 捕获晦涩的操作,以便在需要时进行更深入的分析。 |
all | 以上所有内容 | 全面的日志记录,用于完整的审计跟踪。 |
以下是一个将 PGAudit 分配给监控特定类别的有限示例。
1-- log all CREATE, ALTER, and DROP events2... pgaudit.log = 'ddl';34-- log all CREATE, ALTER, DROP, and SELECT events5... pgaudit.log = 'read, ddl';67-- log nothing8... pgaudit.log = 'none';会话日志记录#
当你在会话环境中连接时,例如 psql 连接,你可以配置 PGAudit 以记录会话内发起的事件。
仪表板 是一个事务性环境,无法维持会话。
在会话中,默认情况下,PGAudit 不会记录任何内容
1-- returns 'none'2show pgaudit.log;在会话中,你可以 set pgaudit.log 变量来记录事件
1-- log CREATE, ALTER, and DROP events2set pgaudit.log = 'ddl';34-- log all CREATE, ALTER, DROP, and SELECT events5set pgaudit.log = 'read, ddl';67-- log nothing8set pgaudit.log = 'none';用户日志记录#
在某些情况下,你可能希望监控数据库用户的操作。例如,假设你将数据库连接到 Zapier 并为其创建了一个自定义角色
1create user "zapier" with password '<new password>';你可能希望记录由 zapier 发起的所有操作,可以使用以下命令来完成
1alter role "zapier" set pgaudit.log to 'all';要删除设置,请执行以下代码
1-- disables role's log2alter role "zapier" set pgaudit.log to 'none';34-- check to make sure the changes are finalized:5select6 rolname,7 rolconfig8from pg_roles9where rolname = 'zapier';10-- should return a rolconfig path with "pgaudit.log=none" present全局日志记录#
谨慎使用全局日志记录。它会生成许多日志,并使查找重要事件变得困难。尽可能使用会话、用户或对象日志记录来限制日志记录的范围。
以下 SQL 将配置 PGAudit 以记录与 postgres 角色关联的所有事件。由于它具有广泛的权限,这实际上会监控所有数据库活动。
1alter role "postgres" set pgaudit.log to 'all';要检查 postgres 角色是否正在审计,请执行以下命令
1select2 rolname,3 rolconfig4from pg_roles5where rolname = 'postgres';6-- should return a rolconfig path with "pgaudit.log=all" present要删除设置,请执行以下代码
1alter role "postgres" set pgaudit.log to 'none';对象日志记录#
要微调 PGAudit 将记录的对象事件,你必须创建一个权限有限的自定义数据库角色
1create role "some_audit_role" noinherit;没有其他 Postgres 用户可以假定或通过此角色登录。它仅存在于安全地定义 PGAudit 将记录的内容。
创建角色后,你可以通过将其分配给 pgaudit.role 变量来指示 PGAudit 进行日志记录
1alter role "postgres" set pgaudit.role to 'some_audit_role';然后,你可以将角色分配给仅监控批准的对象事件,例如包含特定表的 select 语句
1grant 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_role2alter role "postgres" set pgaudit.role to '';34-- view if pgaudit.role changed with the following command:5select6 rolname,7 rolconfig8from pg_roles9where rolname = 'postgres';10-- should return a rolconfig path with "pgaudit.role="解释审计日志#
PGAudit 旨在将日志存储为具有以下标题的 CSV 文件
参考自 PGAudit 官方文档
| 标题 | 描述 |
|---|---|
| AUDIT_TYPE | SESSION 或 OBJECT |
| STATEMENT_ID | 此会话的唯一语句 ID。即使某些语句未记录,也是顺序的。 |
| SUBSTATEMENT_ID | 主语句中每个子语句的顺序 ID。即使某些语句未记录,也是连续的。 |
| CLASS | ..., READ, ROLE (参见 pgaudit.log)。 |
| COMMAND | ..., ALTER TABLE, SELECT。 |
| OBJECT_TYPE | TABLE、INDEX、VIEW 等。适用于 SELECT、DML 和大多数 DDL 语句。 |
| OBJECT_NAME | 完全限定的对象名称(例如,public.account)。适用于 SELECT、DML 和大多数 DDL。 |
| STATEMENT | 在后端执行的语句。 |
| PARAMETER | 如果设置了 pgaudit.log_parameter,则此字段包含用引号分隔的 CSV 格式的语句参数,或者 <none>。否则,为 <not logged>。 |
由以下 create 语句生成的日志
1create table account (2 id int primary key,3 name text,4 description text5);在 仪表板的 Postgres 日志 中生成以下日志
1AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.account,create table account(2 id int,3 name text,4 description text5); <not logged>查找和过滤审计日志#
PGAudit 生成的日志可以在 Postgres 日志 中找到。要查找特定日志,可以使用日志资源管理器。以下是一个提取引用 CREATE TABLE 事件的日志的基本示例
1select2 cast(t.timestamp as datetime) as timestamp,3 event_message4from5 postgres_logs as t6 cross join unnest(metadata) as m7 cross join unnest(m.parsed) as p8where event_message like 'AUDIT%CREATE TABLE%'9order by timestamp desc10limit 100;实用示例#
监控 API 事件#
API 请求已经在 API Edge 网络 日志中记录。
要监控由 PostgREST API 角色发起的所有写入
1alter role "authenticator" set pgaudit.log to 'write';23-- 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 role2create role "auth_auditor" noinherit;34-- give role permission to observe relevant table events5grant select on auth.users to "auth_auditor";6grant delete on auth.users to "auth_auditor";78-- assign auth_auditor to pgaudit.role9alter role "postgres" set pgaudit.role to 'auth_auditor';使用上述代码,涉及读取或删除 auth.users 表的任何查询都将被记录。
最佳实践#
禁用过多的日志记录#
如果未仔细配置,PGAudit 会记录所有数据库事件,包括后台任务。这可能会在几个小时内生成大量不必要的日志。
解决此问题的第一步是确定 PGAudit 正在观察哪些数据库用户
1-- find all users monitored by pgaudit2select3 rolname,4 rolconfig5from pg_roles6where7 exists (8 select9 110 from UNNEST(rolconfig) as c11 where c like '%pgaudit.role%' or c like '%pgaudit.log%'12 );要阻止 PGAudit 监控有问题角色,你需要将他们的 pgaudit.log 值更改为 none 和 pgaudit.role 值更改为 空引号 ''
1-- Use to disable object level logging2 alter role "<role name>" set pgaudit.role to '';34 -- Use to disable global and user level logging5 alter role "<role name>" set pgaudit.log to 'none';常见问题解答#
使用 PGAudit 调试数据库函数#
从技术上讲,是的,但这不是最好的方法。最好查看我们的 函数调试指南。
下载数据库日志#
在 日志仪表板 中,你可以将日志下载为 CSV 文件。
记录观察到的表行#
默认情况下,PGAudit 记录查询,但不记录返回的行。你可以使用 pgaudit.log_rows 变量修改此行为
1--enable2alter role "postgres" set pgaudit.log_rows to 'on';34-- disable5alter role "postgres" set pgaudit.log_rows to 'off';除非你绝对 确定这是你的用例所必需的,否则你不应该这样做。它可能会将敏感值暴露给你的日志,而这些值理想情况下不应该被保留。此外,如果过度使用,可能会明显降低数据库性能。
记录函数参数#
我们目前不支持配置 pgaudit.log_parameter,因为它可能会记录加密列中的密钥,如果你正在使用 pgsodium 或 Vault。
你可以通过 此功能请求 投票,并提供你的用例,如果你希望取消此限制。
PGAudit 是否支持系统范围的配置?#
PGAudit 允许将设置应用于 3 个不同的数据库范围
| 范围 | 描述 | 配置文件/命令 |
|---|---|---|
| 系统 | 整个服务器 | ALTER SYSTEM 命令 |
| 数据库 | 特定数据库 | ALTER DATABASE 命令 |
| 角色 | 特定用户/角色 | ALTER ROLE 命令 |
Supabase 对文件系统和数据库变量的全权限有限制,这意味着 PGAudit 修改只能在角色级别进行。将 PGAudit 分配给 postgres 角色可以赋予其几乎完全的数据库可见性,因此在角色级别进行调整是配置数据库或系统级别的实用替代方案。
PGAudit 的 官方文档 侧重于系统和数据库级别的配置,但其文档也正式支持角色级别配置。