pg_obfuscator — обфускатор для postgres с сохранением распределения данных (на основе clickhouse obfuscator)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Введение

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

Наш клиент - klara.com - коммуникационная телемедицинская платформа, упрощающая взаимодействие пациентов с врачами в США, столкнулась со стремительным ростом на волне пандемии 2020 года. Одним из вызовов на которые пришлось отвечать инженерам klara.com в это непростое время стало автоматизированное нагрузочное тестирование, способное обнаружить проблемы с производительностью до того как они проявят себя в production среде.

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

Постановка задачи выглядела так: спроектировать и реализовать пайплайн нагрузочного тестирования таким образом, чтобы его можно было легко поддерживать силами QA-инженеров, использовать как часть CI/CD процессов компании, расширять по необходимости и иметь возможность реализовать различные сценарии нагрузочного тестирования. Критерием успешности проекта стала точная реализация одного из кейса по производительности из production в среде нагрузочного тестирования с помощью инструментов, которые мы разработали.

Технологическая платформа

Основные языки программирования в команде - Ruby, JS. В качестве основного хранилища klara.com использует Postgres. Безопасность персональных данных пациентов (PHI - Protected Health Information) является ключевым аспектом бизнеса klara.com. Для обеспечения надежного хранения и обработки данных платформа использует HIPPA совместимую SaaS платформу - Aptible. Aptible покупает ресурсы у AWS, поэтому для дальнейшего описания будет достаточно считать Aptible сильно урезанной и зарегулированной версией AWS. 

Для максимально корректной реализации нагрузочного тестирования нам нужна среда максимально похожая на production среду. Идеально, если идентичными будут: серверный парк, структура и объем данных, версии кода, структура и объем трафика. Очевидно также, что сделать все перечисленное абсолютно идентичным за разумное время и бюджет не реально и всегда приходится принимать некие допущения.

В этой статье я расскажу как мы готовили данные для нагрузочного тестирования.

Чтобы воспроизвести похожее поведение приложения во время тестов нам нужно иметь максимально похожую на production базу данных с точки зрения объема данных и их распределения. Из-за того, что klara хранит в том числе персональные данные, нам понадобится обфускация базы. Дополнительное условие - скорость работы обфускатора, хотелось бы быстро.

Обзор решений

Сейчас существует несколько инструментов для решения этой задачи в postgres, мы провели краткий сравнительный анализ, который приведен ниже:

postgresql_anonymizer

+ Самое популярное по количеству звезд на github решение из имеющихся 

+ Очень много функций для разных типов данных с разными стратегиями, которые можно применять точечно для выбранных полей (https://postgresql-anonymizer.readthedocs.io/en/latest/masking_functions/)

+ Можно выгружать сразу в *.sql дамп

- Нужно устанавливать как расширение рядом с бд

- Для каждого поля нужно прописывать security labels с масками

- Маски работают только с одной схемой

- Нет данных по производительности

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

triki

+ Заявлена высокая скорость работы (1.4гб mysql dump 17sec)

+ Много типов данных + можно определить свои (форк + правки т.к. кристал руби-френдли язык)

+ Можно выгрузить конфигурацию всей схемы для дальнейшей настройки обфускатора (таблицы-поля)

+ Не требуется никаких правок в исходной бд, только настроить коннект

+ Выгружает в *.sql дамп

Выглядело неплохим вариантом, удобный деплой, понятный нам и заказчику язык, очевидный недостаток - не понятно как сохраняется распределение данных.

pgdump-obfuscator (форк)

+ есть возможность задавать параметры полей через cli (только в форке)

- нет информации о производительности

- обновлялся 8 лет назад

clickhouse-obfuscator

+ Заявлена высокая скорость работы (в докладе говорилось, что 1тб данных обфусцирован за 1.5 дня)

- Написан на C++ (нашей команде сложно вносить изменения)

- Принимает только csv-формат

- Нет внятной документации (только статья на Хабре)

Высокая скорость, сохранение распределения данных после обфускации, поддержка большой компанией и комьюнити - по этим причинам мы выбрали обфускатор от clickhouse.

pg_obfuscator

К сожалению для нашей задачи, clickhouse obfuscator не поддерживал прямое подключение к postgresql. Поэтому нам пришлось написать утилиту, которая решает задачу обфускации postgresql с учетом всей специфики работы именно с этой базой. Исходный код доступен по адресу.

Утилита представляет собой wrapper над psql client и clickhouse obfuscator и реализует следующую функциональность

  • выгрузка схемы базы с сохранением внешних ключей и проверок ссылочной целостности 

  • исключение из обфускации таблиц, полей таблиц

  • использование предопределенных шаблонов для генерации фейковых значений для полей

  • маппинг типов данных postgres на типы данных clickhouse

  • генерацию конфигурации со значениями по умолчанию

Из-за специфики работы clickhouse-obfuscator утилита требует дискового пространства для работы равного двойному размеру базы данных. Поставляется в виде docker image и доступна по адресу.

В настоящий момент есть ограничения, которые следует иметь в виду: 

  • утилита поддерживает только базовые типы postgres и не поддерживает вложенные: hstore, json, jsonb

  • несмотря на автоматическую генерацию конфига, для первого запуска он нуждается в правках

  • объем docker image составляет почти 700Mb

В рамках поставленной задачи мы наблюдали следующие скоростные характеристики: тестовая база 10Гб обфусцировалась за 40 минут, продуктовая в 50 Гб - 6..8 часов. Чем обусловлена нелинейность работы мы не выясняли.

Ниже я продемонстрирую работу c pg_obfuscator на примере работы с devrimgunduz/pagila: PostgreSQL Sample Database.

Демо

Развернем контейнер с postgres и создадим в нем 2 базы для демонстрации:

docker run --rm --name=db -e POSTGRES_PASSWORD=password -p5432:5432 postgres
docker exec -i db psql -U postgres postgres -c 'create database pagila;'
docker exec -i db psql -U postgres postgres -c 'create database pagila_o;'

Посмотрим IP-адрес базы - он понадобится для работы обфускатора:

docker inspect db | grep IPAdd

            "SecondaryIPAddresses": null,

            "IPAddress": "172.17.0.2"

И зальем в контейнер скрипты из проекта pagila:

cd /tmp
git clone git@github.com:devrimgunduz/pagila.git
docker exec -i db psql -U postgres pagila < /tmp/pagila/pagila-schema.sql
docker exec -i db psql -U postgres pagila < /tmp/pagila/pagila-data.sql

Убедимся, что там появились данные:

docker exec -i db psql -U postgres pagila -c 'select     a.first_name, a.last_name, f.film_id, f.title, f.description from film f join film_actor fa on f.film_id = fa.film_id join actor a on a.actor_id=fa.actor_id where f.film_id = 7;'

first_name | last_name | film_id |      title      |                                    description

------------+-----------+---------+-----------------+-----------------------------------------------------------------------------------

 JIM        | MOSTEL    |       7 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat

 RICHARD    | PENN      |       7 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat

 OPRAH      | KILMER    |       7 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat

 MENA       | HOPPER    |       7 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat

 MICHAEL    | BOLGER    |       7 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat

(5 rows)

 База для экспериментов готова. Теперь расчехлим pg_obfuscator, принципиальным моментом является монтирования тома для конфига, чтобы иметь возможность его потом поправить.

mkdir /tmp/config
docker run -it --rm -v /tmp/config:/opt/pg_obfuscator/config pg_obfuscator sh

Дальше команды выполняются в шелле обфускатора, если не сказано другого:

bundle exec ruby pg_obfuscator.rb  --configure --source-db-host 172.17.0.2 --source-db-port 5432 --source-db-name pagila --source-db-user postgres --source-db-password password

.......
I, [2021-04-02T08:47:54.682868 #9]  INFO -- : Processed 20 tables

I, [2021-04-02T08:47:54.683243 #9]  INFO -- : Check config before run export tables and obfuscation!

I, [2021-04-02T08:47:54.696328 #9]  INFO -- : Config saved to: config/config.yml

Обфускатор говорит, что нужно проверить конфиг и внести необходимые изменения. Конфиг для 20 таблиц получился около 400 строк, секции, которые нуждаются в правках отмечены - need_fix: true. Для того, чтобы вам было легче повторить я выложил исправленный конфиг сюда.

Для демонстрации генерации фейковых данных посмотрим на секцию в таблице actor:

last_name:
	db_data_type: text
  not_null: true
  obfuscator_data_type: String
  fake_data:
  	type: pattern
		value: "%{first_name}SON"

В качестве фамилии мы используем имя и постфикс SON.

Выполним последовательно экспорт схемы, данных, обфускацию и заливку полученных данных в базу pagila_o

ruby pg_obfuscator.rb --export-schema --source-db-host 172.17.0.2 --source-db-port 5432 --source-db-name pagila --source-db-user postgres --source-db-password password
ruby pg_obfuscator.rb --export-tables --source-db-host 172.17.0.2 --source-db-port 5432 --source-db-name pagila --source-db-user postgres --source-db-password password
bundle exec ruby pg_obfuscator.rb --obfuscate
ruby pg_obfuscator.rb --import --target-db-host 172.17.0.2 --target-db-port 5432 --target-db-name pagila_o --target-db-user postgres --target-db-password password

и выйдя из контейнера с обфускатором посмотрим на результат

docker exec -i db psql -U postgres pagila_o -c 'select   a.first_name, a.last_name, f.film_id, f.title, f.description from film f join film_actor fa on f.film_id = fa.film_id join actor a on a.actor_id=fa.actor_id where f.film_id = 7;'
 first_name | last_name | film_id |   title   |                                                      description

------------+-----------+---------+-----------+------------------------------------------------------------------------------------------------------------------------

 SA         | SASON     |       7 | ROON SUIT | A Amazing Display of a Database Administ And a Dog And a Database a Pastry Chef And a Car And a Manned Mine Shark Tank

 RURA       | RURASON   |       7 | ROON SUIT | A Amazing Display of a Database Administ And a Dog And a Database a Pastry Chef And a Car And a Manned Mine Shark Tank

 BER        | BERSON    |       7 | ROON SUIT | A Amazing Display of a Database Administ And a Dog And a Database a Pastry Chef And a Car And a Manned Mine Shark Tank

 CA         | CASON     |       7 | ROON SUIT | A Amazing Display of a Database Administ And a Dog And a Database a Pastry Chef And a Car And a Manned Mine Shark Tank

 MER        | MERSON    |       7 | ROON SUIT | A Amazing Display of a Database Administ And a Dog And a Database a Pastry Chef And a Car And a Manned Mine Shark Tank

(5 rows)

Видим, что last_name сформирован фейкером, описание обфусцировано, ссылочная целостность сохранена.

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

Благодарим команду clickhouse obfuscator за отличный продукт!

Источник: https://habr.com/ru/post/551200/


Интересные статьи

Интересные статьи

Многие компании активно переносят свои данные в облако, обеспечивая тем самым гибкость и масштабируемость своих приложений. Но те, кто впервые пробуют облачные технологии...
Эта работа вдохновлена статьей «Мечтают ли нейросети об электроденьгах?», где автор без преувеличения талантливо в своей доходчивости объясняет, почему использование искусственных нейросетей на...
Введение Для обеспечения дополнительного уровня безопасности сервера можно использовать мандатную модель распределения доступа. В данной публикации будет описано каким образом можно запускать ap...
Исследователи из Microsoft и Вашингтонского университета продемонстрировали первую полностью автоматизированную систему хранения данных в искусственно созданной ДНК с возможностью считывания...
Как обновить ядро 1С-Битрикс без единой секунды простоя и с гарантией работоспособности платформы? Если вы не можете закрыть сайт на техобслуживание, и не хотите экстренно разворачивать сайт из бэкапа...