Tomcat 8からRDS for MySQLへのJDBC SSL接続/2015年の証明書版メモ

  • 1
    Like
  • 0
    Comment

Tomcat 8からAWSのRDS for MySQLに、SSL証明書を使ってJDBC接続するための設定です。
2015年に証明書が更新され(ルート証明書・リージョン別中間証明書、新・旧など)複数に分かれた関係で、提供される.pemファイルが(2010年版証明書の手順のままでは).jksファイルに正しく変換できなくなっていましたので、手順をメモとして残しておきます。

ポイント

参考にしたもの

2010年版証明書と同じ手順でインポートすると…

Tomcatのログ(catalina.out)に、以下のようなエラーが記録され、正しく接続できません。

catalina.out(一部抜粋)
23-Jan-2017 09:34:13.247 WARNING [localhost-startStop-2] org.apache.naming.NamingContext.lookup Unexpected exception resolving reference
 org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Could not create connection to database server. Attempted reconnect 3 times. Giving up.)
(中略)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
(中略)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
(中略)
The last packet successfully received from the server was 9 milliseconds ago.  The last packet sent successfully to the server was 9 milliseconds ago.
(中略)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
(中略)
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

手順

1.MySQLのユーザを「REQUIRE SSL」付きで発行する

mysql> GRANT 【権限】 ON 【対象スキーマ.テーブル名など】 TO 【ユーザ名】 IDENTIFIED BY '【パスワード】' REQUIRE SSL;

2.証明書を用意する

$ wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem
$ csplit -b %02d.pem -z rds-combined-ca-bundle.pem /-----BEGIN/ {*}

※2015年版の場合、15個のファイルに分割される。

$ for i in {0..14}; do name=$(printf xx%02d $i); keytool -keystore amazon.jks -alias $name -importcert -file $name.pem; done;

※最初だけ、同じパスワードを2回入力して「yes」。2個目からは同じパスワードを1回ずつ入力する。

$ sudo cp amazon.jks /etc/pki/java/
$ sudo chmod 444 /etc/pki/java/amazon.jks

※念のため、既存の他ファイルと置き場所・パーミッションを合わせておいた。なお、600・400などにしてしまうと読めないので注意。

なお、東京リージョンのみで使う場合は、15個の証明書を変換・連結して.jksファイルに入れなくても、以下の2ファイルのみ変換して1個の.jksファイルにまとめるだけでも問題なく使うことができます。

3.server.xmlまたはコンテキストファイルに記述(Commons DBCPを使う場合)

xxx.xml(一部抜粋)
<Resource name="jdbc/mykomon" auth="container"
        type="javax.sql.DataSource"
        driverClassName="com.mysql.jdbc.Driver"

        factory="org.apache.commons.dbcp.BasicDataSourceFactory"
        url="jdbc:mysql://xxx.xxx.ap-northeast-1.rds.amazonaws.com/【DB名】?useSSL=true&amp;requireSSL=true&amp;verifyServerCertificate=true&amp;trustCertificateKeyStoreUrl=file:///etc/pki/java/amazon.jks&amp;trustCertificateKeyStoreType=JKS&amp;trustCertificateKeyStorePassword=【JKSファイル生成時パスワード】"
        username="【MySQLユーザ名】"
        password="【MySQLパスワード】"
/>

※Amazon LinuxでTomcat 8を使う場合、本家には含まれている「tomcat-dbcp.jar」がRPMパッケージに含まれず「commons-dbcp.jar」になっているため、「factory="org.apache.commons.dbcp.BasicDataSourceFactory"」が必要。

なお、SSL証明書を使う場合、ドメイン名(FQDN)が気になるところですが、urlに記述するホスト名はRoute53のPrivateゾーンに登録した別名(CNAMEレコード)などでも正しく接続できるようです。

※(別名を使うなど)接続先RDSのIPアドレスが変化することを想定するのであれば、JVMで名前解決をキャッシュしないように(または短時間のキャッシュにとどめるように)設定する必要もありそうです。