はじめに
MySQL 5.7.11 以降では、透過的テーブルスペース暗号化が実装されています。また、MariaDB 10.1.3 以降でも、Data at Rest Encryption というデータベースレベルの暗号化が実装されていますが、MySQL とは設定方法や範囲などが異なります。ここでは、それぞれの機能の違いについて、実際の手順を確認しながら調査をしてみました。
MySQL – 透過的テーブルスペース暗号化
InnoDB supports data encryption for InnoDB tables stored in file-per-table tablespaces. This feature provides at-rest encryption for physical tablespace data files.
引用元 : 14.7.10 InnoDB Tablespace Encryption
MySQL では、InnoDB のテーブルスペースを透過的に暗号化することが可能です。また、MySQL 5.7.18 現在、暗号化することができるのは innodb_file_per_table を有効にした際のテーブル毎の .ibd ファイルのみで、共有テーブルスペース(Undo ログなど)や InnoDB ログファイルといったログ系のファイルは暗号化できません。
暗号化は以下のような、マスター暗号化キーとテーブルスペースキーからなる 2 層構造になっています。 InnoDB テーブルが暗号化されると、テーブルスペースキーが作成/暗号化されて、テーブルスペースのヘッダーに格納されます。暗号化されたテーブルスペースのデータにアクセスする場合、InnoDB はマスター暗号化キーを使用してテーブルスペースキーを解読します。テーブルスペースキーのバージョンはテーブルの作成後は変更されませんが、マスター暗号化キーは必要に応じて変更することができます(“master key rotation”)。
透過的テーブルスペース暗号化には keyring_file プラグインが使用されているため、あらかじめインストールしてから設定を行っていきます。
検証環境
- CentOS 7.2
- MySQL 5.7.18
[1] プラグインのインストール
1 |
mysql> INSTALL PLUGIN keyring_file SONAME 'keyring_file.so'; |
MySQL 5.7.11 ではデフォルトのプラグインでしたが、5.7.12 以降はデフォルトで入っていないので明示的にインストールする必要があります。
あるいは、MySQL を起動する前に、my.cnf に以下の内容を追記しておきます。
1 2 3 4 5 6 |
[mysqld] #MySQL5.6 以降はデフォルトで有効 innodb_file_per_table=1 early-plugin-load=keyring_file.so keyring_file_data=/var/lib/mysql-keyring/keyring |
※keyring_file_data のデフォルト値は環境によって変化します
[2] 確認
1 2 3 4 5 6 |
mysql> SELECT PLUGIN_NAME,PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'keyring%'; +--------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +--------------+---------------+ | keyring_file | ACTIVE | +--------------+---------------+ |
[3] 暗号化テーブルの作成/テーブルの暗号化
ENCRYPTION=’Y’ を指定することで暗号化テーブルを作成できます。
1 |
mysql> CREATE TABLE t1 (id INT) ENCRYPTION='Y'; |
既存のテーブルを暗号化する場合も、ALTER TABLE で同様に ENCRYPTION=’Y’ を指定できます。
1 |
mysql> ALTER TABLE t1 ENCRYPTION='Y'; |
■ マスター暗号化キーのローテーション方法
1 |
mysql> ALTER INSTANCE ROTATE INNODB MASTER KEY; |
マスター暗号化キーをローテートすると、既存の暗号化テーブルについても、テーブルスペースキーの暗号化情報が新しいものに書き換えられます。
MariaDB – Data at Rest Encryption
MariaDB encryption is fully supported for the XtraDB and InnoDB storage engines. Additionally, encryption is supported for the Aria storage engine, but only for tables created with ROW_FORMAT=PAGE (the default).
MariaDB allows the user to configure flexibly what to encrypt. In XtraDB or InnoDB, one can choose to encrypt:
everything ? all tablespaces (with all tables)
individual tables
everything, excluding individual tables
Additionally, one can choose to encrypt XtraDB/InnoDB log files (recommended).
引用元 : Data at Rest Encryption ― Which storage engines does MariaDB encryption support?
MariaDB では、XtraDB/InnoDB のテーブルスペースに加えて、Undoログスペースや InnoDB ログファイル、バイナリログ/リレーログなども暗号化することができます。
暗号化には file_key_management プラグインが使用されており、以下のようなキーファイルに各テーブルのキーが格納されています。また、キーファイルは暗号化されていてもよく、ファイルを解読するためのキーをさらに設定することができます。テーブルを暗号化する際には、キーファイルの ID を指定することで使用するキーを指定します(デフォルト値は innodb_default_encryption_key_id = 1
)。なお、キーファイルのローテーションには対応していません。
Data at Rest Encryption を利用するためには、あらかじめ file_key_management プラグインをインストールします。また、事前にキーファイルや設定ファイル(my.cnf)を作成/設定しておく必要があります。
file_key_management プラグインでは、以下の設定オプションがあります。
value | detail |
---|---|
file_key_management_filename | キーファイル名。このオプションは必須ですが、プラグインがない場合に設定するとエラーになります。 |
file_key_management_filekey | キーファイルを解読するオプションのキー。キーが FILE: で始まる場合、残りの値はキーを含むファイルへのパスとして解釈されます。 |
file_key_management_encryption_algorithm | 使用する暗号化アルゴリズム。AES_CBC(デフォルト値)または AES_CTR を指定できます。 |
なお、SHOW コマンドでパスワードが読み取られないように、file_key_management_filekey にはファイルを指定し、適切なパーミッションを設定することを推奨します。
検証環境
- CentOS 7.2
- MariaDB 10.1.23
[1] キーファイルの作成
キーファイルには、セミコロンで区切られた ID(32 ビットの数字)と 16 進数の暗号化キーで構成されています。暗号化キーは 128/192/256 ビットのキー長がサポートされています。
1 2 3 4 |
1;32A94731D84A0D25C298EAB0D496EA05BF73761AA77917463E238528EF24F119 2;7C30299F0BE1D41BA5C245740D9DA6A437E33B02134ADD6BE9519E4EBBE8ED6E 3;00000000000000000000000000000000 4;0F04165A1B293C115A59B231E0AEC281EC39B9A4A386628178CB23F58239EC51 |
例えば、1 はテーブルの作成に使用できるキーの ID で、セミコロンの後に 16 進数で暗号化キーが続きます。
キーID はテーブルごとに指定できますが、XtraDB/InnoDB のシステムテーブルスペースやログファイルは、キーID 1 を使用するため、常に存在する必要があります。また、キーID 2 はオプションですが、存在する場合は、一時テーブルや一時ファイルの暗号化時に使用されます。なお、キーのローテーションはサポートされていません。このキーファイルが存在しないなどの理由で、サーバーの起動時にキーファイルを読み取れない場合は、暗号化は機能せず、暗号化されたテーブルは読み取れなくなるので注意してください。
暗号化キーを作成する場合、以下のコマンドを実行して、その key 部分を流用することができます。
1 2 3 4 |
[root@mariadb ~]# openssl enc -aes-256-cbc -k Password@generate -P -md sha256 salt=4DB5ACE8641CBA3B key=0F04165A1B293C115A59B231E0AEC281EC39B9A4A386628178CB23F58239EC51 iv =FF0F0A6D219766F557876590C209DC01 |
[2] キーファイルの暗号化
もし必要であれば、作成したキーファイルを以下のコマンドで暗号化することができます。なお、aes-256-cbc および sha1 以外では、キーファイルの復号化に対応していないので注意してください。
1 |
[root@mariadb ~]# openssl enc -aes-256-cbc -md sha1 -k secret -in /etc/keys.txt -out /etc/keys.enc |
file_key_management_filekey を FILE: として設定する場合は、キーファイルのパスワード(ここでは “secret”) をファイル(/etc/secret.txt)に記述して、適切なパーミッションを指定してください。
1 2 |
[root@mariadb ~]# chown mysql:mysql /etc/secret.txt [root@mariadb ~]# chmod 400 /etc/secret.txt |
[3] 設定ファイル(my.cnf)への追記&プラグインのインストール
my.cnf に以下のパラメーターを追記して MariaDB を起動することで、file_key_management プラグインをインストールすることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[mysqld] plugin-load-add = file_key_management.so file-key-management-filename = /etc/keys.enc file_key_management_filekey = FILE:/etc/secret.txt file_key_management_encryption_algorithm = AES_CBC #テーブルの暗号化...ON:有効、OFF:無効、FORCE:暗号化が設定されていないテーブルの作成を許可しない innodb-encrypt-tables = ON #InnoDB/XtraDB ログファイルの暗号化...1:有効、0:無効 innodb-encrypt-log = 1 #一時テーブルの暗号化...1:有効、0:無効 encrypt-tmp-disk-tables = 1 #一時ファイルの暗号化...1:有効、0:無効 encrypt-tmp-files = 1 #バイナリログ/リレーログの暗号化...1:有効、0:無効 encrypt-binlog = 1 |
あるいは、既に稼働している MariaDB の再起動を行わないで暗号化を有効にしたい場合は、plugin-load-add 以外のパラメーターを設定ファイルに追記した後、以下のコマンドを実行します。
1 |
mysql> INSTALL PLUGIN file_key_management SONAME 'file_key_management.so'; |
[4] 暗号化テーブルの作成/テーブルの暗号化
ENCRYPTION=YES および使用するキーの ID を ENCRYPTION_KEY_ID に指定することで、暗号化テーブルを作成できます。なお、ENCRYPTION_KEY_ID を指定しない場合は、innodb_default_encryption_key_id
の値が使用されます。
1 |
mysql> CREATE TABLE t1 (id INT) ENCRYPTED=YES ENCRYPTION_KEY_ID=3; |
既存のテーブルを暗号化する場合も、ALTER TABLE で同様に ENCRYPTION=YES と ENCRYPTION_KEY_ID を指定できます。
1 |
mysql> ALTER TABLE t1 ENCRYPTED=YES ENCRYPTION_KEY_ID=3; |
課題点
MySQL と MariaDB のどちらも、root/mysql ユーザーがキーファイルやマスター暗号化キーファイルを読み出せてしまうので、セキュリティ上の問題となります。この問題については、MySQL/MariaDB の起動時にキーファイルがメモリー上に読み込まれるため、キーファイルをマウントされたドライブ上に置いて、起動後にアンマウントすることで対処可能です。しかし、この場合、クラッシュした際に自動で再起動されず、手動で復旧する必要があります。なお、MySQL であれば keyring_okv プラグインを、MariaDB であれば Amazon Web Services (AWS) Key Management Service (KMS) Encryption Plugin を使用することで、キーの管理を行うことができるので、PCI DSS や HIPAA などの高いセキュリティ基準も満たすことができます(どちらも有償版でのみ使用可能です)。
また、MariaDB でバイナリログを暗号化した場合、mysqlbinlog コマンドを使用して中身を確認することができなくなってしまいます。Percona XtraBackup というバックアップツールについても、MariaDB のテーブルスペース暗号化に対応していないため、実行すると以下のようなエラーとなってしまいます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
(...) 170523 10:23:23 [01] Copying ./test/t1.ibd to /tmp/backup/test/t1.ibd [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Database page corruption detected at page 1, retrying... 170523 10:23:23 >> log scanned up to (94518444) [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Database page corruption detected at page 1, retrying... [01] xtrabackup: Error: failed to read page after 10 retries. File ./test/t1.ibd seems to be corrupted. [01] xtrabackup: Error: xtrabackup_copy_datafile() failed. [01] xtrabackup: Error: failed to copy datafile. |
まとめ
MySQL の暗号化は「透過的」という名前のとおり、暗号化の仕組みについて意識せずとも簡単に設定することができました。一方の MariaDB では、MySQL に比べると手順が煩雑ですが、InnoDB/XtraDB ログファイルを含めて多岐にわたるファイルを任意に暗号化することができるので、セキュリティを重視する場合には優位性があります。
なお、余談ですが、MySQL 8.0 では 共有テーブルスペース(Undo ログなど)や InnoDB ログファイルを含めたテーブルスペース暗号化ができるようになるようです。また、MariaDB 10.1.23 では、MariaDB の暗号化や圧縮機能に対応したバックアップツールである MariaDB Backup がアルファ版として公開されました。今後どのように暗号化機能が進歩していくのか、MySQL/MariaDB の動向が注目されます。
参考 URL
Percona Database Performance Blog ― MySQL Data at Rest Encryption
MariaDB Knowledge Base ― Data at Rest Encryption
MySQL 5.7 Reference Manual ― 14.7.10 InnoDB Tablespace Encryption