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

Представьте ситуацию, знакомую многим: руководитель ИБ требует «логировать всё». Админ включает log_statement = 'all', диск переполняется за полчаса, база тормозит, а в логах невозможно найти ничего полезного среди гигабайтов отладочной информации.
С pg_proaudit — расширением для аудита безопасности Postgres Pro — ситуация была иной. Это расширение не тормозило базу и не переполняло диск — с производительностью у него всегда всё было в порядке. Но первая версия попала в другую, классическую «инженерную ловушку»: это был мощный инструмент, которым оказалось слишком сложно пользоваться. Администраторы баз данных смотрели на документацию, считали, скольк�� правил нужно создать вручную, вздыхали и часто выбирали решения попроще.
«Да, конечно, классная штука, но мы задолбаемся её настраивать», — слышали разработчики. И проблема была не только в трудозатратах. Сложная настройка — гарант человеческой ошибки. Стоило забыть добавить правило всего для одного типа команд, и у злоумышленника появлялся шанс сделать «грязное дело» абсолютно незамеченным.
И что самое интересное — мы это исправили. Не защищали дизайн, не говорили «вы неправильно используете», а кардинально переработали логику настройки. Эта история о том, как услышать пользователя и пересоздать продукт.
Когда совершенство становится врагом
В 2022 году команда разработки начала «ковырять» pg_proaudit. То, что они нашли, было интересным парадоксом. Расширение было технически превосходным:
гранулярность без компромиссов: логировалась почти любая операция;
высокая скорость: использовались эффективные хэш-таблицы, что давало пренебрежимое влияние на производительность;
максимальная гибкость: можно было регистрировать действия любого пользователя.
Одна проблема: почти никто его не использовал.
«В двадцать втором году, когда я пришёл, это уже было достаточно заслуженное расширение, но пользователей почти не было. Там раз в несколько лет прилетал какой-то баг, его исправляли, тестировщики проверяли, но до реальной эксплуатации большим количеством клиентов, кажется, не доходили», — вспоминает Михаил Грибков.
Баги приходили редко, потому что пользователей было мало. Когда все молчат, это может означать либо идеальный продукт, либо что его никто не трогает.
Почему ванильного логгера и pgAudit недостаточно
Прежде чем осуждать нас за сложность первой версии, стоит понять контекст. Зачем Postgres Professional вообще создал собственное расширение? Ведь есть стандартный логгер PostgreSQL, а есть популярное open source расширение pgAudit.
«Идеологически мы позиционируем pg_proaudit не как конкурент логгеру Постгреса, а как его дополнение. Лог Постгреса — это техническая жизнь системы: варнинги, ошибки, чекпоинты. А нам нужно обеспечить чистый поток событий для внешних систем анализа (SIEM). Безопасники редко читают сырые логи базы данных — они работают с инструментами вроде ArcSight или Kaspersky KUMA, которые собирают данные со всей инфраструктуры. И наша задача — поставить этим системам качественные входные данные для построения моделей угроз, а не заваливать их техническим шумом», — разъясняет Михаил.
Кроме того, основным драйвером создания pg_proaudit была сертификация у регуляторов (ФСТЭК). Но дело не только в сертификации, а в здравом смысле. pgAudit, сделанный для PCI DSS, давал слишком много лишнего, заваливая систему логами всех операций чтения. Нам требовался инструмент, который позволит не писать «всё подряд», а выделить конкретные «опасные» участки данных и следить только за ними, игнорируя безопасную рутину.
В чем отличия от 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, расширение уже доступно.
Добавьте библиотеку в postgresql.conf:
shared_preload_libraries = 'pg_proaudit'Перезагрузите сервер.
Создайте расширение:
CREATE EXTENSION pg_proaudit;Создайте первое правило и сохраните его:
SELECT pg_proaudit_set_rule(current_database(), 'AUTHENTICATE', NULL, NULL, NULL); SELECT pg_proaudit_save();
Заключение
История pg_proaudit — это история о том, что даже отличный продукт может быть «убийцей» сам для себя, если он игнорирует удобство пользовате��я.
Разработчики создали мощный, быстрый инструмент. Но им не пользовались. Когда они наконец поняли почему — «это невозможно настроить» — то не стали защищать старую архитектуру. Они пересмотрели систему правил. Кардинально. Отказались от хэш-таблиц, перешли на перебор правил, внедрили классы событий и поддержку схем.
Сегодня pg_proaudit — это зрелый инструмент безопасности, который позволяет спать спокойно. DROP TABLE заметят все и сразу, а вот если кто-то тихо изменит баланс на счете или в обход регламента выдаст права на чтение конфиденциальных данных — это увидит только аудит. И вы сможете задать вопрос «на каком основании?» конкретному сотруднику до того, как станет слишком поздно.
