Rails から MySQL に SSL を用いて通信を行う
ActiveRecord には SSL によるデータベースアクセスをサポートする機能が付属しているので、それを使って通信を暗号化してみます。検証には VirtualBox にインストールした CentOS 5.6 を使用し、作業はすべて root ユーザで行いました。
証明書の作成
今回は動作の確認が目的なので、自己証明書を使ってテストします。証明書の作り方は以下のアドレスを参考にしました。
http://blog.livedoor.jp/burtman/archives/51962114.html
記事中で www.hoge.com となっている箇所を 192.168.1.156(テスト用仮想マシンのプライベートIP)に置き換えて、パスフレーズはすべて「password」とします。途中、国の指定など色々聞かれますが、メモしつつ適当に答えてしまえば問題ありません。
MySQL サーバ側の設定
上記の手順の通りに証明書を作成したものとして、以下のように証明書をコピーし、ファイルの所有権を mysql ユーザに移譲します。
mkdir /etc/mysql cp /var/ssl/CA/cacert.pem /etc/mysql/ cp /var/ssl/CA/server_cert/192.168.1.156/192.168.1.156.cer /etc/mysql/ cp /var/ssl/CA/server_cert/192.168.1.156/192.168.1.156.key /etc/mysql/ chown -R mysql:mysql /etc/mysql
次に my.cnf を開いて、以下の行を追加します。
ssl-ca=/etc/mysql/cacert.pem ssl-cert=/etc/mysql/192.168.1.156.cer ssl-key=/etc/mysql/192.168.1.156.key
完了したら mysqld を再起動します。
/etc/init.d/mysqld restart
うまく起動しない時は、記述にミスがないか確認して下さい。起動が終わったら mysql コマンドから対話型ウインドウを開き、SSL が有効になっているかチェックします。
show variables like 'have_ssl';
結果が YES になっていれば SSL が有効になっています。
次に、アプリケーションを動作させる MySQL のユーザを SSL を用いる前提で作成します。
grant all on some_database.* to rails@localhost identified by 'password' require ssl;
この状態で接続できるかチェックしてみます。
mysql -u rails -p --ssl-ca=/etc/mysql/cacert.pem
うまく接続できていれば、サーバ側の設定は完了です。
アプリケーション側の設定
まずはサーバ側同様に証明書をコピーします。今回は root 権限でアプリケーションを動かすのでファイルの所有権は変更しませんが、実運用の場合は適宜変更して下さい。
cp /var/ssl/CA/cacert.pem /path/to/rails/root/db/ cp /var/ssl/CA/client_cert/test01.cer /path/to/rails/root/db/ cp /var/ssl/CA/client_cert/test01.key /path/to/rails/root/db/
次にデータベースへの接続設定を変更します。config/database.yml を開いて、先ほど設定した値にそれぞれ修正します。
development: adapter: mysql2 database: some_database host: localhost username: rails password: password sslca: /path/to/rails/root/db/cacert.pem sslkey: /path/to/rails/root/db/test01.key sslcert: /path/to/rails/root/db/test01.cer # 以下略
この状態で rails console を実行して、以下のコマンドを実行します。
ActiveRecord::Base.connection.execute("show status like 'Ssl_cipher';").first
うまく実行できると、"DHE-RSA-AES256-SHA" と値が返されるはずです。これで、データベースとの接続が暗号化されました。