Прозрачное шифрование данных (TDE) в Azure SQL с ключом, управляемым клиентом (Customer-Managed Key, CMK), поддерживает сценарий «принеси свой ключ» (Bring Your Own Key — BYOK) для защиты данных в состоянии покоя и даёт возможность разделения обязанностей по управлению ключами и данными. При клиентском управлении TDE пользователь отвечает за жизненный цикл ключей (создание, загрузка, ротация, удаление), права на их использование и аудит операций с ключами. Ключ, используемый для шифрования ключа шифрования базы данных (Database Encryption Key, DEK), называемый TDE-протектором, — это асимметричный ключ, которым управляет клиент и который хранится в Azure Key Vault.
После включения TDE с использованием ключа из Key Vault новые резервные копии продолжают шифроваться с использованием того же TDE-протектора. Смена TDE-протектора не изменяет уже созданные резервные копии — чтобы восстановить резервную копию, зашифрованную ключом Key Vault, необходимо, чтобы материал соответствующего ключа был доступен серверу, на который выполняется восстановление. Особенность реализации TDE требует, чтобы для успешного восстановления были доступны как текущий, так и предыдущие TDE-протекторы. Рекомендуется сохранять все предыдущие версии протектора в хранилище ключей, чтобы иметь возможность восстановить резервные копии базы данных.
В этой статье подробно объясняются, какие ключи должны быть доступны для восстановления базы данных и почему это необходимо.
Шифрование файла журнала транзакций
Чтобы понять, какие ключи требуются для восстановления из резервной копии до указанной точки во времени, сначала нужно разобрать, как работает шифрование журнала транзакций. Движок баз данных SQL Server делит каждый физический файл журнала на несколько виртуальных журналов — VLF (Virtual Log Files). Каждый VLF имеет собственный заголовок. Зашифровать весь файл журнала одной «волной» невозможно, поэтому каждый VLF шифруется отдельно, а информация о шифровании сохраняется в заголовке VLF. Когда при восстановлении менеджеру журнала нужно прочитать конкретный VLF, он использует информацию о шифровании из заголовка этого VLF, чтобы найти соответствующий ключ и расшифровать содержимое.
Нешифрованный журнал транзакций
Представим логические блоки файла журнала как последовательность VLF. Изначально мы находимся в VLF1, и текущий LSN (Log Sequence Number) попадает в VLF1.
Когда включено TDE
После включения TDE текущий VLF заполняется «неоперационными» записями журнала (non-operational log records), и создаётся следующий VLF (VLF2).
Каждый VLF имеет заголовок с информацией о шифровании; поэтому когда меняется идентификатор шифратора, запись журнала «перекатывается» к границе следующего VLF.
В заголовке новоuj VLF будет храниться текущий DEK (например, DEK_1
) и отпечаток (thumbprint) использованного шифра — и все добавленные записи в этот VLF будут зашифрованы.
Когда VLF2 заполняется, создаётся следующий VLF (VLF3). Поскольку шифрование включено, VLF3 также будет содержать DEK и информацию о шифре в его заголовке, и он будет зашифрован.
Ротация ключей
При генерации нового DEK или смене его шифра журнал «перекатывается» к следующей границе VLF. Новый VLF (например, VLF4) будет содержать обновлённый DEK и сведения о новом шифре.
Например, при ротации ключа в Azure Portal создаётся DEK_2
, до его активации VLF3 заполняется неоперационными записями, затем появляется VLF4, зашифрованный новым DEK.
База данных может одновременно использовать несколько ключей
На текущий момент при использовании CMK на уровне сервера и базы после ротации ключей часть активных VLF может оставаться зашифрованной старым ключом. Поскольку ротация ключей допускается до момента «смыва» этих VLF, база данных может одновременно использовать несколько ключей. Чтобы гарантировать, что в каждый момент времени база использует лишь текущий протектор (primary generation p) и предыдущее (p-1), реализован следующий порядок действий:
- Блокируем операцию изменения протектора, если есть любые активные VLF, использующие старый отпечаток (thumbprint), отличный от текущего. При попытке пользователя сменить протектор или при автоматической ротации мы проверяем, имеются ли активные VLF со старым отпечатком — если есть, операция блокируется.
- Если активных VLF со старым отпечатком нет, выполняем бэкап журнала (log backup), чтобы «смыть» неактивные VLF, затем проводим ротацию протектора и ждём полного завершения процесса.
Такой подход гарантирует, что база будет одновременно использовать два ключа.
Пример хронологии
Иллюстрация работы механизма на примере:
- t0 — база создана без шифрования;
- t1 — база защищена отпечатком A;
- t2 — протектор базы ротируется на отпечаток B;
- t3 — клиент просит сменить протектор на отпечаток C; мы проверяем активные VLF, видим, что они используют отпечаток A, и блокируем смену;
- затем, когда активных VLF с отпечатком A не остаётся, выполняем бэкап журнала, смываем VLF, выполняем ротацию и завершаем операцию только после полного окончания всех этапов;
- в результате после t4 база использует только отпечатки B и C.
Восстановление до точки во времени (Point-in-time restore)
Из приведённого следует: если происходила ротация ключей, для восстановления требуется несколько ключей. Чтобы восстановить резервную копию, зашифрованную TDE-протектором из Azure Key Vault, убедитесь, что секреты нужных ключей доступны серверу. Поэтому мы рекомендуем сохранять старые версии TDE-протектора в Key Vault, чтобы гарантировать возможность восстановления бэкапов.
Для выяснения наличия ключей используйте команды Azure PowerShell:
Get-AzSqlServerKeyVaultKey # для целевого сервера
Get-AzSqlInstanceKeyVaultKey # для целевого управляемого экземпляра
Эти команды возвращают список доступных ключей и помогают определить, какие ключи отсутствуют. Чтобы обеспечить восстановление всех резервных копий, у целевого сервера восстановления должен быть доступ ко всем необходимым ключам. Обратите внимание: для восстановления ключи не обязаны быть помечены как TDE-протекторы в конфигурации.
Файлы журнала, сохранённые в бэкапах, остаются зашифрованными исходным TDE-протектором, даже если он был затем ротирован и база перешла на новый протектор. При восстановлении могут потребоваться оба ключа: и тот, что использовался для шифрования соответствующих VLF в момент создания бэкапа, и текущий (или другие промежуточные) ключи.
Пример восстановления до точки во времени
Если клиент хочет восстановить данные до конкретной точки времени tx, ему понадобятся текущий протектор (p) и предыдущий (p-1) для периода [tx-8 дней]…[tx]. Значение «tx-8» выбрано потому, что предполагается наличие полного бэкапа раз в 7 дней, то есть гарантирован полный бэкап за последние 8 дней. Поскольку VLF могли оставаться активными и зашифрованными более ранним ключом, система может также потребовать отпечатки p-2 и p-3 из вне этого буфера.
Рассмотрим пример: запрос PITR сделан на 20.08.2025 (tx). В этот момент активен отпечаток D (p). Чтобы обеспечить наличие полного бэкапа, вычитаем 8 дней — получаем 12.08.2025 (tx-8), когда был активен отпечаток C (p-1). Поскольку некоторые VLF могут всё ещё быть зашифрованы более ранними ключами, также требуются отпечатки B (p-2) и A (p-3).
Итого: для данного восстановления требуются отпечатки A, B, C и D.
Выводы
При восстановлении резервной копии, зашифрованной TDE-протектором из Azure Key Vault, крайне важно, чтобы секрет ключа был доступен серверу, где выполняется восстановление из резервной копии. Рекомендуется хранить все прежние версии TDE-протектора в Key Vault, чтобы обеспечить возможность восстановления резервных копий баз данных.
Комментариев нет:
Отправить комментарий