Все началось с обычного тикета в Jira, из тех, которые выглядят безобидно и даже немного скучно. «Нужно протестировать новый личный кабинет. Разверни тестовую базу».

Через несколько месяцев этот тикет аукнулся сорванным релизом, сгоревшим маркетинговым бюджетом и отложенным запуском важнейшего сервиса. А Олег, как всегда, остался крайним.

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

Сперва все выглядело просто

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

 Нашему герою, администратору Олегу, поставили задачу развернуть тестовую базу.

Он поднял структуру, проверил доступы, убедился, что все открывается, и отписался: готово, можно работать. Первой пришла команда тестирования, и сразу выяснилось, что под словами «развернуть тестовую базу» все понимали разное. Для Олега это была схема, окружение и доступы, а для QA — полноценная копия продовой системы с данными, на которых можно гонять сценарии, проверять личный кабинет и давать нагрузку — примерно 10 ТБ.

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

Лайфхаки, которые помогают ликвидировать бардак в задачах

Когда у технических команд (разработчики, тестировщики, администраторы) и бизнеса разное представление о том, что значит «задача выполнена», мы совершенно закономерно получаем хаос в процессах, сорванные дедлайны и привычные игры отделов в «пинг-понг». Лечится это чёткими критериями выполнения задач: DoR (Definition of Ready) и DoD (Definition of Done). В одной из прошлых статей мы разобрали, как внедрить эти правила на практике.

Разобравшись, что от него нужно, Олег поднимает копию БД из бэкапов продакшена: данные есть и объем достаточный. Кажется, все окей, но здесь появляются безопасники.

А потом пришла ИБ

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

Олег запрашивает список чувствительных полей и получает инструкции, список колонок и установку: «вот это замаскируй, и будет хорошо». Дальше он делает то, что на его месте сделали бы многие, берет чувствительные поля и прогоняет через хэш.

С точки зрения ИБ получается неплохо: значения больше не читаются, возможности обратного восстановления нет, так что задача формально закрыта. А вот с точки зрения команды тестирования это полный провал. Дело в том, что для обкатки новых сервисов нужны не просто какие-то данные, а данные правильного формата. Номер карты должен быть шестнадцатью цифрами, которые проходят проверку по алгоритму Луна. То же самое с телефоном, ИНН и остальными идентифицирующими полями. Фронтенд и валидация работают с конкретными форматами, а не с хэшами. Для паролей это ещё куда ни шло, но для тестирования бизнес-процессов совершенно не подходит. 

И это тот случай, когда у всех своя правда. Службе безопасности нужно вымарать из баз все намеки на ПДн, а QA нужны валидные данные. Если между этими требованиями нет заранее выстроенного процесса, на выходе получится конфликт, и между молотом и наковальней останется тот, кто последним трогал базу.

Когда одного хэша мало, в ход идут костыли

Итак, Олегу снова пришлось все переделывать. Он начал собирать генераторы: open source библиотеки, скрипты, фейковые ФИО, телефоны, номера карт. Где-то готовые решения, где-то своя обвязка. Задача из тикета «разверни базу» превратилась в отдельный мини-проект без бюджета и дедлайна.

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

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

Документация врала

Олег работал по перечню полей, который ему выдали безопасники, вот только их данные отстали от реальности на несколько лет. За это время в базе появились новые таблицы, новые (в том числе конфиденциальные) поля, дополнительные сущности, логовые хвосты, временные хранилища и технические закоулки, которые никто не актуализировал, пока одна из таких строк не попала на глаза тестировщикам… 

Из этого следует, пожалуй, главный урок всей истории.

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

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

Можно сколько угодно спорить о том, какой алгоритм лучше: хэширование, генерация, словарная подмена, токенизация. Всё это вторично, если часть чувствительных данных ты просто не заметил.

Олег начал искать вручную. Регулярки, переборы, выборочные проверки, нечто среднее между дата-аудитом и детективной работой. Сил и времени не хватало, и Олег наделал ошибок. Например, забыл обработать двойные фамилии, и вместо нормальной подмены в одном из полей появился нечитаемый набор спецсимволов. Потом выяснилось, что нужно было отдельно обрабатывать дефисы, отдельно экранировать строки, отдельно следить за полями, где ФИО хранится частями, и отдельно за теми, где оно записано целиком. 

И если этого еще можно было избежать, то сохранить внутреннюю логику в терабайтах данных при ручном маскировании практически нереально. Вот, допустим, у вас есть пользователь по фамилии Сыроглазов. Если в одной таблице он после маскирования превратился в Развалова, то он должен стать Разваловым везде. А это базовое условие того, что тестовая среда будет похожа на реальную.

А потом тестировщики случайно уронили базу

Олегу потребовалось несколько недель переработок, чтобы подготовить базу, а потом тестировщики случайно снесли ее вместе с бэкапами.

С этой минуты история перестала быть просто неприятной и стала дорогой, даже очень дорогой. Потому что сделать «еще раз такую же» для Олега означало повторить почти весь описанный путь заново. В результате сдвинулся запуск продукта. Следом поехали связанные финансовые планы, активности по допродажам, привлечение новых клиентов, маркетинговые сценарии. 

Нужно ли говорить, что виноватым сделали Олега. Неправильно выстроенные процессы предпочли не замечать.

Что стоит вынести из этой истории, кроме сочувствия к Олегу

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

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

  2. Результат должен быть проверяем до запуска на полный объем. Олег работал вслепую: запустил скрипт на 10 ТБ, подождал, посмотрел на результат, ужаснулся, переделал, запустил снова. Нормальный процесс предполагает, что сначала можно увидеть сэмпл: было — стало, и только после этого запускать на объём.

  3. Замаскированный человек должен оставаться одним и тем же человеком везде.

  4. Замаскированные данные пользователя должны быть одинаковыми во всех связанных системах. В Oracle, в PostgreSQL, в истории операций, в зависимых сущностях.

  5. QA редко нужны все 10 ТБ, обычно нужен репрезентативный срез с сохранением связей и нужных сценариев. Если нагрузочное тестирование закрывается на 30% объема — нет смысла обрабатывать остальное.

  6. Когда тестировщики уронили базу, единственным человеком, который знал, как её поднять заново, был Олег, но зрелый процесс должен быть отчуждаемым. А это означает настроенный пайплайн, который может запустить любой.

Главная ошибка в таких историях — считать, что «сделать тестовую базу» — это техническая задача. На практике это давно не так. Это отдельный процесс на стыке ИТ, ИБ, QA и инфраструктуры, и если он не описан, не автоматизирован и не воспроизводим, значит, у вас нет процесса. У вас период везения между двумя инцидентами.


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