概要
MySqlConnectorを用いたWEBアプリケーションにSSL通信を構築する実装方法 (今回は証明書の発行元をherokuにしています。)参考にしたサイト
https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html
バージョン
Flask==1.1.2 Python 3.8.7 mysql-connector-python==8.0.23 mysql 5.5.62 (↑ ClearDBといったクラウド上にホスティングされたDaaSを使用)導入手順
①以下のファイルを用意します。 ・SSL認証局の情報を含むssl_caファイル ・SSL証明書を含むssl_certファイル ・SSLキーを含むssl_keyファイルherokuでClearDBを使用している場合、
作成したアプリケーションのダッシュボードから対象のアプリを選択し
ResourceタブのClearDB MySQLからNAVISITEにジャンプします。
ジャンプ先のSecurityタブから各種証明書を発行できます。
② 前手順で取得したディレクトリに各pemファイルを配置します。
(ディレクトリ構成は公式に則り、opt/mysql/sslとしています。)
また必ずメインモジュールと同階層に配置するようにします。
app.pyがメインモジュールの場合、以下のようになります。
├── app.py
├── opt
│ └── mysql
│ └── ssl
│ ├── ca.pem
│ ├── client-cert.pem
│ └── client-key.pem
③mysqlconnectorのDB接続引数を設定します。
接続引数に与える証明書のパスは、前手順で設定したものを記載します。
import mysql.connector
from mysql.connector.constants import ClientFlag
config = {
'user': 'ssluser',
'password': 'password',
'host': '127.0.0.1',
'client_flags': [ClientFlag.SSL],
'ssl_ca': '/opt/mysql/ssl/ca.pem',
'ssl_cert': '/opt/mysql/ssl/client-cert.pem',
'ssl_key': '/opt/mysql/ssl/client-key.pem',
}
この設定後、私が躓いた点はファイルパスの渡し方でした。
PythonではOSによってスラッシュ記法が異なる為、windows環境で設定したファイルパスは、herokuにデプロイすると参照されずエラーを出力しました。
app[web.1]: FileNotFoundError: [Errno 2] No such file or directory
app[web.1]:"Invalid CA Certificate: {}".format(err))
app[web.1]: mysql.connector.errors.InterfaceError: Invalid CA Certificate: [Errno 2] No such file or directory
os毎のパスのフォーマットは以下のように異なります。 windowsの場合 --> \\\ POSIX(mac/linux)の場合 --> /
対処方法としては、メインモジュールの絶対パスと証明書ファイルの相対パスを連結させてパスを渡すようにしました。 その際、作動するosを判定して、osに応じてパスの取得方法をスイッチさせるようにしました。(若干冗長な気もしますが...)
import os
# 証明書のディレクトリ指定
dirname = os.getcwd()
if os.name == 'nt':
# windows
ca_path = os.path.join(dirname, 'opt\\mysql\\ssl\\ca.pem')
cert_path = os.path.join(dirname, 'opt\\mysql\\ssl\\client-cert.pem')
key_path = os.path.join(dirname, 'opt\\mysql\\ssl\\client-key.pem')
elif os.name == 'posix':
# mac or linux
ca_path = os.path.join(dirname, 'opt/mysql/ssl/ca.pem')
cert_path = os.path.join(dirname, 'opt/mysql/ssl/client-cert.pem')
key_path = os.path.join(dirname, 'opt/mysql/ssl/client-key.pem')
config = {
'user': 'ssluser',
'password': 'password',
'host': '127.0.0.1',
'client_flags': [ClientFlag.SSL],
'ssl_ca': ca_path ,
'ssl_cert': cert_path ,
'ssl_key': key_path ,
}
以上で設定は完了です!