
Привет, Хабр! Меня зовут Александр Дубов, я старший инженер в команде Tantor Labs.
Давайте поговорим о маскировании данных — не самом гламурном, но жизненно важном инструменте.
С каждым годом объем персональных данных, которые обрабатывают компании, растет как снежный ком. Параллельно ужесточаются и требования регуляторов: с 30 мая 2025 г. в России штрафы за нарушения в работе с персональной информацией вырастают в разы. Без маскирования — как без зонта в грозу: один неверный шаг, и репутация компании под ударом, оно предотвращает утечки и помогает соответствовать нормативным требованиям, таким как требования ФЗ №152 «О персональных данных». С передачей же данных «как есть» сопряжен ряд рисков: финансовые и репутационные потери, нарушение законодательства, штрафы и использование данных злоумышленниками.
Чтобы избежать подобных рисков, нужны гибкие инструменты обезличивания. Один из них — opensource-инструмент pg_anon. Он маскирует конфиденциальные данные, помогая соблюдать закон, защищая информацию и сохраняя её пригодность для анализа. Помимо общедоступной версии, существует и коммерческая реализация, но это предмет отдельной беседы, а разговор о бесплатной лучше начать с азов.
Маскирование данных: что это, для чего, и что делает pg_anon?
Маскирование — это изменение данных так, чтобы скрыть личную или конфиденциальную информацию, но сохранить их структуру и целостность. Например:
Имена и адреса, учетные или корпоративные данные заменяются на случайные, но правдоподобные аналоги.
Номера телефонов частично скрываются: +7 950 *** ** **.
Номера карт или банковские реквизиты шифруются или заменяются на тестовые номера.
Медицинские диагнозы, истории болезни превращаются в обезличенные.
Зачем это нужно?
Чтобы передавать данные подрядчикам или аналитикам без риска утечки.
Чтобы разработчики тестировали функции на реалистичных, но безопасных данных.
Чтобы избежать штрафов по 152-ФЗ и сохранить репутацию компании.
Типичные сценарии:
Создание копии рабочей базы для тестовой среды.
Подготовка данных для маркетингового исследования.
Демонстрация функционала на конференции без показа реальной информации о клиентах.
4 ключевых метода маскирования:
Замена — подлинные данные заменяются на вымышленные. Пример: «Иван Петров» → «Сергей Волков».
Обфускация — часть информации скрывается. Пример: email vasya@domain.com преобразуется в v***@domain.com.
Шифрование — данные преобразуются так, чтобы их можно было восстановить только с ключом. Используется для номеров карт или паспортов.
Генерация — создание новых данных по заданным правилам (например, случайные даты рождения в определенном диапазоне).
pg_anon — рабочий инструмент от «Тантор Лабс» для анонимизации данных в PostgreSQL, который дает следующие возможности:
Создание и использование словарей с правилами маскирования.
Интеграция с любой актуальной версией PostgreSQL.
Режимы работы для создания дампов и восстановления данных.
Работы с БД на другом хосте.
Ключевой особенностью pg_anon является система шаблонов маскирования, которые, будучи прописаны один раз, «покрывают» большинство типовых структур баз данных. Вместо того чтобы вручную создавать правила для каждого поля, можно использовать готовые политики анонимизации под распространённые сценарии — будь то персональные данные, платёжная информация или логины пользователей. Это не только экономит время на первоначальную настройку, но и гарантирует согласованность данных при дальнейшем использовании, поскольку шаблоны автоматически применяются ко всем новым таблицам с аналогичной структурой.
Установка pg_anon
Перед установкой убедитесь, что на вашем хосте установлены:
Python 3.8+
venv
для PythonGit и pip
PostgreSQL или иная СУБД на его основе (например, Tantor Postgres)
Клонируйте репозиторий и перейдите в каталог pg_anon:
git clone https://github.com/TantorLabs/pg_anon.git && cd pg_anon
Создайте виртуальное окружение и активируйте его:
python3 -m venv venv && source venv/bin/activate
Установите зависимости:
pip install -r requirements.txt
Проверьте, что установка завершена успешно:
python3 pg_anon.py --help
Если всё подготовленно корректно, то вы увидите основные ключи для работы с инструментом.
Инициализация БД
Для работы с целевой БД ее сперва следует инициализировать:
python3 pg_anon.py --mode=init \
--db-user=<имя пользователя БД> \
--db-user-password=<пароль пользователя БД> \
--db-name=<имя БД> \
--db-host=<адрес сервера БД> \
--db-port=<порт БД>
В процессе инициализации БД появится схема с функциями анонимизации anon_funcs
:
erp_v_anon=# \dn
Список схем
Имя | Владелец
------------+-------------------
anon_funcs | postgres
public | pg_database_owner
(2 строки)
Создание словаря анонимизации
Для обнаружения чувствительных данных pg_anon использует мета-словарь — это отдельный файл с описанием правил анонимизации для БД (если базы типовые, словарь можно использовать общий). Он помогает настроить обработку чувствительных данных. Чтобы создать такой мета-словарь:
Подключитесь к БД, используя административный доступ. Убедитесь, что у вас есть права на чтение схемы данных и анализ таблиц.
Проанализируйте структуру данных, определите, какие таблицы и поля содержат чувствительную информацию. Если структура БД плохо документирована – обсудите с разработчиками, какие данные могут быть конфиденциальными, или изучите данные вручную, например, через запросы к таблицам.
-
Определите конфиденциальные поля. Например, можно выделить следующие:
Таблица
Customers
: поляcustomername
,contactname
,address
.Поля с шаблоном
*name
в других таблицах. Поляphone
, которые часто содержат телефонные номера.Поля с датами, такие как
orderdate
иbirthdate
.
-
Определите типы данных, например:
Поля с текстовыми данными (
varchar
) могут содержать имена, адреса и другие строки.Поля с датами (
timestamp
) могут содержать конфиденциальную временную информацию.
Для большей безопасности добавьте обработку дополнительных данных, например, регулярных выражений для номеров банковских карт, ИНН, паспортных данных и т. д. Чтобы было проще писать регулярные выражения, можно использовать специальные конструкторы или обратиться за помощью к ИИ.
-
Проверьте работоспособность регулярного выражения, выполнив запрос такого вида:
SELECT <наименование поля> FROM <имя таблицы> WHERE <наименование поля> ~ '<регулярное выражение>';
Если у вас есть нетекстовое поле (например, числовое или дата), но вам нужно выполнить проверку с использованием регулярного выражения, то это поле сначала нужно преобразовать в текстовый тип данных. Пример:
SELECT Fld69944 FROM Reference787_VT69940 WHERE CAST(_Fld69944 AS TEXT) ~ '^(7?\d{10})$';
Если выражение написано правильно, вы увидите все строки, попавшие под условие.
После выполненных действий у вас получится примерно такой словарь:
{
"field": { # must be anonymized without scanning
"rules": [
"^fld_5_em",
"^amount",
"details$",
"contract_expires$",
"inn$"
],
"constants": []
},
"skip_rules": [],
"data_regex": {
"rules": [
"""[A-Za-z0-9]+([._-][A-Za-z0-9]+)*@[A-Za-z0-9-]+(\.[A-Za-z]{2,})+""", # email
"7?[\d]{10}", # phone 7XXXXXXXXXX
"^other_ext_tbl_text", # catch "schm_mask_ext_exclude_2.other_ext_tbl_2"
"""[0-9]{3}-[0-9]{2}-[0-9]{4}""", # social Security numbers "nnn-nn-nnnn"
"""\b[0-9A-Z]{3}([^ 0-9A-Z]|\s)?[0-9]{4}\b""", # license plate numbers aaa-nnnn
"""^\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}$""", # IPV4 addresses
# """^([1][12]|[0]?[1-9])[\/-]([3][01]|[12]\d|[0]?[1-9])[\/-](\d{4}|\d{2})$""", # Dates in MM/DD/YYYY format
# MasterCard numbers 5258704108753590
"""^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$""",
# Visa card numbers 4563-7568-5698-4587
"""\b([4]\d{3}[\s]\d{4}[\s]\d{4}[\s]\d{4}|[4]\d{3}[-]\d{4}[-]\d{4}[-]\d{4}|[4]\d{3}[.]\d{4}[.]\d{4}[.]\d{4}|[4]\d{3}\d{4}\d{4}\d{4})\b""",
# Any card number
"""[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}""",
# URLs
"""(?i)\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()]+|\(([^\s()]+|(\([^\s()]+\)))*\))+(?:\(([^\s()]+|(\([^\s()]+\)))*\)|[^\s`!()\[\]{};:'".,?«»“”‘’]))""",
"""[0-9]{2}-[0-9]{7}""", # INN from 1c
# """[0-9]{4}-[0-9]{2}-[0-9]{2}""" # timestamp
]
},
"data_const": {
"constants": [
"account",
"email",
"лимонад",
"сергей"
]
},
"sens_pg_types": [
"text",
"integer",
"bigint",
"character",
"json",
"mvarchar",
# "timestamp"
],
"funcs": {
"text": "anon_funcs.digest(\"%s\", 'salt_word', 'md5')",
"numeric": "anon_funcs.noise(\"%s\", 10)",
# "timestamp": "anon_funcs.dnoise(\"%s\", interval '6 month')",
"bigint": "anon_funcs.random_inn()",
"integer": "anon_funcs.random_int_between(1, 10)",
"mvarchar": "anon_funcs.digest(\"%s\"::text, 'salt_word', 'md5')",
# "timestamp": "anon_funcs.random_date_between_1c('1900-01-01'::timestamp, now()::timestamp WITHOUT TIME ZONE)"
}
}
Данный словарь взят из конкретного кейса с базой 1С, вы можете взять его за основу. Сохраните его содержимое в файл с расширением .py
. Чтобы создать словарь анонимизации на основе мета-словаря, выполните команду:
python3 pg_anon.py --mode=create-dict \
--db-user=<имя пользователя БД> \
--db-user-password=<пароль пользователя БД> \
--db-host=<адрес сервера БД> \
--db-port=<порт БД> \
--db-name=<имя БД> \
--meta-dict-file=<путь до мета-словаря в формате py> \
--output-sens-dict-file=<имя словаря с конфиденциальными данными в формате py> \
--output-no-sens-dict-file=<имя словаря с неконфиденциальными данными в формате py>
В результате создадутся два словаря: один — с чувствительными конфиденциальными данными, а другой без. Эти словари будут использоваться для обезличивания данных в момент снятия дампа.
Снятие дампа с маскированием и восстановление
Чтобы создать дамп данных с маскированием, выполните команду:
python3 pg_anon.py --mode=dump \
--db-user=<имя пользователя БД> \
--db-user-password=<пароль пользователя БД> \
--db-host=<адрес сервера БД> \
--db-port=<порт БД> \
--db-name=<имя БД> \
--pg-dump=<путь до pg_dump> \
--prepared-sens-dict-file=<имя словаря с конфиденциальными данными в формате py> \
--output-dir=<директория для файлов дампа> \
--clear-output-dir
После ее запуска начнётся процесс маскирования и создания дампа. Время выполнения зависит от размера БД и объёма чувствительных данных, подлежащих маскированию. После снятия дампа проверьте вывод работы инструмента на наличие ошибок. Чтобы восстановить данные из маскированного дампа, потребуется создать новую БД на целевом хосте. Для этого выполните команду:
python3 pg_anon.py --mode=restore \
--db-user=<имя пользователя БД> \
--db-user-password=<пароль пользователя БД> \
--db-host=<адрес сервера БД> \
--db-port=<порт БД> \
--db-name=<имя БД> \
--pg-restore=<путь до pg_restore> \
--input-dir=<директория файлов дампа>
После восстановления БД обезличивание и анонимизация завершены.
Проверка результата маскирования
Рассмотрим результаты на примере одной записи из таблицы с помощью запроса SELECT:
До маскирования:
-[ RECORD 1 ]--+-----------------------------------------------------------------------------
_idrref | \x1184f8d111067d4611e42c46baf81660
_version | 0
_marked | f
_predefinedid | \x00000000000000000000000000000000
_parentidrref | \x00000000000000000000000000000000
_folder | t
_code | 000000722
_description | Иванов Иван Иванович
_fld69917 | 1888-08-14 00:00:00
_fld69918rref | \xa5ba88039f4bfe3c463072dc5545798f
_fld69919 | 711202580930
_fld69920 | 124-665-929 78
_fld69921 | 0,г. Москва,Московского района,Какой-то области,
_fld69922rref | \x7c84f8d111067d4611e4e29a151abcce
_fld69923 | f
_fld69924 | f
_fld69925 | Иванов Иван Иванович
_fld69926 |
_fld69930 | 0001-01-01 00:00:00
_fld69931 | ИВАНОВ ИВАН ИВАНОВИЧ
_fld69932rref | \x00000000000000000000000000000000
_fld69935 | f
_fld69936 | Иванов
_fld69937 | Иван
_fld69938 | Иванович
_fld69939 |
_fld78306 | И. И.
_fld101386rref | \x00000000000000000000000000000000
_fld101387rref | \x00000000000000000000000000000000
_fld113200 | f
_fld116354 | f
_fld116355 | f
_fld116356 | f
_fld2488 | 0
После маскирования:
-[ RECORD 1 ]--+-----------------------------------------------------------------------------
_idrref | \x1184f8d111067d4611e42c46baf81660
_version | 0
_marked | f
_predefinedid | \x00000000000000000000000000000000
_parentidrref | \x00000000000000000000000000000000
_folder | t
_code | 82da6gd8d7
_description | 6a59cf7f00761c55b89f420583519d90
_fld69917 | 00761c55b89f420
_fld69918rref | \xa5ba88039f4bfe3c463072dc5545798f
_fld69919 | 89f420583
_fld69920 | a59cf7f00761c55b89
_fld69921 | f7f00761c55b89f420583519d90a88039f4bfe3
_fld69922rref | \x7c84f8d111067d4611e4e29a151abcce
_fld69923 | f
_fld69924 | f
_fld69925 | 00761c55b89f420583519d90a88039
_fld69926 |
_fld69930 | 0001-01-01 00:00:00
_fld69931 | 55b89f420583519d90a88039f4bf
_fld69932rref | \x00000000000000000000000000000000
_fld69935 | f
_fld69936 | 59cf7f0076
_fld69937 | f00761c55b
_fld69938 | b89f420c55b89
_fld69939 |
_fld78306 | 55b89f420
_fld101386rref | \x00000000000000000000000000000000
_fld101387rref | \x00000000000000000000000000000000
_fld113200 | f
_fld116354 | f
_fld116355 | f
_fld116356 | f
_fld2488 | 0
После тщательной проверки можно передавать обезличенную БД.
Заключение
В статье была рассмотрена opensource‑реализация pg_anon — специализированного решения от «Тантор Лабс», предназначенного для автоматизированной анонимизации персональных данных в PostgreSQL. Это эффективный рабочий инструмент для минимизации рисков утечек конфиденциальной информации и обеспечения соответствия требованиям регуляторных стандартов. Как отмечалось ранее, наряду с бесплатной версией существует коммерческая реализация pg_anon с графическим интерфейсом и расширенным функционалом, однако даже базовый opensource‑вариант решения предоставляет достаточный набор средств анонимизации для интеграции в процессы разработки и тестирования. Его внедрение позволяет организациям выстроить устойчивую систему защиты данных без значительных инвестиций, что особенно актуально для стартапов и проектов с ограниченными ресурсами.