Azureで基本的な構成を構築してみる③(MySQL作成, VMからのSSL接続)


1. 背景

前回の記事続きになります。Azureの基本的な構成を作ってみました。
Azureで基本的な構成を構築してみる①(前提、ネットワーク・VM作成)
Azureで基本的な構成を構築してみる②(ALB、DNS作成)
Azureで基本的な構成を構築してみる③(MySQL作成, VMからのSSL接続) ←今ここ

2. アーキテクチャ図

今回はDBとしてMySQLを作成し、可能な限りVMからセキュアな接続設定をしていきます。

4. 構築手順

4.9 DatabaseforMySQL作成

AWSでいうRDSforMySQLとなる、DatabaseforMySQLを作成します。
Azureポータルで「Azure Database for MySQL」に移動 → 「+作成」
・デプロイオプションとして、今回は 「単一サーバ」を使いました。
【基本】
・リソースグループ:VM,AGW等と同じグループ選択
・サーバ名:任意
・データソース:なし
・場所:東日本
・バージョン:8
・コンピューティンングストレージ:デフォルトで汎用プラン選択されてますが、今回高いメモリスペックが必要ないのと、コストを抑えたかったのでBasicプランを選びました。(汎用プランだと最低でも¥2万以上/月します、、)
 「サーバの構成」→Basicプラン選択し、必要スペックに応じてvCore・ストレージ・ストレージの自動拡張等選択します。

DBのユーザ、パスワードも適当に設定します。

→作成
最低スペックでも¥4,000/月程度かかります。。

4.10 DBへの接続設定

前提

お気づきかと思いますが、上記DB作成時にDBの所属サブネットグループ等指定するところがありませんでした。
AzureではAWSのようにプライベートサブネットにRDSを所属させることができず、デフォルトではMySQLへの接続にはインターネットを経由しなくてはいけません

そしてさらに、BasicプランのDBforMySQLだと他Azureサービスからプライベートな接続ができないため、VMのパブリックIPによりインターネット経由でMySQLにアクセスすることしかできません…。
(汎用 or メモリ最適化プランだと「プライベートエンドポイント」というものを作成することでプライベートIPによるセキュアな接続が可能です。)

そこで今回のBasicプランMySQLでは、
1. MySQL側のFirewall機能でVMのパブリックIPのみ開放
2. SSL接続を強制化して通信
により、インターネット経由であっても可能な限りセキュアにVMから接続させることにしました。

手順

上記で作成したDBforMySQLに移動
→左側のタブで「接続のセキュリティ」に移動
・「Azure サービスへのアクセスを許可」を「いいえ」
・「ファイアウォール規則名」で開始IP、終了IPにVMの静的パブリックIPを設定
・「SSL接続を強制」を「有効」

→保存

これでVMのパブリックIPからのみ、SSLでMySQLに接続が可能になります。

4.11 VMからのSSL接続設定

上記の設定で、VMのIPからの接続は開放されましたが、VMでSSL接続の準備をする必要があります。
具体的には、VMにSSL証明書をインポートします。

SSL証明書インポート

https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem からSSL証明書をローカルのMac等にダウンロード
・Pem形式に変換

$ openssl x509 -inform DER -in BaltimoreCyberTrustRoot.crt -out MyServerCACert.pem
$ less MyServerCACert.pem
     →pemの中身見てコピーしておく

・VMにSSH接続

$ ssh -i <鍵のパス> azureuser@<VMのパブリックIP>

・任意のディレクトリに移動し、証明書を複製

$ sudo touch MyServerCACert.pem
$ sudo vi MyServerCACert.pem
   →lessで見た中身をペースト

これでSSL証明書をVMにインポートできました。

接続確認

mysqlクライアントでSSL接続できるか確認してみます。
まず、mysqlコマンドをインストールする必要がありました。
mysql8のリポジトリ追加

$ sudo yum install https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm

リポジトリ追加できたか確認

$ ls -l /etc/yum.repos.d
-rw-r--r--  1 root root 1050 Oct  4  2019 mysql-community-source.repo
-rw-r--r--  1 root root  995 Oct  4  2019 mysql-community.repo

デフォルトのmysqlモジュール無効化

$ sudo yum module disable mysql

mysqlクライアントインストール

$ sudo yum install mysql-community-client

これでmysqlコマンド使えるようになりました。ssl強制で接続してみます。

$ mysql -h <DBforMySQLのサーバ名> -u <MySQLユーザ名>@<サーバ名> -p --ssl-mode=REQUIRED –ssl-ca=<pemのパス>
(例:$ mysql -h mydbformysql.mysql.database.azure.com -u myuser@mydbformysql -p --ssl-mode=REQUIRED –ssl-ca=MyServerCACert.pem)

 →パスワード入力
mysqlのプロンプトに変わると接続成功です。

以下のように、ssl無効で接続しようとすると失敗することも確認します。

$ mysql -h mydbformysql.mysql.database.azure.com -u myuser@mydbformysql -p –ssl-mode=DISABLED
ERROR 9002 (28000): SSL connection is required. Please specify SSL options and retry.

補足ですが、MySQL8.0では--ssl-mode指定しなくても、デフォルトでSSL接続を試みるようです。(参考
実際に以下コマンドでも接続できました。

$ mysql -h mydbformysql.mysql.database.azure.com -u myuser@mydbformysql -p

でも、このコマンドは証明書(MyServerCACert.pem)指定しなくても接続できています。。理由は調べたけどよく分からない…。ご存知の方コメントいただけると幸いです。

アプリケーションでの接続

このMyServerCACert.pemを使って、使用するアプリケーションに応じて、DBへのSSL設定をしましょう。

まとめ

以上、3記事に渡って簡単な構成を作ってみました。
感想としては、同じサービスでもグレードによって使えないオプションや他サービスと連携できないことがあり予算がそれなりにないと不便なことが多かったです。しかもグレードを上げると急激に値段が高い。。(ApplicationGatewayのStandard v2、DBforMySQLの汎用プランとか)
小規模構成や個人運用にAzureは向いてないのかな、と思いました。

今後のTodo

サイトのSSL化についてコストを抑えて構築できればと思ってます。
ApplicationGatewayのStandard v2プランだとKeyVaultと連携してSSL証明書の自動更新できそうですが、v1プランだとKeyVaultとの連携がサポートされていないみたい。ここクリアできるんだろうか。。