Aurora PostgreSQL接続時の「The authentication type 10 is not supported.」エラーに対応する

JDBCドライバのバージョンを上げましょう。どうしても無理ならpassword_encryptionをmd5にしてパスワードの再設定を
2023.03.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

CX事業本部@大阪の岩田です

社内のチャットでAurora PostgreSQL接続時に発生した

org.postgresql.util.PSQLException: The authentication type 10 is not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or subnet, and that it is using an authentication scheme supported by the driver.

というエラーの対応方法に質問があったので、対応方法等をブログにまとめておきます。

ブログのタイトルはAurora PostgreSQLとなっており、検証作業もAuroraで行いましたが、通常のRDS for PostgreSQLやPostgreSQLでもバージョン14以後であれば同様の考え方になるはずです。

結論

利用しているJDBCのバージョンが古いのでPostgreSQL JDBC ドライバーのバージョン42.2.0以後にバージョンを上げましょう。もし何らかの理由でJDBCのバージョンが上げられない場合はpassword_encryptionをmd5に設定した上で対象のDBユーザーのパスワードを再設定しましょう。

環境

今回検証に利用した環境は以下の通りです

  • Aurora PostgreSQL: エンジンバージョン14.6
  • DB クラスターのパラメータグループ: default.aurora-postgresql14
    • rds.accepted_password_auth_method: md5+scram
    • password_encryption: 指定なし → デフォルト値としてscram-sha-256が利用される
    • ※参考 PostgreSQL 14 に関する技術情報
  • クライアントのOS: Amazon Linux2 (4.14.214-160.339.amzn2.x86_64)
  • Java: OpenJDK 1.7.0_321
  • JDBCドライバ
    • postgresql-42.1.4.jre7.jar
    • postgresql-42.2.27.jre7.jar

概要

パスワードのハッシュ方式について

PostgreSQLはDBユーザーのパスワードのハッシュをサーバーに格納する方式としてscram-sha-256とmd5の2種類をサポートしています。※古いバージョンでは平文での格納も可能だったようです。

このハッシュ形式はpassword_encryptionというパラメータで設定されており、password_encryptionがmd5の場合、CREATE ROLEやALTER ROLEで設定されたパスワードはmd5形式で、password_encryptionがscramの場合はSCRAM-SHA-256でハッシュ化されます。

通常のPostgreSQL(非RDS)であればpg_authidを確認すればハッシュ形式が確認できます。

postgres=# select rolname,rolpassword from pg_authid ;
          rolname          |                                                              rolpassword
---------------------------+---------------------------------------------------------------------------------------------------------------------------------------
...略
 scram                     | SCRAM-SHA-256$4096:hjOj1xgMBZjgk12E5CZluA==$JQOYWNm82TAOUowHcrGLDISUB5xZLesOEn1Y9yZNBUg=:rjeoQ1TgTn1d/qlqpNuIXpLX5hmcqED+mAHcFz2kAgA=
 md5                       | md53062e1e11c64939824f4f249890f7157

クライアントが入力したパスワードが送信される方式について

PostgreSQLのクライアントが接続確立時にサーバーにパスワードを送信する方式は前述のscram-sha-256とmd5に加えてpassword(平文利用)という方式がサポートされています。実際に利用可能な方式はサーバー上でパスワードがどの形式でハッシュ化されているかに依存して以下のように決まります。

  • サーバー上でパスワードがscram-sha-256でハッシュ化されている場合
    • クライアントはscram-sha-256もしくはpasswordが利用可能
  • サーバー上でパスワードがmd5でハッシュ化されている場合
    • クライアントはmd5もしくはpassword

さらにpg_hba.confの設定により、特定のクライアントからの接続はscramのみ許可する といった設定も可能です。

RDSにおけるパスワードハッシュ化の形式

ここまでは通常のPostgreSQLの話でしたが、RDSでは追加の考慮事項があります。通常のPostgreSQLではpg_hba.confの設定によりmd5やscramの利用可否を細かく制御できますが、pg_hba.confが編集できないRDS環境においては代わりにrds.accepted_password_auth_methodによってクライアントが利用可能なハッシュ形式が制限できます。このパラメータは

  • md5+scram
  • scram-sha-256

の2種類から指定でき、scram-sha-256を指定した場合、クライアントはハッシュ形式としてmd5が利用できなくなります。つまりRDS上でユーザーのパスワードがmd5でハッシュ化されている場合にrds.accepted_password_auth_methodscram-sha-256に設定されてしまうと、クライアントはRDSに接続できないことになります。

rds.accepted_password_auth_methodmd5+scram に指定されている場合は、クライアントはmd5とscramの両方が利用可能です。よってRDS上でユーザーのパスワードがmd5でハッシュ化されている場合、scram-sha-256でハッシュ化されている場合、いずれの場合も対応可能です。

PostgreSQL 14からpassword_encryptionのデフォルト値がscram-sha-256

このようにクライアントが利用できるハッシュ形式に影響を与えるpassword_encryptionというパラメータですが、PostgreSQL 14からはscram-sha-256がデフォルト値となりました。従来はmd5がデフォルト値だったので、デフォルトの設定でPostgreSQLを利用している分にはクライアントが利用するハッシュ形式も必然的にmd5となっていましたが、PostgreSQL 14からはscram-sha-256を利用することになります。が、ここに注意が必要で、古いクライアント(各種ライブラリやJDBCドライバ)はscram-sha-256に対応しておらず、パスワードがscram-sha-256でハッシュ化されたDBユーザーを利用してサーバーに接続できないことになります。

やってみる

ここまでの説明を踏まえつつ、冒頭のエラーについて検証していきましょう。

まずはpsqlからAuroraに接続して設定を確認しておきます。

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


postgres=> CREATE EXTENSION rds_tools;
CREATE EXTENSION
postgres=> SELECT * FROM rds_tools.role_password_encryption_type();
       rolname        | encryption_type
----------------------+-----------------
 pg_database_owner    |
 pg_read_all_data     |
 pg_write_all_data    |
 pg_monitor           |
 pg_read_all_settings |
 pg_read_all_stats    |
 pg_stat_scan_tables  |
 pg_signal_backend    |
 postgres             | scram-sha-256
(9 rows)

password_encryptionscram-sha-256が設定されており、マスターユーザーであるpostgresのencryption_typeもscram-sha-256となっています。

検証用にパスワードのencryption_typeがscram-sha-256のユーザーを作成しておきます。

postgres=> CREATE ROLE scram WITH PASSWORD 'scram' LOGIN;
CREATE ROLE
postgres=> SELECT * FROM rds_tools.role_password_encryption_type();
       rolname        | encryption_type
----------------------+-----------------
 pg_database_owner    |
 pg_read_all_data     |
 pg_write_all_data    |
 pg_monitor           |
 pg_read_all_settings |
 pg_read_all_stats    |
 pg_stat_scan_tables  |
 pg_signal_backend    |
 postgres             | scram-sha-256
 scram                | scram-sha-256
(10 rows)

同様にencryption_typeがmd5のユーザーも作成してます

postgres=> SET password_encryption=md5;
SET

postgres=> CREATE ROLE md5 WITH PASSWORD 'md5' LOGIN;
CREATE ROLE

postgres=> SELECT * FROM rds_tools.role_password_encryption_type();
       rolname        | encryption_type
----------------------+-----------------
 pg_database_owner    |
 pg_read_all_data     |
 pg_write_all_data    |
 pg_monitor           |
 pg_read_all_settings |
 pg_read_all_stats    |
 pg_stat_scan_tables  |
 pg_signal_backend    |
 postgres             | scram-sha-256
 scram                | scram-sha-256
 md5                  | md5
(11 rows)

検証用コード

設定が確認できたらJavaのコードからAuroraに接続して動作を確認していきます。今回は以下のコードで実験します。

JdbcTest.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;

public class JdbcTest {

  public static void main(String[] args) {

    final String URL  = "jdbc:postgresql://Auroraのエンドポイント:5432/template1";
    final String USER = System.getenv("USER");
    final String PASS = System.getenv("PASSWORD");

    try(
      Connection conn = DriverManager.getConnection(URL, USER, PASS);
      Statement st = conn.createStatement();
      ResultSet rs = st.executeQuery("SELECT now()");
    ) {
      rs.next();
      System.out.println(rs.getString(1));
    } catch (SQLException e) {
      System.out.println(e);
    }
  }
}

環境変数USERとPASSWORDに設定された情報を使ってAuroraに接続し、SELECT now()を発行するだけのシンプルな処理です。

コードが準備できたのでコンパイルしてclassファイルを準備します

$ javac JdbcTest.java

古いJDBCドライバ × パスワードのencryption_typeがmd5のユーザーで接続してみる

まずは古いJDBCドライバとパスワードのencryption_typeがmd5のユーザーの組み合わせで試してみます。

$USER=md5 PASSWORD=md5 java -classpath postgresql-42.1.4.jre7.jar:./ JdbcTest
2023-03-24 13:58:37.544767+00

問題なく実行できました

古いJDBCドライバ × パスワードのencryption_typeがscram-sha-256のユーザーで接続してみる

続いて古いJDBCドライバとパスワードのencryption_typeがscram-sha-256のユーザーの組み合わせです

USER=scram PASSWORD=scram java -classpath postgresql-42.1.4.jre7.jar:./ JdbcTest
Mar 24, 2023 2:00:47 PM org.postgresql.Driver connect
SEVERE: Connection error:
org.postgresql.util.PSQLException: The authentication type 10 is not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or subnet, and that it is using an authentication scheme supported by the driver.
	at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:614)
	at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:222)
	at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
	at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:194)
	at org.postgresql.Driver.makeConnection(Driver.java:450)
	at org.postgresql.Driver.connect(Driver.java:252)
	at java.sql.DriverManager.getConnection(DriverManager.java:571)
	at java.sql.DriverManager.getConnection(DriverManager.java:215)
	at JdbcTest.main(JdbcTest.java:16)

org.postgresql.util.PSQLException: The authentication type 10 is not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or subnet, and that it is using an authentication scheme supported by the driver.

エラーになりました。古いJDBCドライバはSCRAMに未対応ということが分かります。

新しいJDBCドライバ × パスワードのencryption_typeがscram-sha-256のユーザーで接続してみる

今度はJDBCドライバのバージョンを42.2系に変更して試してみましょう。先程実行したコマンドの引数-classpathの指定を変更して利用するJDBCドライバのバージョンを変更しています。

USER=scram PASSWORD=scram java -classpath postgresql-42.2.27.jre7.jar:./ JdbcTest
2023-03-24 14:03:22.895092+00

今度は無事に接続できました!

DBユーザーのパスワードをencryption_type:md5で更新してから古いJDBCドライバで接続してみる

JDBCドライバのバージョンを上げれば The authentication type 10 is not supported.のエラーが回避できることが分かりました。が、諸事情によりJDBCドライバのバージョンを上げられないようなケースもあると思います。こういった場合の対応方法としてDBユーザーのパスワードをencryption_type:md5に更新すれば古いJDBCドライバからでも接続可能になることを確認しておきましょう。

先程作成したscramユーザーのパスワードをencryption_type:md5で再設定します。

postgres=> SELECT * FROM rds_tools.role_password_encryption_type() where rolname = 'scram';
 rolname | encryption_type
---------+-----------------
 scram   | scram-sha-256
(1 row)

postgres=> SET password_encryption=md5;
SET

postgres=> ALTER role scram with password 'scram';
ALTER ROLE

postgres=> SELECT * FROM rds_tools.role_password_encryption_type() where rolname = 'scram';
 rolname | encryption_type
---------+-----------------
 scram   | md5
(1 row)

改めて古いJDBCドライバを使って接続確認してみます。

USER=scram PASSWORD=scram java -classpath postgresql-42.1.4.jre7.jar:./ JdbcTest
2023-03-24 14:12:31.141669+00

無事に古いJDBCドライバからでもつながりました!

まとめ

PostgreSQLのクライアントのバージョンが古い場合は、パスワードのハッシュ形式scram-sha-256 に対応できません。一例として42.2.0より前のJDBCドライバが挙げられます。

もしPostgreSQL 14以後に対して古いクライアントから接続したい場合はまずクライアントのバージョンアップを検討して下さい。もし何らかの事情によってクライアントのバージョンアップが不可能な場合は、encryption_typeをmd5に設定した状態で対象DBユーザーのパスワードを更新することでPostgreSQL 13以前と同様にmd5を利用した接続が可能になります。

参考