亚马逊AWS官方博客
解决 RDS PostgreSQL 10 升级到 14 后,JDBC 应用程序连接失败的问题
背景
根据 Amazon RDS for PostgreSQL 发布说明,RDS PostgreSQL 10/11 标准支持终止日期到 2023 年,建议升级到合适的新版本。
客户在验证 PostgreSQL 10 升级到 14 过程中,发现第三方应用程序无法正常连接 RDS PostgreSQL 14 数据库。
PG10 升级到 14 后,应用程序无法连接数据库
Metabase 是一个开源的数据分析工具,客户基于 Metabase 构建了很多报表。将 PG 升级到 14 后,发现当前版本 Metabase(v0.29.3)无法连接 PG14,具体错误如下:
Metabase 日志错误堆栈:
问题分析
通过错误关键信息:The authentication type 10 is not supported,结合查看 pgjdbc 的源码,确认这是一个当前版本的 JDBC 驱动无法支持服务器要求的密码认证方式而产生的问题。
在 Server 端,通过 psql 工具连入,结合 rds_tools 扩展去查看当前用户的 encryption_type:
注意:rds_tools 在 RDS PostgreSQL 13 以及后续版本可用。
可以看到用户的默认加密类型是:scram-sha-256。
从客户端测,我们分析 JDBC 驱动,可以看到针对 SASL 的支持在 46.2.1 版本开始加入。
驱动版本 42.1.0
驱动版本 46.2.1
关于 SASL 的说明详见:https://www.postgresql.org/docs/14/sasl-authentication.html。
SASL is a framework for authentication in connection-oriented protocols. At the moment, PostgreSQL implements two SASL authentication mechanisms, SCRAM-SHA-256 and SCRAM-SHA-256-PLUS. More might be added in the future. The below steps illustrate how SASL authentication is performed in general, while the next subsection gives more details on SCRAM-SHA-256 and SCRAM-SHA-256-PLUS.
以上分析可见,服务器端默认使用 scram-sha-256,但是当前版本的 JDBC 驱动不支持这种加密方式,导致问题产生。
如果你的应用程序可控,可以通过升级 JDBC 驱动来解决这个问题。
参考驱动的 release 版本说明,从版本 42.6.1 起增加了对 SASL 的支持。
经实测,升级 JDBC 驱动到 42.6.1 及后续版本可以正常连接 PG14。
如果无法升级应用程序和驱动, 可以通过修改 RDS 实例的配置来解决。
修改 RDS 实例配置以支持旧版本驱动的方法
要点:
- 配置 RDS PostgreSQL 14 支持 MD5 的密码认证方式
- 将具体用户的密码认证方式修改为 MD5
第一步:新建一个自定义参数组
第二步:修改 RDS parameters 参数的 password_encryption
将 password_encryption 的值修改为 md5
第三步:修改 RDS 实例使用自定义参数组并重启
修改参数组需要重启 RDS 服务,重启完成后可以继续下一步。
重启完成后,通过 psql 工具等连接进入目标数据库实例查看 password_encryption,确认值为 md5。
第四步:通过修改现有用户的密码的方式将用户密码加密方式修改为 MD5
根据 postgresql 的文档 https://www.postgresql.org/docs/current/auth-password.html:
The availability of the different password-based authentication methods depends on how a user’s password on the server is encrypted (or hashed, more accurately). This is controlled by the configuration parameter password_encryption at the time the password is set.
设置密码的时候会根据 password_encryption 指定的加密方式来存储密码。修改 password_encryption 变量以后, 可以通过重设密码操作来确保密码采用修改后的方式加密。
应用该修改后,数据库进入以下状态 Resetting-master-credentials:
完成后,再次通过 rds_tools 扩展查看当前用户的加密类型,确认已经是 MD5。
再次使用以上用户名和密码连接数据库,可以正常连接。
总结
出于安全等角度, 我们总是需要将数据库升级到新的版本。AWS 提供了很多方法和实践去帮助我们的升级数据库,但是在升级过程中我们总是会遇到各种各样的挑战。本文中使用到的一些工具和方法希望可以帮助大家定位问题。
祝大家升级顺利。
参考链接
- Best practices for upgrading Amazon RDS to major and minor versions of PostgreSQL https://thinkwithwp.com/cn/blogs/database/best-practices-for-upgrading-amazon-rds-to-major-and-minor-versions-of-postgresql/
- SCRAM Authentication in RDS https://thinkwithwp.com/blogs/database/scram-authentication-in-rds-for-postgresql-13/
- 了解 PostgreSQL 角色和权限 https://docs.thinkwithwp.com/zh_cn/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Roles.html
- Release calendar for Amazon RDS for PostgreSQL https://docs.thinkwithwp.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-release-calendar.html