Full JDK上ではHTTPSでアクセスできるが、distrolessイメージ+カスタムJREだとhandshake_failureが発生する

このエントリは2022/10/18現在の情報に基づいています。将来の機能追加や変更に伴い、記載内容との乖離が発生する可能性があります。

問い合わせ

タイトル通りの内容が届いた。とあるREST APIにHTTPSでアクセスするアプリケーションをコンテナー上で実行すると、以下の例外が発生した、とのこと。

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

もうちょっと深く尋ねてみた。

  • distrolessのコンテナーイメージをベースイメージとして利用
  • jlinkで作成したJDK 17ベースのカスタムJREを利用
  • full JDK(ローカル環境も含む)のコンテナーであれば、問題なく動作

原因

JCA (Java Cryptography Architecture、Java暗号化アーキテクチャ) と互換性のあるセキュリティプロバイダーがカスタムJREに含まれていなかったことが原因であった。本件は以下のドキュメントにも記載がある。

JCA と暗号化のための JCE プロバイダー / JCE Provider for JCA and Crypto
https://learn.microsoft.com/java/openjdk/java-security#jce-provider-for-jca-and-crypto

OpenJDKの場合、jdk.crypto.ecモジュールにJava Cryptography Extension (JCE) の既定の実装プロバイダーが含まれているが、jdepsで必要なモジュールを識別し、jlinkでカスタムJREを作成する場合、このjdk.crypto.ecモジュールが含まれない(依存関係を認識できない)ことがある。

TLSのための依存関係が入っているLinuxイメージ上で実行している場合は、カスタムJREであってもHTTPSでのアクセスが可能の場合がある。例えばHelidon 3.0.1 (MP) でとあるREST APIにアクセスするアプリケーションをカスタムJREで動作させるようにコンテナーイメージを作成したときの出力のスクリーンショット。確かに依存モジュールとしてjdk.crypto.ecはヒットしていない。

カスタムJREに対して–list-modulesを実行しても再確認できる。

例えばdebian-slimイメージ上でこのカスタムJREを使い上記アプリケーションを実行すると問題なく動作するが、distrolessイメージ上の場合、明示的に必要なモジュールを含めたり、依存関係を追加指定したりしなければhandshake_failureが発生する。3rdパーティープロバイダーを利用しないのであれば、jlinkでカスタムJREを作成する際に、このjdk.crypto.ecモジュールを明示的に指定しなければならない。これはJDKのバージョンを問わないため、JDK 19でも同じ事象が発生する。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中