

# 使用 pgAudit 记录数据库活动
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit"></a>

金融机构、政府机构和许多行业需要保留*审计日志*以满足监管要求。通过将 PostgreSQL Audit 扩展（pgAudit）与 RDS for PostgreSQL 数据库实例结合使用，您可以捕获审计人员通常需要或满足监管要求的详细记录。例如，您可以设置 pgAudit 扩展来跟踪对特定数据库和表所做的更改，记录进行更改的用户以及许多其他详细信息。

pgAudit 扩展通过更详细地扩展日志消息，进一步构建原生 PostgreSQL 日志记录基础设施的功能。换句话说，您将使用与查看任何日志消息相同的方法来查看审计日志。有关 PostgreSQL 日志记录的更多信息，请参阅 [RDS for PostgreSQL 数据库日志文件](USER_LogAccess.Concepts.PostgreSQL.md)。

pgAudit 扩展会编辑日志中的敏感数据，例如明文密码。如果您的 RDS for PostgreSQL 数据库实例配置为记录数据操作语言（DML）语句（详情请见[为您的 RDS for PostgreSQL 数据库实例开启查询日志记录](USER_LogAccess.Concepts.PostgreSQL.Query_Logging.md)），则可以使用 PostgreSQL Audit 扩展来避免明文密码问题。

您可以在数据库实例上配置具有高度明确性的审计。您可以审计所有数据库和所有用户。或者，您可以选择仅审计某些数据库、用户和其他对象。您也可以明确排除对某些用户和数据库进行审计。有关更多信息，请参阅 [从审计日志记录中排除用户或数据库](Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db.md)。

考虑到可以捕获的详细信息量，我们建议您在使用 pgAudit 时监控存储消耗。

所有可用的 RDS for PostgreSQL 版本。有关可用 RDS for PostgreSQL 版本支持的 pgAudit 版本的列表，请参阅《Amazon RDS for PostgreSQL 版本注释》**中的 [Amazon RDS for PostgreSQL 的扩展版本](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)。

**Topics**
+ [设置 pgAudit 扩展](Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.md)
+ [审计数据库对象](Appendix.PostgreSQL.CommonDBATasks.pgaudit.auditing.md)
+ [从审计日志记录中排除用户或数据库](Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db.md)
+ [pgAudit 扩展的参考](Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.md)

# 设置 pgAudit 扩展
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup"></a>

要在 RDS for PostgreSQL 数据库实例 上设置 pgAudit 扩展，首先要将 pgAudit 添加到 RDS for PostgreSQL 数据库实例的自定义数据库参数组 上的共享库中。有关创建自定义数据库参数组的信息，请参阅 [Amazon RDS 的参数组](USER_WorkingWithParamGroups.md)。接下来，安装 pgAudit 扩展。最后，指定要审计的数据库和对象。本部分中的过程向您展示如何操作。您可以使用 AWS 管理控制台或 AWS CLI。

您必须拥有 `rds_superuser` 角色的权限才能执行所有这些任务。

以下步骤假设您的 RDS for PostgreSQL 数据库实例与自定义 数据库参数组相关联。

## 控制台
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.CON"></a>

**设置 pgAudit 扩展**

1. 登录 AWS 管理控制台 并通过以下网址打开 Amazon RDS 控制台：[https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)。

1. 在导航窗格中，选择 RDS for PostgreSQL 数据库实例。

1. 打开 的**配置**选项卡。RDS for PostgreSQL 数据库实例的 Configuration（配置）选项卡。在实例详细信息中，找到 **Parameter group**（参数组）链接。

1. 选择此链接以打开与您的 RDS for PostgreSQL 数据库实例关联的自定义参数。

1. 在 **Parameters**（参数）搜索字段中，键入 `shared_pre` 以查找 `shared_preload_libraries` 参数。

1. 选择 **Edit parameters**（编辑参数）以访问属性值。

1. 将 `pgaudit` 添加到 **Values**（值）字段的列表中。使用逗号分隔值列表中的项目。  
![\[添加了 pgAudit 的 shared_preload_libaries 参数的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pgaudit.png)

1. 重启 RDS for PostgreSQL 数据库实例，以使对 `shared_preload_libraries` 参数的更改生效。

1. 当实例可用时，请验证 pgAudit 是否已初始化。使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，然后运行以下命令。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

1. 初始化 pgAudit 后，您现在可以创建扩展了。您需要在初始化库后创建扩展，因为 `pgaudit` 扩展会为审计数据定义语言（DDL）语句安装事件触发器。

   ```
   CREATE EXTENSION pgaudit;
   ```

1. 关闭 `psql` 会话。

   ```
   labdb=> \q
   ```

1. 登录 AWS 管理控制台 并通过以下网址打开 Amazon RDS 控制台：[https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)。

1. 在列表中找到 `pgaudit.log` 参数并设置为适合您的使用案例的值。例如，将 `pgaudit.log` 参数设置为 `write`（如下图所示），可以捕获对日志的插入、更新、删除和其他一些类型的更改。  
![\[带有设置的 pgaudit.log 参数的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/rpg_set_pgaudit-log-level.png)

   还可以为 `pgaudit.log` 参数选择以下值之一。
   + none – 这是默认值。不记录任何数据库更改。
   + all – 记录所有内容（read、write、function、role、ddl、misc）。
   + ddl – 记录所有数据定义语言（DDL）语句（不包括在 `ROLE` 类中）。
   + function – 记录函数调用和 `DO` 块。
   + misc – 记录其他命令，例如 `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM` 和 `SET`。
   + read –当源为关系（例如表）或查询时记录 `SELECT` 和 `COPY`。
   + role – 记录与角色和权限相关的语句，例如 `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE` 和 `DROP ROLE`。
   + write – 当目标为关系（表）时，记录 `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE` 和 `COPY`。

1. 选择 **Save changes**（保存更改）。

1. 通过以下网址打开 Amazon RDS 控制台：[https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)。

1. 从“数据库”列表中选择 RDS for PostgreSQL 数据库实例。

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.CLI"></a>

**设置 pgAudit**

要使用 AWS CLI 设置 pgAudit，您可以调用 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) 操作来修改自定义参数组中的审计日志参数，如以下过程所示。

1. 使用以下 AWS CLI 命令向 `shared_preload_libraries` 参数中添加 `pgaudit`。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=pgaudit,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例，以便初始化 pgaudit 库。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 当实例可用时，您可以验证 `pgaudit` 是否已初始化。使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，然后运行以下命令。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

   初始化 pgAudit 后，您现在可以创建扩展了。

   ```
   CREATE EXTENSION pgaudit;
   ```

1. 关闭 `psql` 会话以便您可以使用 AWS CLI。

   ```
   labdb=> \q
   ```

1. 使用以下 AWS CLI 命令指定要由会话审计日志记录所记录的语句类别。该示例将 `pgaudit.log` 参数设置为 `write`，用于捕获对日志的插入、更新和删除。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=pgaudit.log,ParameterValue=write,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

   还可以为 `pgaudit.log` 参数选择以下值之一。
   + none – 这是默认值。不记录任何数据库更改。
   + all – 记录所有内容（read、write、function、role、ddl、misc）。
   + ddl – 记录所有数据定义语言（DDL）语句（不包括在 `ROLE` 类中）。
   + function – 记录函数调用和 `DO` 块。
   + misc – 记录其他命令，例如 `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM` 和 `SET`。
   + read –当源为关系（例如表）或查询时记录 `SELECT` 和 `COPY`。
   + role – 记录与角色和权限相关的语句，例如 `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE` 和 `DROP ROLE`。
   + write – 当目标为关系（表）时，记录 `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE` 和 `COPY`。

   使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

# 审计数据库对象
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.auditing"></a>

在 RDS for PostgreSQL 数据库实例上设置 pgAudit 并根据您的要求进行配置后，将在 PostgreSQL 日志中捕获更多详细信息。例如，虽然默认 PostgreSQL 日志记录配置标识数据库表中发生更改的日期和时间，但使用 pgAudit 扩展后，日志条目可以包括模式、进行更改的用户和其他详细信息，具体取决于扩展参数的配置方式。您可以设置审计以通过以下方法跟踪更改。
+ 对于每个会话，按用户进行跟踪。对于会话级别，您可以捕获完全限定的命令文本。
+ 对于每个对象，按用户和数据库进行跟踪。

当您在系统上创建 `rds_pgaudit` 角色，然后将此角色添加到自定义参数组中的 `pgaudit.role` 参数时，将激活对象审计功能。默认情况下，`pgaudit.role` 参数处于未设置状态，唯一允许的值是 `rds_pgaudit`。以下步骤假设 `pgaudit` 已初始化，并且您已按照[设置 pgAudit 扩展](Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.md)中的步骤创建了 `pgaudit` 扩展。

![\[设置 pgAudit 后 PostgreSQL 日志文件的图像。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/pgaudit-log-example.png)


如本示例所示，“LOG: AUDIT: SESSION”行提供了有关表及其架构的信息以及其他详细信息。

**设置对象审计**

1. 使用 `psql` 连接到 RDS for PostgreSQL 数据库实例。

   ```
   psql --host=your-instance-name.aws-region.rds.amazonaws.com --port=5432 --username=postgrespostgres --password --dbname=labdb
   ```

1. 使用以下命令创建名为 `rds_pgaudit` 的数据库角色。

   ```
   labdb=> CREATE ROLE rds_pgaudit;
   CREATE ROLE
   labdb=>
   ```

1. 关闭 `psql` 会话。

   ```
   labdb=> \q
   ```

   在接下来的几步中，使用 AWS CLI 修改自定义参数组中的审计日志参数。

1. 使用以下 AWS CLI 命令将 `pgaudit.role` 参数设置为 `rds_pgaudit`。默认情况下，此参数为空，`rds_pgaudit` 是唯一允许的值。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=pgaudit.role,ParameterValue=rds_pgaudit,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 使用以下 AWS CLI 命令重启 RDS for PostgreSQL 数据库实例，以使对参数的更改生效。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 运行以下命令确认 `pgaudit.role` 设置为 `rds_pgaudit`。

   ```
   SHOW pgaudit.role;
   pgaudit.role 
   ------------------
   rds_pgaudit
   ```

要测试 pgAudit 日志记录，您可以运行几条要审计的示例命令。例如，您可以运行以下命令。

```
CREATE TABLE t1 (id int);
GRANT SELECT ON t1 TO rds_pgaudit;
SELECT * FROM t1;
id 
----
(0 rows)
```

数据库日志应包含类似于以下内容的条目。

```
...
2017-06-12 19:09:49 UTC:...:rds_test@postgres:[11701]:LOG: AUDIT:
OBJECT,1,1,READ,SELECT,TABLE,public.t1,select * from t1;
...
```

有关查看日志的信息，请参阅[监控 Amazon RDS 日志文件](USER_LogAccess.md)。

要了解关于 pgAudit 扩展的更多信息，请参阅 GitHub 上的 [pgAudit](https://github.com/pgaudit/pgaudit/blob/master/README.md)。

# 从审计日志记录中排除用户或数据库
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db"></a>

如 [RDS for PostgreSQL 数据库日志文件](USER_LogAccess.Concepts.PostgreSQL.md)中所述，PostgreSQL 日志会消耗存储空间。使用 pgAudit 扩展会在不同程度上增加日志中收集的数据量，具体取决于您跟踪的更改。您可能不需要审计 RDS for PostgreSQL 数据库实例中的每个用户或数据库。

为了最大限度地减少对存储的影响，避免不必要地捕获审计记录，您可以将用户和数据库排除在审计范围之外。您还可以在给定会话中更改日志记录。下面的示例向您演示如何操作。

**注意**  
会话级别的参数设置优先于 RDS for PostgreSQL 数据库实例的自定义数据库参数组中的设置。如果您不希望数据库用户绕过您的审计日志记录配置设置，请务必更改其权限。

假设您的 RDS for PostgreSQL 数据库实例配置为审计所有用户和数据库的相同级别的活动。然后，您决定不想对用户 `myuser` 进行审计。您可以使用以下 SQL 命令对 `myuser` 关闭审计功能。

```
ALTER USER myuser SET pgaudit.log TO 'NONE';
```

然后，您可以使用以下查询来检查 `pgaudit.log` 的 `user_specific_settings` 列，以确认该参数已设置为 `NONE`。

```
SELECT
    usename AS user_name,
    useconfig AS user_specific_settings
FROM
    pg_user
WHERE
    usename = 'myuser';
```

您将看到如下输出。

```
 user_name | user_specific_settings
-----------+------------------------
 myuser    | {pgaudit.log=NONE}
(1 row)
```

在给定用户与数据库的会话期间，您可以使用以下命令对此用户关闭日志记录功能。

```
ALTER USER myuser IN DATABASE mydatabase SET pgaudit.log TO 'none';
```

使用以下查询，对于特定用户和数据库组合检查 pgaudit.log 的设置列。

```
SELECT
    usename AS "user_name",
    datname AS "database_name",
    pg_catalog.array_to_string(setconfig, E'\n') AS "settings"
FROM
    pg_catalog.pg_db_role_setting s
    LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase
    LEFT JOIN pg_catalog.pg_user r ON r.usesysid = setrole
WHERE
    usename = 'myuser'
    AND datname = 'mydatabase'
ORDER BY
    1,
    2;
```

您将看到类似以下内容的输出。

```
  user_name | database_name |     settings
-----------+---------------+------------------
 myuser    | mydatabase    | pgaudit.log=none
(1 row)
```

对 `myuser` 关闭审计后，您决定不想跟踪对 `mydatabase` 的更改。您可以使用以下命令对该特定数据库关闭审计。

```
ALTER DATABASE mydatabase SET pgaudit.log to 'NONE';
```

然后，使用以下查询检查 database\$1specific\$1settings 列，以确认 pgaudit.log 已设置为 NONE。

```
SELECT
a.datname AS database_name,
b.setconfig AS database_specific_settings
FROM
pg_database a
FULL JOIN pg_db_role_setting b ON a.oid = b.setdatabase
WHERE
a.datname = 'mydatabase';
```

您将看到如下输出。

```
 database_name | database_specific_settings
---------------+----------------------------
 mydatabase    | {pgaudit.log=NONE}
(1 row)
```

要将 myuser 的设置恢复为默认设置，请使用以下命令：

```
ALTER USER myuser RESET pgaudit.log;
```

要将数据库的设置恢复为默认设置，请使用以下命令。

```
ALTER DATABASE mydatabase RESET pgaudit.log;
```

要将用户和数据库重置为默认设置，请使用以下命令。

```
ALTER USER myuser IN DATABASE mydatabase RESET pgaudit.log;
```

还可以通过将 `pgaudit.log` 设置为 `pgaudit.log` 参数的其他允许值之一，将特定事件捕获到日志中。有关更多信息，请参阅 [`pgaudit.log` 参数允许的设置列表](Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.md#Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings)。

```
ALTER USER myuser SET pgaudit.log TO 'read';
ALTER DATABASE mydatabase SET pgaudit.log TO 'function';
ALTER USER myuser IN DATABASE mydatabase SET pgaudit.log TO 'read,function'
```

# pgAudit 扩展的参考
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference"></a>

您可以通过更改本节中列出的一个或多个参数来为审计日志指定所需的详细级别。

## 控制 pgAudit 行为
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.basic-setup.parameters"></a>

您可以通过更改下表中列出的一个或多个参数来控制审计日志记录。


| 参数 | 说明 | 
| --- | --- | 
| `pgaudit.log`  | 指定会话审计日志记录将记录哪些语句类。允许的值包括 ddl、function、misc、read、role、write、none、all。有关更多信息，请参阅 [`pgaudit.log` 参数允许的设置列表](#Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings)。 | 
| `pgaudit.log_catalog` | 启用（设置为 1）时，如果语句中的所有关系都在 pg\$1catalog 中，则将语句添加到审计跟踪中。 | 
| `pgaudit.log_level` | 指定要用于日志条目的日志级别。允许的值：debug5、debug4、debug3、debug2、debug1、info、notice、warning、log | 
| `pgaudit.log_parameter` | 启用（设置为 1）时，将在审计日志中捕获随语句传递的参数。 | 
| `pgaudit.log_relation` | 启用（设置为 1）时，会话的审计日志为 SELECCT 或 DML 语句中引用的每个关系（TABLE、VIEW 等）创建单独的日志条目。 | 
| `pgaudit.log_statement_once` | 指定日志记录在语句/子语句组合中的第一个日志条目中包含语句文本和参数，还是在每个条目中都包含。 | 
| `pgaudit.role` | 指定用于对象审计日志记录的主角色。唯一允许的条目是 `rds_pgaudit`。 | 

## `pgaudit.log` 参数允许的设置列表
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings"></a>

 


| 值 | 说明 | 
| --- | --- | 
| none | 这是默认值。不记录任何数据库更改。 | 
| 全部 | 记录所有内容（read、write、function、role、ddl、misc）。 | 
| ddl | 记录所有数据定义语言（DDL）语句（不包括在 `ROLE` 类中）。 | 
| 函数 | 记录函数调用和 `DO` 块。 | 
| misc | 记录其他命令，例如 `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM` 和 `SET`。 | 
| read | 当源为关系（例如表）或查询时记录 `SELECT` 和 `COPY`。 | 
| 角色 | 记录与角色和权限相关的语句，例如 `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE` 和 `DROP ROLE`。 | 
| 写入 | 当目标为关系（表）时，记录 `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE` 和 `COPY`。 | 

要使用会话审计记录多种事件类型，请使用逗号分隔的列表。要记录所有事件类型，请将 `pgaudit.log` 设置为 `ALL`。重启数据库实例以应用更改。

通过对象审计，您可以细化审计日志记录以使用特定的关系。例如，您可以指定要对一个或多个表上的 `READ` 操作进行审计日志记录。