Шифрование хранимых данных в MySQL 5.7

Для защиты конфиденциальных данных в MySQL 5.7 появилась возможность шифрования данных с помощью движка InnoDB. В этой статье я объясню принципы шифрования баз данных, используя конкретные примеры.

Шифрование на уровне базы данных

Шифрование всей системы может быть неоправданно дорогим, когда нужно защитить лишь часть данных. Также не всегда возможно изменить код и разработать механизм шифрования на уровне приложения. В таких случаях важно использовать шифрование на уровне базы.

Шифрование данных в MySQL 5,7 имеет следующие преимущества:

  • Надежное шифрование AES-256 для таблиц InnoDB;
  • Прозрачное для приложений. Отсутствие кода для приложения, схемы. Нет необходимости изменять тип данных;
  • Прозрачное для администраторов баз данных. Ключи не управляются администраторами баз данных;
  • Управление ключами. Ключи можно безопасно хранить отдельно от данных, а смена ключей является простой.

MySQL 5.7 свойственно шифрование только таблиц InnoDB, при этом остаются открытыми следующие файлы: binlogs, redo logs, relay logs, slow log, error log, general log, и audit log.

Еще один заслуживающий внимания фактор — защита главного ключа внутри ключевого файла. Если главный ключ является составным, то механизм безопасности данных открыт для утечек. Решить проблему можно поместив файл ключа в раздел, который может быть отключен при запуске MySQL (каталог, подключаемый только во время запуска базы данных). Важно не потерять ключевой файл вместе с главным ключом, так как не будут осуществлено шифрование базы данных MySQL.

Пример

Начнем с того, что разрешим шифрование MySQL, добавив следующие параметры в файл конфигурации my.cnf.

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

Следующим шагом является запуск службы и проверка активности плагина.

mysql> SELECT plugin_name, plugin_status
FROM INFORMATION_SCHEMA.PLUGINS
WHERE plugin_name LIKE 'keyring%';

+--------------+---------------+
| plugin_name  | plugin_status |
+--------------+---------------+
| keyring_file | ACTIVE        |
+--------------+---------------+

Мы также можем проверить настройки шифрования баз данных.

mysql> show global variables like '%keyring%';
+-------------------+------------------------+
| Variable_name     | Value                  |
+-------------------+------------------------+
| keyring_file_data | /var/lib/mysql/keyring |
+-------------------+------------------------+

Чтобы зашифровать таблицы в InnoDB, следует убедиться в том, что параметр innodb_file_per_table включен (ON).

mysql> show global variables like 'innodb_file_per_table';

+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+

Если этот параметр выключен (OFF), нужно добавить следующие параметры для файла конфигурации my.cnf, и перезапустить службу.

[mysqld]
innodb_file_per_table=ON

Рассмотрим шифрование базы данных MySQL в действии. Создадим таблицу для хранения конфиденциальных данных.

mysql> CREATE TABLE sample_db.sensitive_data_tb (
 id int primary key auto_increment,
 payload varchar(256)
) engine=innodb;

Добавляем строку к таблице.

mysql> INSERT INTO sample_db.sensitive_data_tb(payload)
VALUES('Private sensitive data');

Используем команду strings, чтобы извлечь каждую строку символов в двоичном файле, который относится к таблице sensitive_data_tb.

$ strings /var/lib/mysql/sample_db/sensitive_data_tb.ibd

infimum
supremum
Private sensitive data

Также можно проверить, что ключевой файл пуст (нет главного ключа).

$ cat /var/lib/mysql/keyring

Чтобы использовать шифрование баз данных в таблице sensitive_data_tb, нужно сменить таблицу.

mysql> ALTER TABLE sample_db.sensitive_data_tb encryption='Y';

Если мы попытаемся вывести таблицу sensitive_data_tb, то увидим, что теперь данные зашифрованы, и их невозможно увидеть из файловой системы.

$ strings /var/lib/mysql/sample_db/sensitive_data_tb.ibd

bbf7aee4-a14a-11e6-8d4c-080027001884
{i<|4w
RMt_

Хотя мы не можем видеть данные из файловой системы, их можно увидеть из MySQL, используя традиционный оператор SQL.

mysql> SELECT * FROM sample_db.sensitive_data_tb;

+----+------------------------+
| id | payload                |
+----+------------------------+
|  1 | Private sensitive data |
+----+------------------------+

Также можно проверить, что главный ключ генерируется в MySQL.

$ cat /var/lib/mysql/keyring

Keyring file version:1 XXXX

Можно сменить главный ключ шифрования базы данных MySQL, выполнив инструкцию alter instance.

mysql> alter instance rotate innodb master key;

Можно верифицировать смены ключа, проверив временную отметку ключевого файла.

$ ls -al /var/lib/mysql/keyring

Просмотреть список зашифрованных таблиц, можно выполнив запрос.

mysql> SELECT *
FROM information_schema.tables
WHERE create_options LIKE '%ENCRYPTION="Y"%';

Заключение

В этой статье я объяснил принципы шифрования данных на уровне базы в новой версии MySQL. Также я продемонстрировал их на реальных примерах. Теперь вы можете применять эти принципы и приведенные примеры для защиты конфиденциальной информации.