

# 使用 SCRAM 进行 PostgreSQL 密码加密
<a name="PostgreSQL_Password_Encryption_configuration"></a>

在对密码进行加密时，*加盐质询响应身份验证机制（SCRAM）*是 PostgreSQL 的默认消息摘要（MD5）算法的替代方案。―般认为 SCRAM 身份验证机制比 MD5 更安全。要了解有关这两种不同的密码保护方法的更多信息，请参阅 PostgreSQL 文档中的[密码身份验证](https://www.postgresql.org/docs/14/auth-password.html)。

我们建议您使用 SCRAM 而不是 MD5 作为您的 RDS for PostgreSQL 数据库实例的密码加密方案。这是一种加密质询-响应机制，它使用 scram-sha-256 算法进行密码身份验证和加密。

要支持 SCRAM，您可能需要更新客户端应用程序的库。例如，42.2.0 之前的 JDBC 版本不支持 SCRAM。有关更多信息，请参阅 PostgreSQL JDBC 驱动程序文档中的 [PostgreSQL JDBC 驱动程序](https://jdbc.postgresql.org/changelogs/2018-01-17-42.2.0-release/)。有关其他 PostgreSQL 驱动程序和 SCRAM 支持的列表，请参阅 PostgreSQL 文档中的[驱动程序列表](https://wiki.postgresql.org/wiki/List_of_drivers)。

RDS for PostgreSQL 版本 13.1 和更高版本支持 scram-sha-256。这些版本还可让您将数据库实例配置为需要 SCRAM，如以下过程所述。

## 设置 RDS for PostgreSQL 数据库实例以要求使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.preliminary"></a>

您可以要求 RDS for PostgreSQL 数据库实例仅接受使用 scram-sha-256 算法的密码。

**重要**  
对于带有 PostgreSQL 数据库的现有 RDS 代理，如果您将数据库身份验证修改为仅使用 `SCRAM`，代理将在长达 60 秒的时间内不可用。要避免此问题，请执行以下操作之一：  
确保数据库同时允许 `SCRAM` 和 `MD5` 身份验证。
要仅使用 `SCRAM` 身份验证，请创建一个新代理，将应用程序流量迁移到新代理，然后删除先前与数据库关联的代理。

在对系统进行更改之前，请务必了解完整的过程，如下所示：
+ 获取有关所有数据库用户的所有角色和密码加密的信息。
+ 仔细检查 RDS for PostgreSQL 数据库实例的参数设置，以了解用于控制密码加密的参数。
+ 如果您的 RDS for PostgreSQL 数据库实例使用默认参数组，您需要创建自定义数据库参数组，然后将其应用到您的 RDS for PostgreSQL 数据库实例，以便您可以在需要时修改参数。如果您的 RDS for PostgreSQL 数据库实例使用自定义参数组，您可以稍后根据需要在此过程中修改必要的参数。
+ 将 `password_encryption` 参数更改为 `scram-sha-256`。
+ 通知所有数据库用户他们需要更新密码。对您的 `postgres` 账户执行相同的操作。使用 scram-sha-256 算法对新密码进行加密和存储。
+ 验证是否使用加密类型对所有密码加密。
+ 如果所有密码都使用 scram-sha-256，您可以将 `rds.accepted_password_auth_method` 参数从 `md5+scram` 更改为 `scram-sha-256`。

**警告**  
仅将 `rds.accepted_password_auth_method` 更改为 scram-sha-256 之后，使用 `md5` 加密的密码的任何用户（角色）都将无法连接。

### 做好准备，以要求 RDS for PostgreSQL 数据库实例使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.getting-ready"></a>

在对 RDS for PostgreSQL 数据库实例进行任何更改之前，检查所有现有的数据库用户账户。另外，请检查用于密码的加密类型。您可以使用 `rds_tools` 扩展来执行这些任务。要了解哪些 PostgreSQL 版本支持 `rds_tools`，请参阅 [Extension versions for Amazon RDS for PostgreSQL](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)。

**获取数据库用户（角色）和密码加密方法的列表**

1. 使用 `psql` 连接到 RDS for PostgreSQL 数据库实例，如下所示。

   ```
   psql --host=db-name.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

1. 安装 `rds_tools` 扩展。

   ```
   postgres=> CREATE EXTENSION rds_tools;
   CREATE EXTENSION
   ```

1. 获取角色和加密的列表。

   ```
   postgres=> SELECT * FROM 
         rds_tools.role_password_encryption_type();
   ```

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

   ```
          rolname        | encryption_type
   ----------------------+-----------------
    pg_monitor           |
    pg_read_all_settings |
    pg_read_all_stats    |
    pg_stat_scan_tables  |
    pg_signal_backend    |
    lab_tester           | md5
    user_465             | md5
    postgres             | md5
   (8 rows)
   ```

### 创建自定义数据库参数组
<a name="PostgreSQL_Password_Encryption_configuration.custom-parameter-group"></a>

**注意**  
如果您的 RDS for PostgreSQL 数据库实例已使用自定义参数组，您不需要创建新参数组。

有关 Amazon RDS 的参数组的概述，请参阅[在 RDS for PostgreSQL 数据库实例上使用参数](Appendix.PostgreSQL.CommonDBATasks.Parameters.md)。

用于密码的密码加密类型在一个参数（即 `password_encryption`）中设置。 RDS for PostgreSQL 数据库实例允许的加密在另一个参数 `rds.accepted_password_auth_method` 中设置。更改其中任何一个的默认值都要求您创建自定义数据库参数组，然后将其应用到您的实例。

也可以使用 AWS 管理控制台 或 RDS API 创建自定义数据库参数组。有关更多信息，请参阅。

现在可以将自定义参数组与数据库实例关联。

**创建自定义数据库参数组**

1. 使用 CLI 命令 `[create-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-parameter-group.html) ` 创建自定义数据库参数组。此示例使用 `postgres13` 作为此自定义参数组的来源。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds create-db-parameter-group --db-parameter-group-name 'docs-lab-scram-passwords' \
     --db-parameter-group-family postgres13  --description 'Custom parameter group for SCRAM'
   ```

   对于：Windows

   ```
   aws rds create-db-parameter-group --db-parameter-group-name "docs-lab-scram-passwords" ^
     --db-parameter-group-family postgres13  --description "Custom DB parameter group for SCRAM"
   ```

1. 使用 CLI 命令 `[modify-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-instance.html)` 将此自定义参数组应用于 RDS for PostgreSQL 数据库集群。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds modify-db-instance --db-instance-identifier 'your-instance-name' \
           --db-parameter-group-name "docs-lab-scram-passwords
   ```

   对于：Windows

   ```
   aws rds modify-db-instance --db-instance-identifier "your-instance-name" ^
           --db-parameter-group-name "docs-lab-scram-passwords
   ```

   要将 RDS for PostgreSQL 数据库实例与您的自定义数据库参数组重新同步，您需要重启集群的主实例和所有其他实例。为了尽量减少对用户的影响，请安排在常规维护时段内执行此操作。

### 配置密码加密以使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.configure-password-encryption"></a>

RDS for PostgreSQL 数据库实例使用的密码加密机制在数据库参数组的 `password_encryption` 参数中设置。允许的值为未设置、`md5` 或 `scram-sha-256`。默认值取决于 RDS for PostgreSQL 版本，如下所示：
+ RDS for PostgreSQL 14 和更高版本 – 默认为 `scram-sha-256`
+ RDS for PostgreSQL 13 – 默认为 `md5`

使用附加到 RDS for PostgreSQL 数据库实例的自定义数据库参数组，您可以修改密码加密参数的值。

![\[接下来，RDS 控制台显示 RDS for PostgreSQL 的 password_encryption 参数的默认值。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/rpg-pwd-encryption-md5-scram-1.png)


**将密码加密设置更改为 scram-sha-256**
+ 将密码加密的值更改为 scram-sha-256，如下所示。可以立即应用更改，因为参数是动态的，这样，无需重新启动即可使更改生效。

  对于 Linux、macOS 或 Unix：

  ```
  aws rds modify-db-parameter-group --db-parameter-group-name \
    'docs-lab-scram-passwords' --parameters 'ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate'
  ```

  对于：Windows

  ```
  aws rds modify-db-parameter-group --db-parameter-group-name ^
    "docs-lab-scram-passwords" --parameters "ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate"
  ```

### 将用户角色的密码迁移到 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.migrating-users"></a>

您可以将用户角色的密码迁移到 SCRAM，如下所述。

**将数据库用户（角色）密码从 MD5 迁移到 SCRAM**

1. 以管理员用户身份（默认用户名 `postgres`）登录，如下所示。

   ```
   psql --host=db-name.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

1. 通过使用以下命令，在 RDS for PostgreSQL 数据库实例上检查 `password_encryption` 参数的设置。

   ```
   postgres=> SHOW password_encryption;
    password_encryption
   ---------------------
    md5
    (1 row)
   ```

1. 将此参数的值更改为 scram-sha-256。有关更多信息，请参阅 [配置密码加密以使用 SCRAM](#PostgreSQL_Password_Encryption_configuration.configure-password-encryption)。

1.  再次检查该值，以确保它现在已设置为 `scram-sha-256`，如下所示。

   ```
   postgres=> SHOW password_encryption;
    password_encryption
   ---------------------
    scram-sha-256
    (1 row)
   ```

1. 通知所有数据库用户更改其密码。请确保还要更改您自己的用于 `postgres` 账户的密码（具有 `rds_superuser` 权限的数据库用户）。

   ```
   labdb=> ALTER ROLE postgres WITH LOGIN PASSWORD 'change_me';
   ALTER ROLE
   ```

1. 对于您的 RDS for PostgreSQL 数据库实例上的所有数据库重复此过程。

### 更改参数以要求使用 SCRAM
<a name="PostgreSQL_Password_Encryption_configuration.require-scram"></a>

这是该过程的最后一步。在以下过程中进行更改后，任何仍对密码使用 `md5` 加密的用户账户（角色）都将无法登录到 RDS for PostgreSQL 数据库实例。

`rds.accepted_password_auth_method` 指定 RDS for PostgreSQL 数据库实例在登录过程中接受的用户密码加密方法。默认值为 `md5+scram`，这意味着可以接受任一种方法。在下面的图中，您可以找到此参数的默认设置。

![\[RDS 控制台显示 rds.accepted_password_auth_method 参数的默认值和允许的值。\]](http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/images/pwd-encryption-md5-scram-2.png)


此参数允许的值仅为 `md5+scram` 或 `scram`。如果将此参数值更改为 `scram`，则必须使用这种方法。

**更改参数值以要求对密码进行 SCRAM 身份验证**

1. 验证 RDS for PostgreSQL 数据库实例上所有数据库的所有数据库用户密码是否使用 `scram-sha-256` 进行密码加密。为此，查询 `rds_tools` 以获得角色（用户）和加密类型，如下所示。

   ```
   postgres=> SELECT * FROM rds_tools.role_password_encryption_type();
     rolname        | encryption_type
     ----------------------+-----------------
     pg_monitor           |
     pg_read_all_settings |
     pg_read_all_stats    |
     pg_stat_scan_tables  |
     pg_signal_backend    |
     lab_tester           | scram-sha-256
     user_465             | scram-sha-256
     postgres             | scram-sha-256
     ( rows)
   ```

1. 在您的 RDS for PostgreSQL 数据库实例中的所有数据库实例中重复此查询。

   如果所有密码都使用 scram-sha-256，您可以继续操作。

1. 将接受的密码身份验证的值更改为 scram-sha-256，如下所示。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds modify-db-parameter-group --db-parameter-group-name 'docs-lab-scram-passwords' \
     --parameters 'ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate'
   ```

   对于：Windows

   ```
   aws rds modify-db-parameter-group --db-parameter-group-name "docs-lab-scram-passwords" ^
     --parameters "ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate"
   ```