В администрировании баз данных есть такие задачи, которые вызывают у разработчиков азарт: оптимизация запросов, шардирование петабайтных баз или настройка отказоустойчивых кластеров. А есть те, что нужно решать «через не хочу». Одна из них — аудит безопасности. О том, как создавали расширение pg_proaudit, рассказал старший разработчик Postgres Professional Михаил Грибков.

Наверняка вам знакома ситуация, когда руководитель службы ИБ хочет «логировать всё». Тогда админ включает log_statement = 'all', диск за полчаса переполняется, база тормозит, а в логах невозможно найти ничего полезного среди гигабайтов отладочной информации.

С pg_proaudit — расширением для аудита безопасности Postgres Pro — ситуация была иной. Оно не тормозило базу и не переполняло диск — с производительностью всё было в порядке. Первая версия расширения попала в другую классическую инженерную ловушку: таким мощным инструментом было слишком сложно пользоваться. Администраторы баз данных смотрели документацию, считали, сколько правил нужно создать вручную, вздыхали и часто выбирали решение попроще.

«Да, конечно, классная штука, но мы замучаемся её настраивать», — слышали разработчики. И проблема была не только в трудозатратах. Сложная настройка — гарант человеческой ошибки. Стоило забыть добавить правило всего для одного типа команд, и у злоумышленника появлялся шанс абсолютно незаметно проделывать «грязные делишки».

Самое интересное — разработчики Postgres Professional это исправили. Не защищали дизайн, не говорили: «Вы неправильно используете», а кардинально переработали логику настройки. Эта история о том, как услышать пользователя и пересоздать продукт.

Когда совершенство становится врагом

В 2022 году команда разработки начала «ковырять» pg_proaudit и обнаружила интересный парадокс. Расширение было технически превосходным:

  • бескомпромиссно гранулярным — логировало почти любую операцию;

  • высокоскоростным — использовало эффективные хэш-таблицы, а значит, почти не влияло на производительность;

  • максимально гибким — позволяло регистрировать действия любого пользователя.

Но несмотря на все преимущества почти никто решением не пользовался.

«В двадцать втором году, когда я пришёл в компанию, это уже было достаточно заслуженное расширение, но пользователей оно почти не имело. Раз в несколько лет прилетал какой-то баг, его исправляли, тестировщики проверяли, но до реальной эксплуатации с большим количеством клиентов, кажется, не доходили», — вспоминает Михаил Грибков.

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

Почему недостаточно «ванильного» логгера и pgAudit

Зачем Postgres Professional вообще создал собственное расширение для аудита при наличии стандартного логгера PostgreSQL и популярного опенсорсного расширения pgAudit?

«Идеологически мы позиционируем pg_proaudit не как конкурента логгеру Постгреса, а как его дополнение. Лог Постгреса — это технические артефакты системы: варнинги, ошибки, чекпойнты. А нам нужно обеспечить чистый поток событий для внешних систем анализа (SIEM). Безопасники редко читают сырые логи базы данных — они работают с инструментами вроде ArcSight или Kaspersky KUMA, которые собирают данные со всей инфраструктуры. И наша задача — поставить этим системам качественные входные данные для построения моделей угроз, а не заваливать их техническим шумом», — разъясняет Михаил.

Основным драйвером создания pg_proaudit была сертификация у регуляторов (ФСТЭК). Но дело не только в сертификации, но и в здравом смысле. pgAudit для PCI DSS давал слишком много лишнего, заваливая систему логами всех операций чтения. Нам требовался инструмент, который позволит не писать «всё подряд», а выделить конкретные «опасные» участки данных и следить только за ними, игнорируя безопасную рутину.

В чем отличия pg_proaudit от pgAudit?

  • pgAudit работает через стандартный логгер (и смешивает потоки) и логирует только группы событий (например, все READ или все WRITE).

  • pg_proaudit изначально создавался для точечного логирования (конкретная таблица, конкретная команда) и действий с базами данных, что критично для Enterprise-сектора. А во второй версии мы добавили и поддержку групп, объединив преимущества обоих подходов.

Интерфейс, который отпугивал всех

В первой версии применялись неудобные функции настройки вроде set_object или set_role, и пользователю приходилось постоянно гадать, какую из них применить.

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

Но 20 правил — это ещё полбеды. А если у вас 100 таблиц, за которыми нужно следить? Любое изменение в структуре БД превращалось в ночной кошмар администратора.

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

Поворотный момент: прощай, хэш-таблица

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

Вместо сотен строк конфига нужно было вот это: 

SELECT pg_proaudit_set_rule(
    current_database(), 
    'ALL_DDL',      -- Одно правило на все DDL!
    'TABLE',
    null,           -- на все таблицы
    null
);

Просто. Понятно. Работает.

Но тут возник архитектурный вызов. Вся система pg_proaudit была построена на хэш-таблицах. Это давало идеальную скорость поиска, но хэши не поддерживали обобщения, wildcards и иерархию. Хэш — это точное совпадение или ничего.

«Переходить с хэша на перебор правил — это решение из разряда "Прощай, скорость". Нужно было, во-первых, оптимизировать перебор, а во-вторых, быть уверенным, что количество правил у пользователя кардинально уменьшится», — делится мыслями Михаил.

Выбрали путь удобства использования. Попутно решили отказаться от идентификации объектов по OID в пользу имен. Это решило массу проблем при пересоздании таблиц или переносе правил.

Результаты рефакторинга:

  • Количество правил уменьшилось с нескольких сотен до десятка.

  • Сложность управления снизилась в 50–100 раз.

На практике благодаря тому, что 1000 правил превратились в 10 обобщённых, реальная производительность не пострадала. Проверка десятка правил перебором работала молниеносно.

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

Система классов событий и логирование по схемам

pg_proaudit 2.0 принёс унифицированную функцию pg_proaudit_set_rule и структурированный набор классов событий. Теперь можно оперировать крупными категориями: 

-- Все команды DDL (создание, изменение, удаление объектов)
SELECT pg_proaudit_set_rule(null, 'ALL_DDL', null, null, null, 'DDL operations');

-- Все команды модификации данных (INSERT, UPDATE, DELETE, TRUNCATE)
SELECT pg_proaudit_set_rule(null, 'ALL_MOD', null, null, null, 'Data modification');

-- Управление ролями
SELECT pg_proaudit_set_rule(null, 'ALL_ROLE', null, null, null, 'Role management');

Важнейшее нововведение: если указать в качестве объекта схему, правило применится ко всем таблицам внутри неё. Больше не нужно настраивать 100 правил для 100 таблиц.

Группировка по ролям

Главная фишка для крупных компаний — полноценная поддержка иерархии ролей: одни роли могут наследовать права других.

pg_proaudit 2.0 это понимает: 

-- Одно правило для всей группы бухгалтеров
SELECT pg_proaudit_set_rule(
    current_database(),
    'ALL_DML',
    'SCHEMA',
    'accounting',       -- вся схема бухгалтерии
    'accountant_group', -- одна групповая роль
    'Все операции бухгалтеров'
);

Система залогирует действие, даже если его выполнил конкретный пользователь ivan, который входит в группу accountant_group (напрямую или косвенно).

Новые форматы экспорта

По настойчивым просьбам клиентов добавлена поддержка CEF (Common Event Format) — стандарта для SIEM-систем (ArcSight, QRadar, Splunk).

Теперь pg_proaudit может записывать данные одновременно в несколько приёмников:

  • CSV — универсальный формат для архивов или интеграции с SIEM через промежуточные скрипты;

  • CEF — целевой стандарт для большинства SIEM-систем (ArcSight, QRadar, Splunk);

  • Syslog — системный канал, позволяющий передавать в SIEM данные (включая формат CEF) через протокол ОС.

Это означает, что компания с SIEM-инфраструктурой может интегрировать pg_proaudit в свою систему мониторинга гораздо проще и быстрее.

Что отличает pg_proaudit от pgAudit

Фича

pgAudit

pg_proaudit

Место хранения логов

Пишет в общий лог сервера (через стандартный логгер)

Отдельные файлы или свой канал в syslog. Свой фоновый процесс

Настройка правил

Через параметры конфигурации (postgresql.conf)

SQL API. Правила хранятся отдельно, можно менять на лету

Гранулярность

Только группы событий (READ, WRITE, DDL и так далее)

Гибкая комбинация: Группы + конкретные объекты + схемы + типы операций

Классы операций

Только они и есть

 Есть (готовые классы) + возможность детальной настройки

Ролевое логирование

Ограниченно

Полная поддержка иерархии ролей

Ротация логов

Зависит от настроек Postgres

Собственная ротация по времени или размеру

Реальный пример: банк с полным аудитом

Банк должен логировать все попытки входа, все DDL-операции, все операции с таблицей accounts, все операции бухгалтеров и все отключения.

Конфигурация: всего 6 правил вместо сотен. 

-- 1. Аутентификация в критичной БД
SELECT pg_proaudit_set_rule('bank_core', 'AUTHENTICATE', null, null, null, 'Login attempts');

-- 2. Отключения
SELECT pg_proaudit_set_rule('bank_core', 'DISCONNECT', null, null, null, 'Disconnections');

-- 3. Все DDL везде
SELECT pg_proaudit_set_rule(null, 'ALL_DDL', null, null, null, 'Global DDL audit');

-- 4. Изменения в таблице счетов (точечное правило)
SELECT pg_proaudit_set_rule('bank_core', 'ALL_MOD', 'TABLE', 'public.accounts', null, 'Accounts modification');

-- 5. Все операции бухгалтеров (правило на схему и роль)
SELECT pg_proaudit_set_rule(
    'bank_core', 
    'ALL_DML', 
    'SCHEMA', 
    'accounting', 
    'accountant_group',
    'Accountants activity'
);

-- 6. Управление правами (включает CREATE ROLE и др.)
SELECT pg_proaudit_set_rule(null, 'ALL_ROLE', null, null, null, 'Role management');

-- Сохранить изменения
SELECT pg_proaudit_save();

Инженерные истории: что было сложнее всего

Логирование отключений
Это была подлая проблема. Архитектура Postgres устроена так, что сложно «воткнуться» в нужный момент, чтобы гарантированно отследить дисконнект. Процесс сессии может завершиться так, что обычное расширение просто не успеет перехватить управление и записать лог. После долгих исследований разработчикам пришлось добавлять дополнительный хук прямо в ядро Postgres.

CEF и стандарты
CEF — открытый стандарт, но с ним возникли сложности. Стандарт обновлялся, но вендоры SIEM-систем часто интерпретировали его по-разному или использовали старые спецификации. Пришлось повозиться, чтобы формат сообщений корректно «съедался» всеми популярными системами.

Как начать работу

В Postgres Pro Enterprise или Standard расширение доступно «из коробки».

  1. Добавьте библиотеку в postgresql.conf: 

    shared_preload_libraries = 'pg_proaudit'
  2. Перезагрузите сервер.

  3. Создайте расширение:

    CREATE EXTENSION pg_proaudit;
  4. Создайте первое правило и сохраните его:

    SELECT pg_proaudit_set_rule(current_database(), 'AUTHENTICATE', NULL, NULL, NULL);
    SELECT pg_proaudit_save();

Заключение

pg_proaudit — это история о том, что даже отличный продукт может «сыграть в ящик», если проигнорирует удобства пользователя.

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

Сегодня pg_proaudit — это зрелый инструмент безопасности, который позволяет спать спокойно. DROP TABLE заметят все и сразу, а вот если кто-то тихо изменит баланс на счёте или в обход регламента выдаст права на чтение конфиденциальных данных — это увидит только аудит. И вы сможете задать вопрос: «На каком основании?» конкретному сотруднику до того, как станет слишком поздно.