Шифрование наших резервных копий: выход на финишную прямую

Опубликовано: 2017-09-02

Примечание. Этот инженерный пост был написан нашим администратором базы данных Сильвией Ботрос. Ознакомьтесь с некоторыми другими ее постами DBA здесь.

Год назад SendGrid усердно работал над сертификацией SOC2. Все были вовлечены. Почти на каждой доске команды доставки были истории с тегом SOC2, поскольку мы все хотели пройти сертификацию к концу третьего квартала. Как вы можете себе представить, будучи лицом, ответственным за базы данных, определенно нужно было проделать некоторую работу для этой части стека.

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

При тестировании этого подхода я обратил внимание на несколько важных моментов:

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

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

Отслеживание времени резервного копирования

SendGrid использует Graphite для своих метрик инфраструктуры, и хотя подавляющее большинство отправляются через Sensu, Graphite достаточно прост для отправки метрик напрямую через строки bash — очень удобно, поскольку сценарии резервного копирования находятся в bash. Обратите внимание, что отправка метрик напрямую в Graphite не является супер масштабируемой, но, поскольку эти резервные копии выполняются не чаще одного раза в час, это вполне соответствовало моим потребностям.

Эта часть оказалась относительно легкой.

Чтобы объяснить, что произошло в последней строке, я отправляю Graphite путь к отправляемой метрике (убедитесь, что она уникальна), значение метрики, а затем текущее время в формате эпохи. Netcat — это то, что я решил использовать для простоты, и я даю ему тайм-аут в 1 секунду, потому что в противном случае он никогда не завершится. «URL-адрес графита» — это наша конечная точка DNS для Graphite в центре обработки данных.

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

Следуя подробной документации Percona о том, как это сделать, я начал с создания ключа. Если вы внимательно прочитаете эту страницу документации, вы можете кое-что понять.

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

Тесты с очень маленькими БД, в несколько сотен МБ, прошли успешно. Инструмент работает, как и ожидалось, и задокументирован, но это был скорее функциональный тест, и реальный вопрос заключался в том, «каков размер штрафа за шифрование в наших больших БД?» Более устаревшие экземпляры в SendGrid выросли до размера от 1-2 ТБ до одного зверя на 18 ТБ. То, что я собирался использовать для небольших экземпляров, также должно было быть приемлемо с точки зрения эксплуатации на более крупных экземплярах.

Вот где тестирование и тесты стали интересными

Мой первый объект тестирования значительного размера — это наша база данных размером 1 ТБ на диске. Очень быстро я столкнулся с неожиданной проблемой. С минимальными настройками шифрования (1 поток, размеры блоков по умолчанию) я видел, как резервное копирование завершалось с ошибкой:

В то время эти базы данных использовали 512 МБ в качестве размера файла журнала транзакций, а это довольно загруженный кластер, поэтому эти файлы менялись почти каждую минуту. Обычно это было бы заметно по производительности БД, но в основном это было замаскировано чудом твердотельных накопителей. Похоже, что отсутствие параллельных потоков шифрования (читай: использование одного) означает, что мы тратим так много времени на шифрование файлов `.ibd`, что журнал повторов innodb из-под нас прерывает резервное копирование.

Итак, давайте попробуем это снова с несколькими потоками шифрования. В качестве первой попытки я попробовал 50 потоков. Хитрость здесь заключается в том, чтобы найти золотую середину быстрого шифрования, не конкурируя за процессор. Я также увеличил размер ib_logfiles до 1 ГБ каждый.

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

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

Нам нужно было вернуться к более разумным временным рамкам.

Именно здесь проявилась командная работа и более простые решения проблем. Один из членов нашей команды InfoSec решил посмотреть, можно ли упростить это решение. Поэтому он провел еще несколько тестов и вернулся с чем-то более простым и безопасным. Я еще не знал о gpg2, поэтому для меня это тоже стало обучающим упражнением.

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

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

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

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

  • Это было асимметрично
  • Его секретное управление для расшифровки относительно легко меняется (подробнее об этом ниже).
  • Это средство не зависит от инструмента, что означает, что любой другой вид резервного копирования, не использующий xtrabackup, может использовать тот же метод.
  • Он использовал несколько ядер для расшифровки, что дало нам лучшее время восстановления.

Всегда есть возможности для улучшения

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

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