MySQL 8.0.14でバイナリログファイルとリレーログファイルが暗号化できるようになりました。
ファイルデータの暗号化には、AES(CTR) が使用されています。
また、パスワードを暗号化する為のマスターキー(暗号化キー)が生成され、生成したキーデータをMySQLのキーリングの仕組みで管理されています。
詳細については以下の2つのリファレンスを参照されると、理解が深まりますので、興味がある方は一読される事をお勧めします。
- MySQL 8.0 Reference Manual / 17.3.10 Encrypting Binary Log Files and Relay Log Files
- MySQL 8.0 Reference Manual / 6.5.4 The MySQL Keyring
早速ですが、実際に暗号化を設定して確認してみたいと思います。
暗号化設定前の動作確認
暗号化の設定は binlog_encryption
システム変数に ON
または 1
を設定する事で有効化されます。
デフォルトでは暗号化設定は無効となっています。
1 2 3 4 5 6 7 |
mysql> SELECT @@binlog_encryption; +---------------------+ | @@binlog_encryption | +---------------------+ | 0 | +---------------------+ 1 row in set (0.00 sec) |
無効になっている状態で、レコードをテーブルに挿入してバイナリログを確認してみます。
まずは、テーブルにデータを挿入します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
mysql> INSERT INTO t1 (col2) VALUES ('test1'), ('test2'), ('test3'); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT col2 FROM t1; +-------+ | col2 | +-------+ | test1 | | test2 | | test3 | +-------+ 3 rows in set (0.00 sec) |
バイナリログに挿入した値が含まれる事を確認します。
1 2 3 4 5 6 7 |
mysql> SHOW BINARY LOGS; +------------------+-----------+-----------+ | Log_name | File_size | Encrypted | +------------------+-----------+-----------+ | mysql-bin.000001 | 434 | No | +------------------+-----------+-----------+ 1 row in set (0.00 sec) |
SHOW BINARY LOGS;
の出力結果の Encrypted
が No
となっている場合は暗号化されていないバイナリログとなります。
1 2 3 4 5 |
[root@mysql8015-master mysql]# strings mysql-bin.000001 | grep 'test' test1 test2 test3 [root@mysql8015-master mysql]# |
バイナリログは文字通りバイナリ形式であるものの、挿入した値を確認する事ができました。
レプリケーション・スレーブサーバのリレーログに関しても同様に挿入した値を確認する事ができます。
暗号化設定
それでは binlog_encryption
を有効にして、同じ様に確認してみます。
MySQL Community Edition では、keyring_file プラグインを使用して、生成したマスターキーデータをローカルファイルに保存する為、keyring_file プラグインをインストールする必要があります。
MySQL Enterprise Edition であれば Oracle Key Vault や Amazon Web Services Key Management Service でマスターキーを管理する事も可能です。
・MySQL設定ファイル
1 2 3 4 5 |
[mysqld] ・・・ early-plugin-load=keyring_file.so binlog_encryption = ON ・・・ |
上記の設定をしてMySQLサービスを再起動する事で、バイナリログがローテーションされて新しい出力先となるバイナリログが暗号化されます。
あるいは、コマンドで設定する事も可能です。
コマンドで設定した場合は binlog_encryption = ON
に設定した時点でバイナリログがローテーションされます。
(binlog_encryption
の設定には、SUPER
または BINLOG_ENCRYPTION_ADMIN
権限が必要です。)
1 2 3 4 5 |
mysql> INSTALL PLUGIN keyring_file SONAME 'keyring_file.so'; Query OK, 0 rows affected (0.01 sec) mysql> SET PERSIST binlog_encryption = ON; Query OK, 0 rows affected (0.00 sec) |
暗号化が有効になっている事を確認します。
1 2 3 4 5 6 7 |
mysql> SELECT @@binlog_encryption; +---------------------+ | @@binlog_encryption | +---------------------+ | 1 | +---------------------+ 1 row in set (0.00 sec) |
ローテーション後の新しく生成されたバイナリログが暗号化されている事を確認します。
SHOW BINARY LOGS;
の出力結果の Encrypted
が Yes
になっている事から暗号化されたバイナリログにローテーションされていると判断できます。
1 2 3 4 5 6 7 8 |
mysql> SHOW BINARY LOGS; +------------------+-----------+-----------+ | Log_name | File_size | Encrypted | +------------------+-----------+-----------+ | mysql-bin.000001 | 453 | No | | mysql-bin.000002 | 703 | Yes | +------------------+-----------+-----------+ 2 rows in set (0.00 sec) |
続けて、暗号化設定前確認時と同様に、レコードをテーブルに挿入して確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
mysql> INSERT INTO t1 (col2) VALUES ('test5'), ('test6'), ('test7'); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT col2 FROM t1; +-------+ | col2 | +-------+ | test1 | | test2 | | test3 | | test5 | | test6 | | test7 | +-------+ |
バイナリログを確認します。
1 2 |
[root@mysql8015-master mysql]# strings mysql-bin.000002 | grep 'test' [root@mysql8015-master mysql]# |
今度は、挿入した値が抽出できませんでした。
スレーブのリレーログに関しても同様の結果となります。
マスターキーの変更について
MySQLをインストール後、初めてバイナリログの暗号化を有効にした時点で、マスターキーが生成されてキーリングファイルに保存されます。
一度有効にすると、以降、無効にして再度有効にしたとしても、既に存在するマスターキーが使いまわされます。
但し、binlog_rotate_encryption_master_key_at_startup をONに設定すると、MySQLサーバを再起動する度に新しい暗号化キーを生成する事が可能です。
mysqlbinlog コマンド
暗号化されたバイナリログとリレーログを mysqlbinlog コマンドで確認する場合には、注意が必要となります。
まずは試しに、ユーザ、パスワードのみ指定して実行してみます。
1 2 3 4 |
[root@mysql8015-master mysql]# mysqlbinlog -u user1 -p mysql-bin.000002 Enter password: ERROR: Reading encrypted log files directly is not supported. (略) |
ERROR: Reading encrypted log files directly is not supported.
のエラーメッセージが返されました。
mysqlbinlog ではキーリングファイルを使用できない為、MySQLサーバからバイナリログを読み込む必要があります。
その為、–read-from-remote-server オプションを指定する必要があります。
(※--read-from-remote-server
オプションを指定するには、実行ユーザに REPLICATION SLAVE
権限が必要となります。)
1 2 3 4 5 6 |
[root@mysql8015-master mysql]# mysqlbinlog --read-from-remote-server -u user1 -p mysql-bin.000002 Enter password: /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; (略) |
今度は正常に抽出する事ができました。
また、リモートサーバから暗号化したバイナリログを抽出する際は、バイナリログが存在するMySQLサーバも指定する必要があります。
1 2 3 4 5 6 |
[vagrant@mysql8015-test ~]$ mysqlbinlog --read-from-remote-server -h mysql8015-master -u user1 -p mysql-bin.000002 Enter password: /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; (略) |
リモートサーバからも暗号化したバイナリログを抽出する事ができました。
また、暗号化したバイナリログのバックアップを取得する場合は、キーリングファイルも必要となりますので、忘れずに合わせてバックアップを取得しておきましょう。
性能検証
バイナリログの暗号化を無効/有効にした場合とで、sysbenchを使って簡易的な性能検証をしました。
・サーバ(Amazon Web Service / EC2)
サーバースペック | |
---|---|
インスタンス | m5.2xlarge |
OS | Amazon Linux release 2 |
CPU | 8(vCPU) |
RAM | 32(GiB) |
Storage | プロビジョンドIOPS(1000) |
・sysbench
書き込み処理 のみ(oltp_write_only)とし、スレッド数は、8, 16, 32, 64, 128, 256, 512, 1024 で検証します。
1 2 3 4 5 6 7 8 9 10 11 |
./oltp_write_only.lua \ --db-driver=mysql \ --mysql-socket=/var/lib/mysql/mysql.sock \ --mysql-user={ユーザ} \ --mysql-password={パスワード} \ --mysql-db=benchmark \ --tables=10 \ --table_size=100000 \ --threads={スレッド数} \ --time=600 \ run |
・MySQLパラメータ
yumインストールしたデフォルトの my.cnf に以下のパラメータを追加しています。
1 2 3 4 5 6 7 8 9 |
max_connections = 1050 innodb_buffer_pool_size = 20G innodb_buffer_pool_dump_at_shutdown = OFF innodb_buffer_pool_load_at_startup = OFF max_prepared_stmt_count = 1048576 early-plugin-load=keyring_file.so binlog_encryption = ON |
※early-plugin-load
と binlog_encryption
は非暗号化検証時はコメントにします。
※MySQL8.0では、バイナリログをディスクに同期させる設定 sync_binlog はデフォルトで 1 に設定されています。
・検証結果
スレッド数 | 暗号化 | TPS | QPS | Latency (avg) |
---|---|---|---|---|
8 | Disable | 532.48 | 3195.09 | 15.02 ms |
8 | Enable | 531.39 | 3188.56 | 15.05 ms |
16 | Disable | 850.27 | 5102.16 | 18.82 ms |
16 | Enable | 832.83 | 4997.57 | 19.21 ms |
32 | Disable | 1291.24 | 7748.51 | 24.78 ms |
32 | Enable | 1271.70 | 7631.38 | 25.16 ms |
64 | Disable | 1772.00 | 10634.99 | 36.11 ms |
64 | Enable | 1747.41 | 10487.23 | 36.62 ms |
128 | Disable | 2298.14 | 13799.99 | 55.69 ms |
128 | Enable | 2286.04 | 13727.48 | 55.99 ms |
256 | Disable | 3310.31 | 19898.41 | 77.32 ms |
256 | Enable | 3285.41 | 19747.73 | 77.90 ms |
512 | Disable | 4114.85 | 24794.20 | 124.38 ms |
512 | Enable | 4095.47 | 24675.43 | 124.99 ms |
1024 | Disable | 4070.87 | 24659.91 | 251.46 ms |
1024 | Enable | 4061.71 | 24600.95 | 252.01 ms |
・TPS (グラフ)
・QPS (グラフ)
・Latency (グラフ)
暗号化の有効・無効で大きな性能の相違は見られませんでした。
また、CPU使用率等のサーバリソースにもほぼ変動はなく、有効化に伴うリスクも心配無さそうです。
まとめ
今回、確認した内容を箇条書きでまとめておきます。
- バイナリログとリレーログのデータを
AES(CTR)
で暗号化する。 binlog_encryption
システム変数で暗号化の有効・無効を切り替える。
(デフォルト無効)- SETコマンドでの切り替えも可能。
(binlog_encryption
の設定には、SUPER
またはBINLOG_ENCRYPTION_ADMIN
権限が必要) - SETコマンドで切り替えた際は、実行時点でバイナリログがローテーションする。
- バイナリログが暗号化されているかどうかは
SHOW BINARY LOGS
の出力結果項目Encrypted
で確認できる。 - MySQL Community Edition ではマスターキーデータはローカルファイルに保存する。
- MySQL Enterprise Edition では
Oracle Key Vault
やAmazon Web Services Key Management Service
等でマスターキーを管理できる。 binlog_rotate_encryption_master_key_at_startup
を有効にする事で、MySQLサーバを再起動する度にマスターキーをローテーションさせる事ができる。
(デフォルト無効)- 暗号化されたバイナリログ、リレーログを対象に mysqlbinlog 実行時は、
--read-from-remote-server
オプション指定が必要。
(実行ユーザにREPLICATION SLAVE
権限が必要) - 暗号化されたバイナリログもしくは、リレーログをバックアップする際はキーリングファイルのバックアップも忘れずに。
- 暗号化を有効にする事による、性能劣化やリソースの上昇は、ほぼ見られなかった。
最近のMySQLでは、メジャーバージョン内でのバージョンアップにおいても、注目されそうな機能リリースが入っていたりするので、見落とさずに確認していきましょう。