Изображение: recraft
Деперсонализация кажется простой задачей, пока не сталкиваешься с реальностью. На практике это полноценный инженерный вызов, сочетающий профилирование, проверку бизнес-логики, оптимизацию и работу с нетривиальными особенностями инфраструктуры. В этой статье мы разобрали технические сложности, через которые проходят команды, когда пытаются организовать обезличивание в больших системах, — и решения, позволяют пройти этот путь.
С 30 ноября 2024 года вступили в силу важные изменения в законодательстве о защите данных. Теперь за нарушения, связанные с обработкой и защитой персональных данных, появилась уголовная ответственность для сотрудников, отвечающих за информационную безопасность и работу с данными.
Помимо этого, введены оборотные штрафы: за повторные нарушения компания может заплатить до 3% от годового оборота. Суммы ощутимые, особенно для бизнеса, который работает с большими объемами пользовательских данных.
Когда мы обсуждаем нововведения с инженерами, быстро становится ясно: один штраф стоит дороже, чем внедрение нормального процесса обезличивания. И уж точно не стоит того, чтобы рисковать уголовной ответственностью. Поэтому сегодня вопрос «нужно ли обезличивать?» уже не стоит — стоит вопрос, как сделать это эффективно и безопасно.
Как правильно выделить и обработать персональные данные
В процессе обезличивания мы опираемся на два ключевых понятия: профилирование и деперсонализация.
Профилирование — это поиск полей, содержащих персональную информацию. На самом деле мы можем искать не только ПДн: в разных проектах нас просили находить размер каски, обуви и другие специфичные параметры — всё это решалось без проблем.
Деперсонализация (обезличивание) — следующий шаг. Это изменение найденных данных таким образом, чтобы при возможной утечке они не представляли ценности для злоумышленников и не могли быть использованы против пользователя или компании.
Неважно, относятся ли данные к категории персональных или к любому другому чувствительному типу — принцип один и тот же.
На первый взгляд кажется, что определить персональные данные достаточно просто: фамилия, имя, отчество, номер телефона, паспорт, ИНН, СНИЛС — всё это очевидные категории. Но на практике возникает вопрос: как отличить, например, ИНН от любого произвольного набора цифр?
Чтобы минимизировать ложные срабатывания, мы добавляем дополнительные проверки:
- для СНИЛС используем проверку контрольной суммы;
- для паспортных данных анализируем первые четыре цифры, чтобы убедиться; что это действительно паспорт, а не случайная последовательность.
Отдельная важная задача — сохранение консистентности. Когда мы обезличиваем данные из разных баз, одно и то же имя или номер телефона должны превращаться в одинаковые значения. Это критично для последующего анализа и работы с наборами данных, чтобы обезличенные данные оставались полезными и связными.
Ещё один частый сценарий — географически распределенные дата-центры. Между ними может не быть связи вовсе, но при этом важно, чтобы данные в разных хранилищах обезличивались одинаково. Мы решаем и такую задачу: две независимые базы должны выдавать совпадающие обезличенные значения для одних и тех же исходных данных.
Есть и другая особенность, с которой сталкиваются команды тестирования. Если на вход тестам вместо фамилии и имени приходит случайный набор букв, такие значения легко ломают логику сценариев. Поэтому мы научились преобразовывать реальные данные в корректные, естественно выглядящие аналоги: превращать Васю Петрова в Петра Иванова, генерировать валидные номера телефонов и паспортов, корректно подбирать даты рождения.
Бывают и более специфичные запросы. Например, страховая компания просила сохранить информацию о том, что клиент старше 18 лет, но при этом «сдвигать» дату рождения так, чтобы она обязательно попадала в первую или вторую половину месяца — потому что на этом основана внутренняя логика расчета коэффициентов. Таких кейсов у нас накопилось много, и каждый требовал отдельного подхода.
В итоге сформировалась большая библиотека способов корректного и устойчивого обезличивания данных — и это, как оказалось, куда сложнее, чем кажется на первый взгляд.
Технические сложности профилирования
Понять, какие сущности мы ищем
Первый шаг — понять, с какими видами данных вы работаете. Типовой список включает ПДн физических лиц включает:
- ФИО
- Адрес
- Телефонный номер
- Паспортные данные
- СНИЛС
- ОГРН
- ИНН
- Номер счетов / банковских карт
Однако в зависимости от домена персональные данные могут относиться не только к физическим лицам: могут быть задействованы и юридические лица, и другие типы сущностей. На этом этапе важно четко зафиксировать, что именно считается чувствительными данными в вашем контуре.
Определить методы поиска
Даже разобравшись с тем, что искать, нужно понять, как это искать. Мы выделяем три основных метода:
- метаданные;
- словари;
- регулярные выражения.
У вас могут появиться дополнительные методы, но эти три — основа.
Собрать данные для этих методов
Чтобы методы профилирования работали корректно, требуется предварительно собрать и подготовить данные. Это включает:
- наполнение словарей фамилиями, именами и другими возможными значениями;
- создание и отладку регулярных выражений для структурированных типов данных (например, ИНН, СНИЛС и т. д.);
- поддержку и обновление этих словарей и шаблонов по мере появления новых форматов и правил.
Это трудоемкий этап, без которого невозможно добиться точного распознавания чувствительных данных.
Собрать движок профилирования
Когда данные готовы, нужно собрать движок, который умеет всё это применять. Если база данных большая, движок придётся долго оптимизировать, чтобы он справлялся с нагрузкой, корректно масштабировался и при этом оставался достаточно быстрым.
Разобраться с архитектурной дельтой
Даже если профилирование прошло успешно и у вас есть готовый профиль данных, работа на этом не заканчивается. Базы со временем обновляются: появляются новые поля и таблицы. Значит, профилирование нужно выполнять повторно — хотя бы по дельте изменений. Это также должно быть заложено в архитектуру движка: инструмент обязан уметь находить новые сущности без полного пересканирования всего хранилища.
Технические сложности деперсонализации
Уникальные сущности и «забытые» места хранения данных
Может показаться, что достаточно обезличить основные таблицы — и работа сделана. На практике это далеко не так. Важно отметить, что пример далее приведен на базе Oracle, и часть подобных проблем специфична именно для этой СУБД. В других системах хранения данные сложности могут проявляться иначе или не встречаться вовсе.
Material View
Физический объект базы данных, который содержит результат выполнения запроса. Материальные представления могут содержать слепки данных, которые не обновились после обезличивания основной таблицы. Поэтому они должны входить в общий контур обработки.
Material View Log
Рядом с ними в Oracle существует ещё одна специфичная сущность — Material View Log. Это вспомогательный физический объект для оптимизации работы с материальными представлениями (позволяет выполнять fast refresh вместо complete refresh). С точки зрения обезличивания не вызывает дополнительных задач, но становится источником серьезных проблем при параллельной обработке данных. В процессе вы рискуете получить взаимные блокировки и остановить весь пайплайн.
Отключить Material View Log нельзя — его приходится удалять и затем восстанавливать. Это нужно учитывать и вписывать в общий процесс обработки данных.
Constraints
Правила, которые добавляются при изменении/добавлении данных в таблицу. Даже если вы умеете корректно работать с нужными полями, всегда существуют ограничения в базе. Например:
- дата закрытия договора не может быть раньше даты открытия;
- связанные значения должны оставаться согласованными.
Все такие ограничения тоже нужно профилировать и учитывать при обезличивании. Иначе результат будет некорректным, а база — потенциально сломанной.
Ошибки при пересоздании базы данных
Проблемы с JDK и Java-объектами
В ряде кейсов при восстановлении базы мы сталкивались с тем, что в Oracle:
- отсутствует возможность компилировать Java source;
- версия JDK отличается от ходовой (1.5 вместо 1.8).
В результате часть логики, завязанной на Java внутри БД, просто перестает работать. Исправляется это довольно приземленно — переустановкой JDK и приведением версии к нужной.
Индексы в невалидном состоянии
При копировании часть индексов оказывается сломанной, что приводит к остановкам при обновлении таблиц.
Чаще всего это всплывает не на «боевых» таблицах, а на:
- архивных таблицах;
- пользовательских слепках/копиях, которые когда-то сделали «на всякий случай» и про них забыли.
Один из обязательных шагов — научиться обнаруживать и корректно обрабатывать такие индексы: либо чинить, либо переcоздавать, либо исключать эти объекты из обработки по согласованным правилам. Иначе процесс обезличивания будет регулярно ломаться на забытых и «заброшенных» участках базы.
Проблемы с настройками баз данных и таблиц
Низкое значение Initrans
Один из характерных примеров — параметр INITRANS в Oracle. Он отвечает за количество DML-запросов, которые могут выполняться параллельно на записях внутри блока данных.
Когда таблица большая и активно обновлялась, ее блоки могут иметь слишком низкое значение INITRANS. В результате при массовом обновлении данных мы параллельно обращаемся в разные блоки и начинаем блокировать сами себя, создавая задержки и замедляя процесс обезличивания.
Исправить ситуацию простым изменением настройки нельзя: для применения потребуется MOVE, а это уже отдельная трудоемкая операция, потенциально влияющая на структуру таблицы. Поэтому на практике проблему приходится решать ручной обработкой взаимных блокировок.
Ограничение свободного места в tablespace
Массовое обновление занимает дополнительное пространство, и если его мало, процесс может просто не завершиться. Это тоже нужно учитывать заранее.
Валидация отдельных сущностей
Отдельная группа проблем — корректность данных после обезличивания. Во-первых, это техническая валидация. Например:
- Прохождение котрольных суммы (СНИЛС, ИНН и т. д.);
- корректность формата имени;
- структуры номера документа.
Если такие проверки не пройдены, приложение может отказать на ровном месте, потому что формат данных перестанет соответствовать ожиданиям.
Во-вторых, есть валидация сохранения бизнес-логики, которую нельзя игнорировать. Например:
- дата закрытия договора не может быть раньше даты открытия;
- дата рождения должна соответствовать паспортным данным;
- связанные сущности должны оставаться согласованными.
Все эти правила должны учитываться прямо в методах обезличивания, иначе база после обработки окажется в неконсистентном состоянии и вызовет ошибки в потребляющих системах.
Оптимизация алгоритмов обезличивания
Все перечисленные сложности приводят к тому, что даже если вы собрали свой рабочий движок, на больших базах данных проблемы с оптимизацией всё равно рано или поздно появятся.
Распараллеливание процессов
Для крупных БД необходимо уметь распараллеливать обработку. Если ваше решение основано, например, на stored procedures или схожем подходе, нативной поддержки параллелизма там обычно нет.
Значит, придется придумывать дополнительный механизм:
- запускать отдельные jobs;
- управлять ими через планировщики;
- контролировать распределение нагрузки.
И это само по себе становится отдельной инженерной задачей.
Оптимизация алгоритмов
Даже если алгоритмы работают корректно, на практике почти всегда оказывается, что скорость обработки оставляет желать лучшего. Массовые обновления, большие объемы данных, сложные проверки и валидации — всё это требует оптимизации.
Иногда приходится пересматривать часть логики, перерабатывать методы или менять подход к обработке данных, чтобы уложиться в адекватное время выполнения.
Пример решения с Oracle
Изначально у нас был простой и понятный конвейер. Один общий планировщик проходил по списку таблиц, которые нужно обезличить.
Старый процесс:
Для каждой таблицы мы:
- отключали индексы и триггеры;
- запускали через планировщик набор работ, которые выполняли обновления;
- по завершении возвращали индексы и триггеры обратно.
Так мы проходили все таблицы по очереди.
Но когда мы обезличивали данные в одном из банков, оказалось, что такой процесс перестал справляться с нагрузкой.
На графике утилизации CPU выше видно множество «пустых» участков — ресурсы простаивали, а значит, мы теряли время. Для больших объемов данных это неприемлемо.
Мы полностью пересобрали процесс, чтобы устранить простои и максимально загрузить доступные ресурсы.
Теперь пайплайн выглядит так:
- Первый планировщик проходит таблицы в прямом порядке и обрабатывает крупные таблицы.
- Второй планировщик идет навстречу первому, но работает с мелкими таблицами — в обратном порядке.
Оба планировщика выполняют подготовку таблиц: отключают индексы, триггеры и запускают обновления.
Завершение же процесса вынесено отдельно:
- Третий планировщик занимается включением индексов и триггеров, потому что это длительная операция, которая не должна блокировать основной поток обработки.
На выходе — новый график утилизации CPU, где «провалов» практически нет. Все ресурсы загружены равномерно, а процесс обезличивания работает заметно быстрее.
Для нас это был важный шаг вперед: более гибкая схема распараллеливания дала ту производительность, которой мы не могли добиться предыдущим подходом.
Дальнейшие планы по продукту DataSan
После нескольких лет работы над ядром мы пришли к тому, что пора развивать пользовательский интерфейс. Это одно из наших ближайших направлений — сделать работу с инструментом более удобной и прозрачной.
- Параллельно мы развиваем новый модуль усечения данных. На Oracle он уже доступен в стабильной поставке. Этот модуль позволяет значительно сокращать время обезличивания в тех случаях, когда нет необходимости обрабатывать всю базу целиком.
- Усечение можно выполнять по разным параметрам — не только по дате, но и, например, по фамилиям или сериям паспортов. Мы планируем расширить поддержку и вынести модуль за пределы Oracle, чтобы он был доступен в других СУБД.
- Разумеется, продолжаем развивать и профилирование — это один из ключевых и наиболее трудоемких этапов, который требует постоянного улучшения.
Авторы: Пётр Мельченко, лид команды разработки в “Перфоманс Лаб”, Василий Жидков, продакт-менеджер DataSan.
Оригинал публикации на сайте CISOCLUB: "Обезличивание данных в базах: в чем сложность и как организовать процесс".
Смотреть публикации по категориям: Новости | Мероприятия | Статьи | Обзоры | Отчеты | Интервью | Видео | Обучение | Вакансии | Утечки | Уязвимости | Сравнения | Дайджесты | Прочее.
Подписывайтесь на нас: VK | Rutube | Telegram | Дзен | YouTube.