javaの証明書キーストアにletsencryptをインストールする（PKIX path building failedエラーへの対処 第二弾）

# 背景

先日、以下のエラーへの対処方法として、

```
[エラーメッセージ]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
```

以下の記事を書きました。

[PKIX path building failedエラーへの対処。JVMの信頼済ホストにAPIサーバ側のTLS証明書をインポートする](https://qiita.com/s-katsumata/items/837e3160917baeccbd04)


この方法でAPIリクエストのエラーは解消できますが、よく考えたら相手先の証明書が期限切れになるたびに都度再インストールが必要になると思われます。

そこで、根本対応として大本であるLetsEncryptの証明書をインストールする方法を調べたところありました。事細かに記載してくれています。

[SSL error: How to import the Let's Encrypt certificates in the Java truststore - Tutorials & Examples / Solutions - openHAB Community](https://community.openhab.org/t/ssl-error-how-to-import-the-lets-encrypt-certificates-in-the-java-truststore/64671)

さらに、上述した手順をシェルスクリプトにしてGithubで公開してくださっている方もいらっしゃいました。今回はこれを使います。

[install-letsencrypt-in-jdk.sh](https://gist.github.com/Firefishy/109b0f1a90156f6c933a50fe40aa777e)

# 実行方法
## スクリプトダウンロード
Githubからクローンします。後からわかりやすいようにディレクトリ名も指定しておきます。

```
$ git clone https://gist.github.com/109b0f1a90156f6c933a50fe40aa777e.git install_letsencrypt_to_java_cacerts
$ cd install_letsencrypt_to_java_cacerts
```

## Javaホームディレクトリ確認
証明書をインストールしたいJavaのホームディレクトリの場所を調べます。

`echo $JAVA_HOME`とか`which java`とか`locate cacerts`とか。

## キーストアファイルのバックアップ

失敗した場合を考慮して、念の為、キーストアファイル(cacerts)をバックアップします。
ファイルJavaホームディレクトリ下の`/jre/lib/security/cacerts`にあります。

## 実行

```
$ sudo  ./install-letsencrypt-in-jdk.sh <JAVAホームディレクトリ eg./usr/java/latest>
```

### 実行結果
```bash
--2019-06-29 10:28:00--  https://letsencrypt.org/certs/letsencryptauthorityx1.der
Resolving letsencrypt.org (letsencrypt.org)... 184.26.113.203, 2600:140b:a000:295::ce0, 2600:140b:a000:29b::ce0
Connecting to letsencrypt.org (letsencrypt.org)|184.26.113.203|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1425 (1.4K) [application/x-x509-ca-cert]
Saving to: ‘letsencryptauthorityx1.der’

letsencryptauthorityx1.der             100%[=========================================================================>]   1.39K  --.-KB/s    in 0s      

2019-06-29 10:28:00 (247 MB/s) - ‘letsencryptauthorityx1.der’ saved [1425/1425]

--2019-06-29 10:28:00--  https://letsencrypt.org/certs/letsencryptauthorityx2.der
Resolving letsencrypt.org (letsencrypt.org)... 184.26.113.203, 2600:140b:a000:29b::ce0, 2600:140b:a000:295::ce0
Connecting to letsencrypt.org (letsencrypt.org)|184.26.113.203|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1425 (1.4K) [application/x-x509-ca-cert]
Saving to: ‘letsencryptauthorityx2.der’

letsencryptauthorityx2.der             100%[=========================================================================>]   1.39K  --.-KB/s    in 0s      

2019-06-29 10:28:00 (255 MB/s) - ‘letsencryptauthorityx2.der’ saved [1425/1425]

--2019-06-29 10:28:00--  https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.der
Resolving letsencrypt.org (letsencrypt.org)... 184.26.113.203, 2600:140b:a000:295::ce0, 2600:140b:a000:29b::ce0
Connecting to letsencrypt.org (letsencrypt.org)|184.26.113.203|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1196 (1.2K) [application/x-x509-ca-cert]
Saving to: ‘lets-encrypt-x1-cross-signed.der’

lets-encrypt-x1-cross-signed.der       100%[=========================================================================>]   1.17K  --.-KB/s    in 0s      

2019-06-29 10:28:00 (136 MB/s) - ‘lets-encrypt-x1-cross-signed.der’ saved [1196/1196]

--2019-06-29 10:28:00--  https://letsencrypt.org/certs/lets-encrypt-x2-cross-signed.der
Resolving letsencrypt.org (letsencrypt.org)... 184.26.113.203, 2600:140b:a000:29b::ce0, 2600:140b:a000:295::ce0
Connecting to letsencrypt.org (letsencrypt.org)|184.26.113.203|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1196 (1.2K) [application/x-x509-ca-cert]
Saving to: ‘lets-encrypt-x2-cross-signed.der’

lets-encrypt-x2-cross-signed.der       100%[=========================================================================>]   1.17K  --.-KB/s    in 0s      

2019-06-29 10:28:00 (217 MB/s) - ‘lets-encrypt-x2-cross-signed.der’ saved [1196/1196]

--2019-06-29 10:28:00--  https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.der
Resolving letsencrypt.org (letsencrypt.org)... 184.26.113.203, 2600:140b:a000:295::ce0, 2600:140b:a000:29b::ce0
Connecting to letsencrypt.org (letsencrypt.org)|184.26.113.203|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1174 (1.1K) [application/x-x509-ca-cert]
Saving to: ‘lets-encrypt-x3-cross-signed.der’

lets-encrypt-x3-cross-signed.der       100%[=========================================================================>]   1.15K  --.-KB/s    in 0s      

2019-06-29 10:28:00 (215 MB/s) - ‘lets-encrypt-x3-cross-signed.der’ saved [1174/1174]

--2019-06-29 10:28:00--  https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.der
Resolving letsencrypt.org (letsencrypt.org)... 184.26.113.203, 2600:140b:a000:29b::ce0, 2600:140b:a000:295::ce0
Connecting to letsencrypt.org (letsencrypt.org)|184.26.113.203|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1174 (1.1K) [application/x-x509-ca-cert]
Saving to: ‘lets-encrypt-x4-cross-signed.der’

lets-encrypt-x4-cross-signed.der       100%[=========================================================================>]   1.15K  --.-KB/s    in 0s      

2019-06-29 10:28:00 (220 MB/s) - ‘lets-encrypt-x4-cross-signed.der’ saved [1174/1174]

Certificate was added to keystore
Certificate was added to keystore
Certificate was added to keystore
Certificate was added to keystore
Certificate was added to keystore
Certificate was added to keystore
```

このスクリプトは複数回実行されることを想定していて、キーストアからインストール済証明書を削除する処理も実装されています。このため初回実行時は証明書がないので以下のエラーが出ますが問題ありません。

**削除処理（全部で6個）**

```bash
keytool -delete -alias isrgrootx1 -keystore $KEYSTORE -storepass changeit 2> /dev/null || true
```
**初回のみ発生するエラー（全部で6個）**

```bash
keytool error: java.lang.Exception: Alias <isrgrootx1> does not exist
```

## インストール確認
keytoolを使ってインストールされたか確認します。

```bash
$ keytool -v -list -keystore $JAVA_HOME/jre/lib/security/cacerts | grep isrgrootx1
Enter keystore password:  changeit  ★入力してEnter★
Alias name: isrgrootx1   ★表示されればインストール成功★
```

## 再起動

Github上でも記載されていますが、再起動が必要です。

## 動作確認

APIリクエストがエラーにならないか確認します。

以上です。助かるー。