症状
JVM上で動作するアプリケーションでhttps
で始まるAPIを実行するとエラー発生。
[エラーメッセージ]sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
[エラー概要]class javax.net.ssl.SSLHandshakeException
[エラー発生箇所]
Alerts.java[192] sun.security.ssl.Alerts.getSSLException
SSLSocketImpl.java[1949] sun.security.ssl.SSLSocketImpl.fatal
Handshaker.java[302] sun.security.ssl.Handshaker.fatalSE
Handshaker.java[296] sun.security.ssl.Handshaker.fatalSE
ClientHandshaker.java[1509] sun.security.ssl.ClientHandshaker.serverCertificate
原因
JVMの信頼済ホストにAPIサーバ側のTLS証明書がインポートされていない
対策
JVMの信頼済ホストにAPIサーバ側のTLS証明書をインポートする
手順
APIサーバ側証明書を手動でダウンロードしてkeytoolでインポートするような記事が多いですが、
以下のツールを使うとAPIを実行したいサーバ上のコマンドラインで完結できます。
ツールをダウンロード
# cd /usr/local/src
# git clone https://github.com/escline/InstallCert
# cd InstallCert
ツールをコンパイル
# javac InstallCert.java
証明書のインポート
[HOST]
と記載している部分はAPIサーバのドメインを設定します。
[CACERT_PATH]
と記載している部分はキーストアファイル(cacerts)のフルパスを指定しています。例えば /usr/java/jdk1.8.0_211-amd64/jre/lib/security/cacerts
とかです。
# java InstallCert [HOST]:443
# keytool -exportcert -alias [HOST]-1 -keystore jssecacerts -storepass changeit -file [HOST].cer
# keytool -importcert -alias [HOST] -keystore [CACERT_PATH]<javapath>/jre/lib/security/cacerts -storepass changeit -file [HOST].cer
インポートされたか確認
キーストア内にインストールされている証明書を確認します。表示されればインストール成功です。
# keytool -list -keystore [CACERT_PATH] | grep [HOST]