Tde В Apache Ignite: История Основной Функции В Большом Проекте С Открытым Исходным Кодом

Многим организациям, особенно финансовым, приходится иметь дело с различными стандартами безопасности, такими как PCI DSS. Такие сертификаты требуют шифрования данных.

Прозрачное шифрование данных на диске реализовано во многих промышленных СУБД.

Apache Ignite используется в банках, поэтому было решено внедрить TDE в нем.

Я расскажу вам, как мы разрабатывали TDE через сообщество, публично, через процессы Apache. Ниже представлена текстовая версия отчета: Я постараюсь рассказать об архитектуре, сложности разработки, о том, как это на самом деле выглядит в open source.



Что сделано и что предстоит?

Apache Ignite TDE в настоящее время реализован.

Фаза 1. Он включает в себя базовые возможности по работе с зашифрованными кэшами:

  • Ключевой менеджмент
  • Создание зашифрованных кешей
  • Сохранение всех данных кэша на диск в зашифрованном виде
На втором этапе планируется включить возможность ротации (изменения) мастер-ключа.

На этапе 3 появилась возможность ротации ключей кэша.



Терминология

  • Transparent Data Encryption – прозрачное (для пользователя) шифрование данных при сохранении на диск.

    В случае с Ignite — шифрование кэша, потому что Ignite — это кэши.

  • Кэш Ignite — это кеш «ключ-значение» в Apache Ignite. Данные кэша могут быть сохранены на диск
  • Страницы — страницы данных.

    В Ignite все данные разделены на страницы.

    Страницы записываются на диск и должны быть зашифрованы.

  • WAL - предварительная запись журнала.

    Там сохраняются все изменения данных в Ignite, все действия, которые мы совершали для всех кэшей.

  • Keystore — это стандартное хранилище ключей Java, создаваемое Java keytool. Он работает и сертифицирован везде, где мы его использовали.

  • Мастер-ключ – мастер-ключ.

    Он используется для шифрования ключей таблиц и кэширования ключей шифрования.

    Хранится в хранилище ключей Java.

  • Ключи кэша — это ключи, с помощью которых данные фактически шифруются.

    Вместе с отмычкой получается двухуровневая структура.

    Мастер-ключ хранится отдельно от ключей кэша и основных данных — в целях безопасности, разделения прав доступа и т. д.



Архитектура

Все было реализовано по следующей схеме:
  • Все данные кэша шифруются с помощью нового Encryption SPI.
  • По умолчанию используется AES, промышленный алгоритм шифрования.

  • Мастер-ключ хранится в файле JKS — стандартном Java-файле ключей.

Банки и другие организации используют собственные алгоритмы шифрования: ГОСТ и другие.

Понятно, что мы предусмотрели возможность подсунуть собственный Encryption SPI — ту реализацию шифрования, которая нужна конкретному пользователю.



Схема работы



TDE в Apache Ignite: история основной функции в большом проекте с открытым исходным кодом

Итак, у нас есть ОЗУ — оперативная память со страницами, содержащими чистые данные.

Использование оперативной памяти означает, что мы не защищаемся от хакера, который получил root-доступ и сбросил всю память.

Защищаемся от администратора, который берет жесткий диск и продает его на Тушинском рынке (или там, где сейчас продаются подобные данные).

Помимо страниц кэша, данные также сохраняются в журнале упреждающей записи, который записывает на диск дельту записей, измененных в ходе транзакции.

В хранилище метаданных хранятся ключи шифрования кэша.

И в отдельном файле есть мастер-ключ.

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

Чтобы никто не мог получить ключ кэша путем получения данных Ignite. Только украв мастер-ключ и данные, вы сможете получить к ним доступ.

Это маловероятно, поскольку для доступа к этим файлам требуются разные разрешения.

Алгоритм действий следующий:

  • При запуске ноды читаем мастер-ключ из jks.
  • При запуске узла мы читаем метахранилище и расшифровываем ключи кэша.

  • При объединении узлов в кластер: — проверяем хеши мастер-ключа.

    — проверяем ключи для общих кешей.

    — сохраняем ключи для новых тайников.

  • При динамическом создании кеша мы генерируем ключ и сохраняем его в метахранилище.

  • При чтении/записи страницы мы ее расшифровываем/шифруем.

  • Мы также шифруем каждую запись WAL для зашифрованного кеша.

Теперь более подробно: Когда узел запускается, у нас есть обратный вызов, который запускает наш EncryptionSPI. Мы в соответствии с параметрами читаем мастер-ключ из файла jks. Затем, когда метахранилище будет готово, мы извлекаем сохраненные ключи шифрования.

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

Отдельно есть очень интересный процесс — как нам объединить новую ноду в кластер.

У нас уже есть распределенная система, состоящая из нескольких узлов.

Как убедиться, что новый узел настроен правильно и что это не злоумышленник? Выполняем следующие действия:

  • Когда прибывает новый узел, он отправляет хэш главного ключа.

    Проверяем, что оно соответствует существующему

  • Затем проверяем ключи для общих кешей.

    Идентификатор кэша и зашифрованный ключ кэша поступают от узла.

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

    Если это не так, то мы просто не имеем права пускать ноду в кластер — иначе будет разброс ключей и данных.

  • Если у нового узла есть какие-то новые ключи и кэши, мы сохраняем их для дальнейшего использования.

  • При динамическом создании кэша предусмотрена функция генерации ключей.

    Генерируем его, сохраняем в метахранилище и дальше можем проводить описанные операции.

Вторая часть представляет собой дополнение к операциям ввода-вывода.

Страницы записываются в файл раздела.

Наше дополнение проверяет, из каких страниц кэша взяты, соответствующим образом шифрует их и сохраняет. То же самое касается WAL. Существует сериализатор, который сериализует объекты записей WAL. А если запись для зашифрованных кэшей, то мы должны ее зашифровать и только потом сохранять на диск.



Трудности в разработке

Трудности свойственны всем более или менее сложным проектам с открытым исходным кодом:
  1. Для начала нужно в общих чертах разобраться с устройством Ignite. Зачем, что и как там делалось, как и в какие места прикреплять свои процессоры.

  2. Нам необходимо обеспечить обратную совместимость.

    Это может быть довольно сложно и не очевидно.

    Когда вы разрабатываете продукт, который используют другие, нужно учитывать, что пользователи хотят без проблем обновляться.

    Обратная совместимость – это правильно и хорошо.

    Когда вы делаете такую большую модификацию, как TDE, вы меняете правила сохранения на диск и что-то шифруете.

    И нам предстоит поработать над обеспечением обратной совместимости.

  3. Еще один неочевидный момент связан с распространением нашей системы.

    Когда разные клиенты пытаются создать один и тот же кэш, необходимо согласовать ключ шифрования, поскольку по умолчанию будут сгенерированы два разных ключа.

    Мы решили эту проблему.

    Подробно вдаваться не буду — решение заслуживает отдельного поста.

    Теперь мы гарантированно используем один ключ.

  4. Следующее важное событие привело к большому количеству доработок, когда казалось, что все уже готово (звучит знакомо?) :).

    Шифрование имеет накладные расходы.

    У нас есть вектор инициализации — нулевые случайные данные, которые используются в алгоритме AES. Они хранятся в открытом виде, и с их помощью мы увеличиваем энтропию: одни и те же данные в разных сеансах шифрования будут зашифрованы по-разному.

    Грубо говоря, даже если у нас есть два Ивана Петрова с одинаковой фамилией, то каждый раз при шифровании мы будем получать разные зашифрованные данные.

    Это снижает вероятность взлома.

    Шифрование происходит блоками по 16 байт, и если данные не выровнены по 16 байт, то мы добавляем информацию о дополнении — сколько данных мы на самом деле зашифровали.

    Вам необходимо записать на диск страницу размером кратным 2 КБ.

    Таковы требования к производительности: мы должны использовать дисковый буфер.

    Если мы запишем не 2 КБ (не 4 и не 8, в зависимости от буфера диска), то сразу получим большое падение производительности.

    Как мы решили проблему? Пришлось зайти в PageIO, в оперативную память, и отрезать от каждой страницы по 16 байт, которые бы шифровались при записи на диск.

    Записываем вектор инициализации в эти 16 байт.

  5. Еще одна сложность – ничего не сломать.

    Это обычное дело, когда вы приходите и вносите какие-то изменения.

    На самом деле все не так просто, как кажется.

  6. MVP получился 6 тысяч строк.

    Пересматривать сложно, да и мало кто хочет этим заниматься, особенно специалисты, у которых и так нет времени.

    У нас есть разные части — общедоступный API, основная часть, менеджеры SPI, постоянное хранилище страниц, менеджеры WAL. Изменения в разных подсистемах требуют, чтобы их анализировали разные люди.

    И это тоже накладывает дополнительные трудности.

    Особенно, когда вы работаете в сообществе, где каждый занят своими делами.

    Тем не менее, нам это удалось.



Что произойдет в TDE.Фазы 2 и 3

Фаза 1 уже реализована.

Вы, как разработчик, можете помочь на втором этапе.

Предстоящие задачи будут интересными.

PCI DSS, как и другие стандарты, требует дополнительных свойств системы шифрования.

Наша система должна иметь возможность менять мастер-ключ.

Например, если он был скомпрометирован или просто пришло время в соответствии с политикой безопасности.

Ignite не может сделать это прямо сейчас.

Но в следующих выпусках мы научим TDE менять мастер-ключ.

То же самое и с возможностью изменить ключ кэша без остановки кластера и работы с данными.

Если кеш долгоживущий и при этом хранит какие-то данные — финансовые, медицинские — Ignite должна иметь возможность менять ключ шифрования кеша и перешифровать все на лету.

Эту проблему мы решим на третьем этапе.



Итого: Как реализовать большую функцию в проекте с открытым исходным кодом?

Подведем итоги.

Они будут актуальны для любого открытого кода.

Я участвовал в Kafka и других проектах — история везде одна и та же.

  1. Начните с небольших задач.

    Никогда не беритесь за очень большую проблему сразу.

    Нам нужно разобраться, что происходит, как это происходит, как это реализуется.

    Кто вам поможет? И вообще – с какой стороны подойти к этому проекту.

  2. Понять проект. Обычно все разработчики — по крайней мере я — приходят и говорят: надо всё переписать.

    До меня все было плохо, но сейчас перепишу и все будет хорошо.

    С такими высказываниями желательно остановиться, разобраться, что именно плохо и нужно ли это менять.

  3. Обсудите, нужны ли улучшения.

    У меня были случаи, когда я приходил со своими работами в различные сообщества — например, в Spark. Я ему рассказал, но сообщество почему-то не заинтересовалось.

    Все может случиться.

    Вам нужно это улучшение, но сообщество говорит: нет, нам не интересно, мы не будем сливаться и помогать.

  4. Сделайте дизайн.

    Есть проекты с открытым исходным кодом, в которых это является обязательным.

    Вы не можете начать кодирование без проекта, согласованного коммиттерами и опытными людьми.

    В Ignite формально этого нет, но в целом это важная часть разработки.

    Вам необходимо составить описание на грамотном английском или русском языке, в зависимости от проекта.

    Чтобы текст был читабелен и из него было понятно, что именно вы собираетесь делать.

  5. Обсудите общедоступный API. Главный аргумент: если есть красивый и понятный публичный API, которым легко пользоваться, значит, дизайн правильный.

    Эти вещи обычно соседствуют друг с другом.

Ниже приведены более очевидные советы, которым может быть не так легко следовать:
  • Реализуйте функцию, ничего не нарушив.

    Делайте тесты.

  • Спрашивайте и ждите (это может быть самое сложное) отзывов от правильных ребят, от правильных участников сообщества.

  • Сделайте бенчмарки, выясните, есть ли у вас падение производительности.

    Это особенно важно при доработке некоторых критически важных подсистем.

  • Дождитесь мерджа, сделайте примеры и документацию.

Спасибо за прочтение! Теги: #с открытым исходным кодом #java #Apache #apache ignite
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.