Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
8年以上前投稿 修正あり

MySQLの保存データ暗号化(Percona Data Performance Blogより)

MySQLで保存データ暗号化(Data at Rest Encryption)を行うための手法についてのPercona Data Performance Blogの記事を紹介します。 MariaDBとMySQL/Percona Serverの暗号化の違いや注意点とは。

原文
MySQL Data at Rest Encryption - MySQL Performance Blog (English)
翻訳依頼者
B5aa4f809000b9147289650532e83932
翻訳者
B5aa4f809000b9147289650532e83932 taka-h
翻訳レビュアー
D98ee74ffe0fafbdc83b23907dda3665 doublemarket
原著者への翻訳報告
未報告


出典について

この記事はThe Percona Data Performance Blog内のAlexander Rubin氏によるMySQL Data at Rest Encryption(2016/4/8)を翻訳したものです。


このブログ投稿はMySQLの保存データ暗号化(Data at Rest Encryption)手法についての記事です。

保存データ暗号化はあったほうがいい、というだけでなく、HIPAA、PCIその他の法規で必要とされます。

保存データ暗号化を行うためには主に3つの方法があります。

  • フルディスク暗号化
  • データベース(テーブル)レベル暗号化
  • アプリケーションレベル暗号化。データがデータベースに挿入される前に暗号化されます。

フルディスク暗号化は、誰かがディスクをサーバー上から物理的に持ち去るケースしか防ぐことしかできないため、最も強度の弱い方法です。一方で、アプリケーションレベルの暗号化は最善の方法です。ほとんどオーバーヘッドを発生させることなく伝送中のデータの暗号化も含め柔軟に行えるためです。残念なことに、アプリケーションのソースコードはアプリケーションレベルの暗号化を行うため常に変更できるとは限らないため、データベースレベル暗号化は非常に重要な代替手段となりえます。

MariaDBのチーフアーキテクトであるSergei Golubchik氏はPercona Live Amsterdamのセッションでデータベース暗号化の長所、短所について次のように述べています。

  • 長所
    • DBMSの全機能が利用できる
    • 実装しやすい
    • データベースからのみデータが閲覧できる
    • テーブル毎の暗号化、テーブル毎の鍵の設定ができる
  • 短所
    • ユーザーごとに実施できない
    • 悪意あるrootユーザーから保護できない

保存データ暗号化: データベースレベル暗号化の選択肢

現在のところ、データベースレベルで保存データ暗号化を行う方法は2つあります。

MariaDBの実装はMySQL 5.7.11とは異なるものです。MySQL 5.7.11はInnoDBのテーブルスペースのみを暗号化する一方で、MariaDBはUNDO/REDOログ、バイナリーログ/リレーログなどを暗号化するかどうか選択できます。しかし、いくつか制限事項があります(とりわけ、Galera Clusterと一緒に利用する場合)。

  • オープンソースのプラグインバージョンではキーのローテーション機能がない(MySQL 5.7.11にはキーのローテーションあり)
  • 暗号化したバイナリログに対してmysqlbinlogが動作しない(報告済みのバグ)
  • Percona XtraBackupが動作しないため、Galera ClusterのSSTがブロッキングメソッドであるrsyncに限定される(SSTの間、1ノード利用できない)。最新のPercona XtraBackupはMySQL 5.7.11のテーブルスペース暗号化で正常に動作。
  • 次のデータが暗号化されない(報告済みのバグ)
    • Galera gcacheとGaleraのレプリケーションデータ
    • 一般クエリーログ/スロークエリーログ

データベースレベルの暗号化には次の2つの弱点があります。

  1. rootおよびMySQLのユーザーはキーリングファイルを読み出し可能でこれは目的からすると大きな問題です。しかしながら、キーをマウントされたドライブ上に置きMySQL起動後にアンマウントする(これはスクリプト化可能)ことは可能です。しかし、MySQLがクラッシュした際に自動で再起動されず、人の介在が必要となってしまう問題があります。
  2. MariaDBのバージョンとMySQLのバージョンはディスクに書いたデータのみを暗号化しRAM上のデータは暗号化しないので、rootユーザーはMySQLにgdb/straceあるいは他のツールをMySQLにアタッチしてサーバー上のメモリを読むことができます。その上、gdbを使えばrootユーザーのパスワードを変更することが可能で、パスワードを変更してからmysqldumpを実行すればデータがコピーできてしまいます。その他の可能性として、MySQLをkillしてskip-grant-tablesオプションで起動される可能性もあります。キーがアンマウントされていれば(例えばUSBドライブにある、など)、MySQLは起動できませんし、したがって暗号化されたテーブルスペースのデータも読み込めません。

MariaDBの暗号化の例

可能な暗号化をすべて実施するためには次のようなオプションをmy.cnfに記載します。

[mysqld]
plugin-load-add=file_key_management.so
file_key_management_filekey = FILE:/mount/keys/mysql.key
file-key-management-filename = /mount/keys/mysql.enc
innodb-encrypt-tables = ON
innodb-encrypt-log = 1
innodb-encryption-threads=1
encrypt-tmp-disk-tables=1
encrypt-tmp-files=1 
encrypt-binlog=1
file_key_management_encryption_algorithm = AES_CTR

MariaDBをこの設定で起動したのちに、データベースの暗号化がバックグラウンドで開始されます。 file_key_managementプラグインが利用され、これは残念なことにキーのローテーションをサポートしていません。キーは次のように暗号化されます。

# openssl enc -aes-256-cbc -md sha1 -k <キー> -in keys.txt -out mysql.enc

暗号化 <キー> は/mount/keys/mysql.keyに配置されます。

MySQLを起動後には"/mount/key"パーティションをアンマウントできます。こうすればたとえハッカーが侵入してもキーは利用できませんし、MySQLを"--skip-grant-tables"オプションでパスワードなしに再起動することもできません。しかし一方で通常の再起動ができなくなり、とりわけSST(クラスターの全同期)の場合に影響があります。

追加の注意点としては次の通りです。

  1. 暗号化は圧縮率に対して影響を与え、これは物理バックアップに影響があります(mysqldumpなどの論理バックアップはデータを暗号化しないで扱うため影響がありません)。暗号化前にバックアップがデータベースサイズの10%に圧縮できていたとしても、暗号化されたテーブルは同様の圧縮率では圧縮できません。
  2. データは伝送中に暗号化されず、したがってスレーブに同じオプションを有効にしない限りレプリケーションスレーブで暗号化されません。暗号化はサーバーに対して局所的であり、サーバーで有効化した直後には、あるテーブルでは暗号化されていないかもしれません(最終的には暗号化されます)。
  3. どのテーブルが暗号化されているかを確認するためには、INFORMATION_SCHEMAのINNODB_TABLESPACES_ENCRYPTIONテーブルに暗号化の情報がありますのでこれをご利用ください。暗号化されている全テーブルを表示するには次のクエリをご利用ください。
select * from information_schema.INNODB_TABLESPACES_ENCRYPTION where ENCRYPTION_SCHEME=1

MySQL 5.7の暗号化の例

暗号化を有効化するには次のオプションをmy.cnfに記載します。

[mysqld]
early-plugin-load=keyring_file.so
keyring_file_data=/mount/mysql-keyring/keyring

再度となりますが、MySQLを再起動した後に、"/mount/mysql-keyring"パーティションをアンマウントすることができます。

MySQLはデフォルトではテーブルを暗号化しないため、テーブルを暗号化させるためには、alter table テーブル名 encryption='Y'を実行する必要があります。

最新のPercona Xtrabackupも暗号化をサポートしており、暗号化したテーブルのバックアップが取得できます。

MySQLあるいはPercona Serverの5.7.11で暗号化された全テーブルスペースを確認するには、information_schema.INNODB_SYS_TABLESPACESおよびflagフィールドを利用してください。例えば、デフォルトの設定で暗号化されたテーブルを探すには次のクエリを発行します。

mysql> select * from information_schema.INNODB_SYS_TABLESPACES where flag = 8225G
*************************** 1. row ***************************
         SPACE: 4688
          NAME: test/t1
          FLAG: 8225
   FILE_FORMAT: Barracuda
    ROW_FORMAT: Dynamic
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Single
 FS_BLOCK_SIZE: 4096
     FILE_SIZE: 98304
ALLOCATED_SIZE: 98304
*************************** 2. row ***************************
         SPACE: 4697
          NAME: sbtest/sbtest1_enc
          FLAG: 8225
   FILE_FORMAT: Barracuda
    ROW_FORMAT: Dynamic
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Single
 FS_BLOCK_SIZE: 4096
     FILE_SIZE: 255852544
ALLOCATED_SIZE: 255856640
2 rows in set (0.00 sec)

次のクエリを発行しても良いでしょう。

select * from information_schema.tables where CREATE_OPTIONS like '%ENCRYPTION="Y"%';.

パフォーマンスのオーバーヘッド

これはよく議論になる問題で、とりわけ全てが暗号化されるように設定されるMariaDBでは問題となります。私が試した範囲ではスタンドアローンのMySQLインスタンスで〜10%のオーバーヘッド、Galera Clusterでは〜20%のオーバーヘッドがみられました。

MySQL 5.7とPercona Server 5.7のテーブルスペースレベルの暗号化は極めて小さいオーバーヘッドでしたが、これは違う条件で試す必要があります。

まとめ

上記の全ての制約が発生したとしても、データベースレベルの暗号化はアプリケーションが変更できないならばファイルシステムレベルの暗号化より良い選択肢です。しかし、これは新しい機能で(とりわけMySQL 5.7.11では)、バグがたくさんあるのではないかと考えています。

次の記事
InfluxDB、Telegraf、Kapacitor 0.12のお知らせ - クエリーのkillと新機能(InfluxData Blogより)
前の記事
MySQL 5.7の一般表領域 : 詳細とTips (MySQL Server Blogより)

Feed small 記事フィード

新着記事Twitterアカウント