
Обезличивание
Копия базы боевого сайта содержит персональные данные: почту и телефоны пользователей, адреса доставки, комментарии к заказам, активные сессии. Отдавать такую копию разработчику или разворачивать её на тестовом сервере нельзя.
mxBackup решает это на этапе дампа: строки читаются из базы, проходят через правила подмены и уже изменёнными попадают в database.sql. Исходная база при этом не меняется — обезличивание существует только внутри архива.
Работает только в режиме Development
Правила применяются, если у профиля выбран режим Development (в файле профиля — mode = dev). В режимах Production и «Пользовательский» данные выгружаются как есть. См. Профили.
Действия
| Действие | Что делает | Пример результата |
|---|---|---|
Заменить тестовыми данными (mask) | Подставляет правдоподобное значение, выведенное из содержимого строки | user4821194@example.test |
Очистить значение (hide) | NULL, если колонка допускает null, иначе пустая строка | '' |
SHA-256 (hash) | Необратимый хеш от значения и «соли» строки | 9f2c… |
Заданное значение (replace) | Фиксированное значение из правила | 0 |
Очистить таблицу (truncate) | Структура сохраняется, строки в дамп не попадают | таблица пуста |
Подстановка детерминирована: значение вычисляется из имени таблицы, ключа строки (id, internalKey, order_id или user_id) и имени колонки. Отсюда два полезных следствия — один и тот же пользователь получает одинаковый псевдоним во всех таблицах, где он упомянут, а повторный запуск копии даёт тот же результат.
Формат подстановки зависит от смысла колонки:
| Колонка | Значение в копии |
|---|---|
email | user<число>@example.test |
phone, mobilephone, fax | +7000<7 цифр> |
fullname, receiver, username | User <число> |
ip | 192.0.2.<число> (диапазон для документации, RFC 5737) |
zip, index | шесть цифр |
| остальные | Test <число> |
Встроенные правила
Стандартный набор включается флагом «Стандартное обезличивание» и обязателен для профиля в режиме Development — выключить его нельзя.
По таблицам
Правила записаны масками, поэтому не зависят от префикса таблиц.
| Маска таблицы | Что делается |
|---|---|
*_session | таблица очищается целиком |
*_users | username подменяется; password, cachepwd, salt, session_stale очищаются |
*_user_attributes | контактные и адресные поля подменяются, comment, website, photo очищаются, dob обнуляется, extended обрабатывается как JSON |
*_ms2_orders | session_id и order_comment очищаются, properties обрабатывается как JSON |
*_ms2_order_addresses | получатель, телефон, почта и все адресные поля подменяются, comment очищается |
*_ms2_customer_profiles | account и spent обнуляются, referrer_code очищается |
По именам колонок
Независимо от таблицы:
- подменяются
email,phone,mobilephone,fullname,address,ip; - очищаются
comment,password,cachepwd,salt,token,secret,api_key,apikey,authorization.
Эти правила покрывают таблицы сторонних дополнений, которые mxBackup «в лицо» не знает, — при условии, что колонки названы типовым образом.
JSON внутри колонок
Колонки properties и extended разбираются как JSON, и внутри них подменяются значения ключей email, phone, mobilephone, fullname, receiver, address, street, city, zip, postcode, comment, ip, token, secret, password, authorization, api_key, apikey — на любой глубине вложенности. Если содержимое колонки не разбирается как JSON, значение очищается: непонятную структуру безопаснее выбросить, чем отдать как есть.
Собственные правила
Встроенные правила знают только про MODX и miniShop2. Всё остальное — таблицы ваших дополнений, самописные формы, поля с нетиповыми именами — пакету неизвестно, и для них правила описываете вы. Такие правила и называются собственными (в интерфейсе — «Пользовательские»): они хранятся не в коде пакета, а в файле профиля, в секции masking.rules, и уезжают вместе с профилем на другой сайт.
Разница видна прямо в гриде: у каждой колонки есть столбец «Источник правила» со значением «Встроенное», «Пользовательское» или «Нет правила». Последнее и есть сигнал, что данные попадут в копию как есть.
Как добавить правило
Вкладка Обезличивание работает по схеме «выбрал профиль → выбрал таблицу → увидел все её колонки». Дальше:
- щёлкните по колонке правой кнопкой мыши — появится пункт «Добавить правило» (или «Изменить правило», если своё правило уже есть);
- выберите действие, при необходимости укажите значение, JSON path и приоритет;
- сохраните и обязательно выполните
dry-run— он покажет итоговый план по всем колонкам.
Правило удаляется там же: пунктом «Удалить» контекстного меню (MODX 2) или кнопкой удаления в строке (MODX 3). Если под колонку подходило встроенное правило, после удаления собственного оно снова вступит в силу.
Тип цели пакет определяет сам: пустое поле JSON path даёт правило на колонку (таблица.колонка), заполненное — правило на путь внутри JSON (таблица.колонка.путь). Отдельная кнопка «Очистить таблицу в dev-копии» в верхней панели создаёт правило на таблицу целиком.
В именах допустимы маски: правило для *_ms2_my_table.email сработает на сайте с любым префиксом таблиц, а путь items.*.email пройдёт по всем элементам массива внутри JSON.
Пример 1. Своя таблица с контактами
Допустим, форма заявок пишет в собственную таблицу modx_my_leads:
| Колонка | Что внутри | Что сделают встроенные правила |
|---|---|---|
client_email | почта клиента | ничего: правило есть для колонки email, а не client_email |
client_phone | телефон | ничего, по той же причине |
manager_note | комментарий менеджера | ничего: встроенное правило знает comment |
created_at | дата | ничего не нужно |
Встроенные правила по именам колонок сравнивают имя целиком, поэтому префикс client_ их обходит. Значит, нужны три собственных правила: для двух первых колонок — «Заменить тестовыми данными», для заметки — «Очистить значение».
Подстановка выбирается по имени колонки
Правдоподобные значения (user123@example.test, +7000…) пакет подставляет, только когда колонка называется типовым образом — email, phone, fullname, ip и подобными. Для колонки client_email действие «Заменить тестовыми данными» даст безопасное, но неправдоподобное Test 4821194. Если тестовому окружению нужен именно похожий на почту адрес, используйте действие «Заданное значение» с фиксированной строкой вроде client@example.test — или переименуйте колонку.
Если таблица нужна в копии только структурой (журналы, очереди, статистика переходов), проще не описывать правила по колонкам, а нажать «Очистить таблицу в dev-копии»: структура останется, строки в дамп не попадут.
Пример 2. UUID внутри extended у пользователя
Колонка extended в modx_user_attributes — это JSON, и встроенное правило её уже обрабатывает. Но обрабатывает по списку известных ключей: email, phone, address, token и подобные. Собственный ключ, например uuid из внешней CRM, в этот список не входит и уедет в копию как есть:
{ "crm": { "uuid": "8f14e45f-ea8d-4b9c-9b0a-2f7d1c3a55e1" }, "email": "user1@example.test" }Чтобы закрыть и его, добавьте правило с JSON path. Щёлкните правой кнопкой по колонке extended, в поле JSON path укажите путь до ключа и выберите действие:
| Путь | Действие | Результат |
|---|---|---|
crm.uuid | SHA-256 | стабильный хеш вместо идентификатора: связи между записями сохраняются, исходное значение не восстановить |
crm.uuid | Очистить значение | null вместо идентификатора |
crm.uuid | Заданное значение | одинаковая заглушка во всех строках |
crm.* | Заменить тестовыми данными | подмена всех ключей внутри crm |
Путь пишется точками от корня JSON; $. в начале можно опустить, пакет его всё равно отбросит. Если значение колонки не разбирается как JSON, правило ничего не меняет.
Как понять, что ещё осталось незакрытым
Правил по JSON нет смысла придумывать наугад: посмотрите реальное содержимое колонки на копии сайта (SELECT extended FROM modx_user_attributes LIMIT 5) и опишите те ключи, которых нет в списке встроенных. После этого dry-run покажет колонку extended в плане обезличивания, а проверить сам результат подмены можно только на готовой копии — правила применяются в момент дампа.
Как правило выглядит в файле профиля
Всё, что вы задали в интерфейсе, оказывается в файле профиля — это удобно для переноса и для code review:
'masking' => [
'standard' => true,
'rules' => [
[
'target_type' => 'column',
'target' => 'modx_my_leads.client_email',
'action' => 'mask',
'value' => null,
'priority' => 100,
'active' => true,
'id' => 1,
],
[
'target_type' => 'json_path',
'target' => 'modx_user_attributes.extended.crm.uuid',
'action' => 'hash',
'value' => null,
'priority' => 100,
'active' => true,
'id' => 2,
],
],
],Правило с 'active' => false сохраняется, но не применяется — удобно временно отключить, не удаляя.
Приоритет
У каждого правила есть числовой приоритет. Правила применяются по возрастанию, и последнее сработавшее определяет результат. Встроенные правила имеют приоритет -900 (адресные, по таблицам) и -1000 (общие, по именам колонок), у собственных по умолчанию 100 — поэтому пользовательское правило всегда перекрывает встроенное для той же колонки.
Отсюда типовой приём: если стандартная подмена мешает (например, домен example.test ломает тестовый сценарий), задайте своё правило с действием «Заданное значение» — оно победит.
Удаление своего правила возвращает встроенное
Если для колонки было встроенное правило, после удаления пользовательского оно снова начнёт действовать. Колонка не остаётся без защиты.
Режим fail-closed
Основная опасность обезличивания — тихий отказ: правило перестало совпадать с изменившейся схемой, копия выглядит нормально, а персональные данные внутри. Поэтому для известных чувствительных таблиц mxBackup проверяет схему до дампа и, если обязательных колонок нет, прерывает работу с ошибкой вида:
Dev backup остановлен: для таблицы modx_users отсутствуют обязательные поля masking: passwordАрхив в этом случае не создаётся вовсе.
Проверка не срабатывает вслепую по имени: у каждой чувствительной таблицы есть «якорные» колонки, и правило применяется, только если схема реально похожа на ожидаемую. Например, *_active_users исключена явно — она подходит под маску *_users, но пользователей не хранит.
Что делать, если копия остановлена:
- посмотреть, какие именно колонки перечислены в ошибке;
- если таблица действительно изменилась (своя доработка, другой пакет) — описать нужные правила самостоятельно;
- если таблица к персональным данным отношения не имеет — исключить её из профиля во вкладке «Таблицы БД»;
- выполнить
dry-runи убедиться, что план обезличивания снова строится.
Проверка перед выдачей копии
php core/components/mxbackup/cli/mxbackup.php dry-run --profile=devВ отчёте есть всё, что нужно проверить глазами:
masking_tables— по каждой таблице список колонок и действие для каждой;masked_columns— общее число обезличиваемых колонок;truncated_tables— таблицы, которые будут выгружены пустыми;table_names— состав таблиц архива.
То же самое показывает кнопка «Проверить состав» в менеджере.
Обезличивание не отменяет ответственности
mxBackup закрывает типовые поля MODX и miniShop2. Собственные таблицы с персональными или коммерчески чувствительными данными пакет знать не может — правила для них описываете вы. Перед первой выдачей копии наружу пройдите отчёт dry-run по всем таблицам своих дополнений.
