qhb_audit
Расширение для осуществления аудита действий QHB.
Расширение состоит из трёх основных компонентов:
- Собственно динамическая библиотека расширения libqhb_audit.so.
- Очередь событий в специальной области общей памяти.
- Выделенный фоновый процесс qhb_audit_worker для обработки очереди.
Цикл работы расширения:
- Процесс сервера выполняет операцию и генерирует событие.
- Расширение помещает событие в очередь в общей памяти.
- Фоновый процесс извлекает событие из очереди и либо записывает в специальный файл -- лог аудита, либо передаёт внешнему HTTP агенту.
Настройка
Подключение расширения осуществляется путем установки параметров в файле конфигурации qhb.conf. Для автоматической загрузки расширения при старте экземпляра нужно добавить в qhb.conf следующую строку:
shared_preload_libraries = 'libqhb_audit'
Если параметр shared_preload_libraries уже задан, то в него нужно добавить значение libqhb_audit через запятую, например:
shared_preload_libraries = 'pg_store_plans,pg_stat_statements,libqhb_audit'
Расширение (точнее, его фоновый процесс) получает события от сервера БД через очередь, размещённую в области общей памяти QHB. Это накладывает ограничения на максимальный размер очереди и отведённой под неё памяти. В случае превышения размера очереди в основном логе сервера появится предупреждение об этом.
Общие параметры считываются только при инициализации расширения (при старте СУБД):
- qhb_audit.queue_memory: объем разделяемой памяти, выделяемой для внутренней очереди сообщений. По умолчанию — 10 МБ.
- qhb_audit.queue_capacity: максимальный размер внутренней очереди сообщений. По умолчанию — 1000 событий.
Если перезагрузка сервера невозможна, допускается обновление параметров с помощью
команды qhb_ctl reload
.
Параметры
Параметры для записи событий в файл
qhb_audit.csv_file
Путь к файлу, куда будут записываться события. Данный параметр можно менять «на лету».
Если значение параметра не задано, запись событий в файл не осуществляется. Если заданное имя не существует в файловой системе, то будет создан новый файл.
Если заданное имя указывает на файл, запрещённый для записи, или на файл, который невозможно создать, в лог сервера будет выдано сообщение об ошибке, а запись событий в файл не будет осуществляться.
Если указан относительный путь к файлу, предполагается, что файл находится в каталоге PGDATA. Промежуточные каталоги, если указаны, не создаются автоматически; при их отсутствии в файловой системе такой путь будет ошибочным.
Если заданное имя указывает на каталог, выдаётся сообщение
qhb_audit: CSV output path is a directory '<имя>', ignoring
и запись событий в файл не будет осуществляться.
При включённой ротации лога (см. ниже) значение параметра csv_file имеет смысл "базового" имени: новые файлы для ротации генерируются на его основе (примеры см. ниже).
qhb_audit.csv_file_rotation
Режим ротации файла событий. Данный параметр можно менять «на лету».
Ротация предотвращает неконтролируемое разрастание файла событий путём разбиения его на множество файлов с перезаписью со временем "по кругу". Имена файлов ротации генерируются на основе значения параметра qhb_audit.csv_file. Файлы ротации создаются в том же каталоге, на который указывает csv_file. Этот каталог не создаётся автоматически, а должен существовать на момент запуска. Если указан относительный путь, файлы ротации (как и одиночный файл без ротации) создаются по указанному пути относительно каталога PGDATA.
Если этот параметр не задан или имеет пустое значение, ротация не осуществляется.
Если задано некорректное значение, работа всего расширения блокируется с выдачей сообщения
incorrect value of parameter csv_file_rotation
Разрешённые значения параметра:
- off - ротация отключена, всё пишется в единственный файл;
- day - дневная ротация в 24 файла;
- week - недельная ротация в 7 файлов;
- month - месячная ротация в 28-31 файл;
- year - годичная ротация в 12 файлов.
Примерные имена файлов, генерируемые для каждого режима при "базовом" имени audit.csv. К имени файла (без расширения) присоединяется различающий суффикс, расширение сохраняется.
Режим ротации | Параметр | Имена файлов |
---|---|---|
дневной | day | audit_00h_of_day.csv ... |
audit_23h_of_day.csv | ||
недельный | week | audit_Mon_of_week.csv |
audit_Tue_of_week.csv | ||
audit_Wed_of_week.csv | ||
audit_Thu_of_week.csv | ||
audit_Fri_of_week.csv | ||
audit_Sat_of_week.csv | ||
audit_Sun_of_week.csv | ||
месячный | month | audit_01d_of_month.csv ... |
audit_31d_of_month.csv | ||
годовой | year | audit_January_of_year.csv |
audit_February_of_year.csv | ||
audit_March_of_year.csv | ||
audit_April_of_year.csv | ||
audit_May_of_year.csv | ||
audit_June_of_year.csv | ||
audit_July_of_year.csv | ||
audit_August_of_year.csv | ||
audit_September_of_year.csv | ||
audit_October_of_year.csv | ||
audit_November_of_year.csv | ||
audit_December_of_year.csv |
Файлы от предыдущего режима ротации остаются и могут быть удалены вручную. То же самое относится и к внешним таблицам для доступа к данным аудита через SQL-запросы (см. ниже).
Предварительные шаги для настройки доступа к данным логов аудита через SQL-запросы
Для доступа к данным аудита через SQL-запросы используется расширение file_fdw. Для этого устанавливается расширение file_fdw, создается основная таблица qhb_audit_log, выбирается схема ротации логов. В зависимости от выбранной схемы берутся за основу приведенные варианты скриптов, где уточняется путь к каталогу данных PGDATA и каталогу файлов логов аудита.
В приведенных ниже скриптах подразумевается, что файлы аудита будут расположены в каталоге
audit каталога данных PGDATA и начало имени файла будет также audit. Для
этого в настройке qhb_audit.csv_file можно прописать либо абсолютный путь
*** нужно заменить на реальный путь к каталогу данных), либо задать путь относительно текущего каталога данных, например audit/audit.csv. При необходимости, отредактируйте приведенные ниже скрипты в соответствии с реальным расположением файлов.
Задание переменной PGDATA и создание каталога audit внутри PGDATA
Здесь и во всех скриптах далее необходимо заменить ***
*** на реальный путь к каталогу PGDATA.
Создаем каталог для файлов логов аудита.
export PGDATA=<PGDATA>
sudo -u qhb mkdir $PGDATA/audit
Делаем данные аудита доступными на уровне системы только пользователю qhb:
sudo -u qhb chmod 700 $PGDATA/audit
Создание расширения file_fdw и регистрация стороннего сервера
Создайте расширение file_fdw и сторонний сервер (как вариант, можно сделать это в базе данных qhb).
CREATE EXTENSION file_fdw;
CREATE SERVER qhb_audit_log FOREIGN DATA WRAPPER file_fdw;
Создание основной таблицы
Данная таблица описывает все поля логов и от нее будут наследоваться при их создании все внешние таблицы логов, соответствующие выбранной схеме ротации.
create table qhb_audit_log
(
event_id bigint,
event_ts timestamp,
event_name text,
event_type text,
user_name text,
db_name text,
table_name text,
query_text text,
event_level text
);
Если ротация не нужна
Если необходимости в ротации нет, следует ограничиться созданием одной внешней таблицы
для файла, указанного в параметре qhb_audit.csv_file.
В следующей команде нужно заменить ***
*** на реальный путь до каталога данных:
export PGDATA=<PGDATA>
В следующей команде нужно заменить <file.csv> на реальное имя файла из параметра qhb_audit.csv_file:
sudo -u qhb touch $PGDATA/audit/<file.csv>
В команде создания внешней таблицы при указании filename нужно заменить ***
*** на реальный путь до каталога данных, а <file.csv> на реальное имя файла из параметра qhb_audit.csv_file:
CREATE FOREIGN TABLE qhb_audit_log_csv() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/<file.csv>', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
Дневная ротация в 24 файла (1 час - 1 файл)
Команды ОС для создания файлов часовых логов
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
export PGDATA=<PGDATA>
sudo -u qhb touch $PGDATA/audit/audit_00h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_01h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_02h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_03h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_04h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_05h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_06h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_07h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_08h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_09h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_10h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_11h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_12h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_13h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_14h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_15h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_16h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_17h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_18h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_19h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_20h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_21h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_22h_of_day.csv
sudo -u qhb touch $PGDATA/audit/audit_23h_of_day.csv
Скрипты для создания таблиц часовых логов
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
CREATE FOREIGN TABLE qhb_audit_00h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_00h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_01h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_01h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_02h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_02h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_03h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_03h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_04h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_04h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_05h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_05h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_06h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_06h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_07h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_07h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_08h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_08h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_09h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_09h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_10h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_10h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_11h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_11h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_12h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_12h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_13h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_13h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_14h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_14h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_15h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_15h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_16h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_16h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_17h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_17h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_18h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_18h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_19h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_19h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_20h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_20h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_21h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_21h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_22h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_22h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_23h_of_day() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_23h_of_day.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
Недельная ротация логов в 7 файлов
Команды ОС для создания файлов логов за каждый день недели
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
export PGDATA=<PGDATA>
sudo -u qhb touch $PGDATA/audit/audit_Mon_of_week.csv
sudo -u qhb touch $PGDATA/audit/audit_Tue_of_week.csv
sudo -u qhb touch $PGDATA/audit/audit_Wed_of_week.csv
sudo -u qhb touch $PGDATA/audit/audit_Thu_of_week.csv
sudo -u qhb touch $PGDATA/audit/audit_Fri_of_week.csv
sudo -u qhb touch $PGDATA/audit/audit_Sat_of_week.csv
sudo -u qhb touch $PGDATA/audit/audit_Sun_of_week.csv
Скрипты для логов для каждого дня недели
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
CREATE FOREIGN TABLE qhb_audit_Mon_of_week() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_Mon_of_week.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_Tue_of_week() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_Tue_of_week.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_Wed_of_week() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_Wed_of_week.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_Thu_of_week() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_Thu_of_week.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_Fri_of_week() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_Fri_of_week.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_Sat_of_week() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_Sat_of_week.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_Sun_of_week() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_Sun_of_week.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
Месячная ротация в 28-31 файл
Команды ОС для создания файлов логов за каждый день месяца
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
export PGDATA=<PGDATA>
sudo -u qhb touch $PGDATA/audit/audit_01d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_02d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_03d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_04d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_05d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_06d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_07d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_08d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_09d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_10d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_11d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_12d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_13d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_14d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_15d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_16d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_17d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_18d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_19d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_20d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_21d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_22d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_23d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_24d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_25d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_26d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_27d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_28d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_29d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_30d_of_month.csv
sudo -u qhb touch $PGDATA/audit/audit_31d_of_month.csv
Скрипты для создания таблиц логов за каждый день месяца
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
CREATE FOREIGN TABLE qhb_audit_01d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_01d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_02d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_02d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_03d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_03d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_04d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_04d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_05d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_05d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_06d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_06d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_07d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_07d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_08d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_08d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_09d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_09d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_10d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_10d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_11d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_11d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_12d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_12d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_13d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_13d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_14d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_14d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_15d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_15d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_16d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_16d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_17d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_17d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_18d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_18d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_19d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_19d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_20d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_20d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_21d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_21d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_22d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_22d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_23d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_23d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_24d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_24d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_25d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_25d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_26d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_26d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_27d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_27d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_28d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_28d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_29d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_29d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_30d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_30d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_31d_of_month() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_31d_of_month.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
Логи c годичной ротацией в 12 файлов
Команды ОС для создания файлов помесячных логов
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
export PGDATA=<PGDATA>
sudo -u qhb touch $PGDATA/audit/audit_January_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_February_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_March_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_April_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_May_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_June_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_July_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_August_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_September_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_October_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_November_of_year.csv
sudo -u qhb touch $PGDATA/audit/audit_December_of_year.csv
Скрипты для создания таблиц помесячных логов
Перед выполнением скриптов не забудьте заменить ***
*** на реальный путь к каталогу данных.
CREATE FOREIGN TABLE qhb_audit_January_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_January_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_February_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_February_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_March_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_March_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_April_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_April_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_May_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_May_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_June_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_June_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_July_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_July_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_August_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_August_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_September_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_September_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_October_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_October_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_November_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_November_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
CREATE FOREIGN TABLE qhb_audit_December_of_year() INHERITS (qhb_audit_log) SERVER qhb_audit_log OPTIONS (filename '<PGDATA>/audit/audit_December_of_year.csv', FORMAT 'csv', HEADER 'true', DELIMITER ',' );
Разделение доступности данных аудита разных баз данных
Пользователь с ролью информационной безопасности (ИБ) qhb_dbms_admin должен видеть все данные таблицы qhb_audit_log. Пользователь с ролью qhb_db_admin должен видеть данные аудита по тем базам данных, администратором которых он является. Подробную информацию о ролях администраторов ИБ см. в главе Описание Ролей ИБ. Разделение прав реализуется с помощью механизма RLS (Row Level Security). Для этого необходимо задать правила видимости данных, опираясь на данные по ролям и пользователям, а также активизировать механизм RLS для таблицы qhb_audit_log. Полная видимость данных для пользователя с ролью qhb_dbms_admin реализуется либо через установку для роли атрибута bypassrls (этот вариант используется, если таких пользователей несколько) либо через установку владельцем таблицы соответствующего пользователя (удобно в случае, когда такой пользователь всего один). Для владельца таблицы правила видимости по умолчанию не работают и ему доступны все данные таблицы.
Создание тестовых пользователей и выдача им соответствующих ролей
Для создания пользователей (здесь в качестве примера - db_admin и dbms_admin) и выдачи им соответствующих ролей нужно выполнить следующие команды:
\c qhb qhb
CREATE USER db_admin;
SELECT oid as user_oid FROM pg_authid WHERE rolname = 'dbms_admin';
SELECT oid as database_oid FROM pg_database WHERE datname = '<database_name>';
SELECT qhb_make_db_admin(<user_oid>, <database_oid>) FROM pg_database d WHERE d.datname = '<db_name>';
CREATE USER dbms_admin WITH bypassrls; -- пользователь с правом игнорирования правил RLS
SELECT user_oid FROM pg_authid WHERE rolname = 'dbms_admin';
SELECT qhb_make_dbms_admin(<user_oid>);
Использовать oid, соответствующий имени роли, можно и таким образом:
SELECT qhb_make_dbms_admin('dbms_admin'::regrole::oid);
Альтернативой установки атрибута bypassrls может стать задание владения таблицей qhb_audit_log ролью dbms_admin, т.к. политики доступа к данным по умолчанию не срабатывают по отношению к владельцу таблицы:
\c qhb qhb
alter table qhb_audit_log owner to dbms_admin;
Создание политики доступа к строкам и активация RLS для таблицы аудита
Для доступности данных только по конкретным базам создадим политику ограничения видимости строк, которая опирается на данные словаря. Нужно активировать механизм RLS для таблицы qhb_audit_log и выдать права на чтение таблицы qhb_audit_log пользователям db_admin и dbms_admin:
create policy policy_audit_log on qhb_audit_log using (
db_name in (select db.datname
from pg_database db
, qhb_db_admin a
where db.oid = a.db_id
and a.user_id = user::regrole::oid)
);
-- Включаем RLS для таблицы аудита
alter table qhb_audit_log enable row level security;
-- Права на чтение на основную таблицу (дочерние внешние таблицы не затрагиваем)
grant select on qhb_audit_log to db_admin;
grant select on qhb_audit_log to dbms_admin;
Для проверки видимости данных можно поочередно подключиться и выполнить запрос. Для пользователя db_admin видны только записи из соответствующего списка баз:
\c qhb db_admin
select * from qhb_audit_log;
Для пользователя dbms_admin будут доступны все данные:
\c qhb dbms_admin
select * from qhb_audit_log;
Если нет строк, соответствующих правам пользователя, или не установлен атрибут bypassrls, выдается сообщение:
ERROR: permission denied for table qhb_db_admin
Отключение RLS для таблицы, удаление политики RLS, отзыв прав на таблицу
\c qhb qhb
alter table qhb_audit_log disable row level security;
drop policy policy_audit_log on qhb_audit_log;
revoke select on qhb_audit_log from db_admin;
revoke select on qhb_audit_log from dbms_admin;
Параметры для отправки событий по REST API
qhb_audit.rest_url URL веб-сервера, принимающий сообщения через REST API. Данный параметр можно менять «на лету». Если он не задан, отправка событий не осуществляется. Если заданы qhb_audit.rest_url и qhb_audit.csv_file, то осуществляется только запись событий в CSV файл.
qhb_audit.rest_max_attempts Максимальное количество попыток отправить событие на сервер при его недоступности.
qhb_audit.rest_attempts_interval_ms Интервал в миллисекундах между попытками отправить сообщение на сервер при его недоступности.
Формат CSV файла
Вновь созданный CSV файл будет состоять из заголовка (первая строка) и непосредственно событий (остальные строки) со следующими полями:
- уникальный в пределах файла или связанного набора ротируемых файлов идентификатор события;
- время, когда событие произошло, в формате RFC3339, например
2018-02-14T00:28:07Z
; - имя события;
- имя типа события;
- имя пользователя, под управлением которого произошло событие;
- имя базы данных при создании соединения;
- имя таблицы (задается только при DDL-операциях на таблице);
- команда SQL, выполнение которой привело к событию;
- степень важности события: low, medium, high, critical, fatal.
Примеры операций и соответствующих записей в CSV-файле
Успешная и неуспешная аутентификация пользователя plop |
---|
0,2023-12-22T08:23:40.516682141Z,connection created:[local]:,authentication control,plop,template1,,,medium |
1,2023-12-22T08:23:40.516682141Z,connection refused:[local]:,authentication control,plop,template1,,,medium |
CREATE USER zodd WITH PASSWORD '123456'; ALTER ROLE zodd RENAME TO gozz; DROP ROLE gozz; |
---|
100,2023-12-22T08:25:14.444569958Z,create role,user account management,plop,,,create user zodd with password <REDACTED>,medium |
101,2023-12-22T08:25:14.447219625Z,alter role rename,user account management,plop,,,alter role zodd rename to gozz;,medium |
102,2023-12-22T08:25:15.284198137Z,drop role,user account management,plop,,,drop role gozz;,medium |
CREATE DATABASE moon; ALTER DATABASE moon RENAME TO dream; DROP DATABASE moon; CREATE TABLE temp (id int, name varchar(255)); ALTER TABLE temp RENAME TO permanent; TRUNCATE TABLE permanent; DROP TABLE permanent; |
---|
400,2023-12-22T08:29:19.313320493Z,create database,changing metadata,plop,moon,,,high |
401,2023-12-22T08:29:19.331731681Z,alter database,changing metadata,plop,moon,,,high |
403,2023-12-22T08:29:19.332957337Z,create table,changing metadata,plop,,temp,,high |
404,2023-12-22T08:29:19.334730324Z,alter table,changing metadata,plop,,temp,,high |
406,2023-12-22T08:29:19.334947840Z,truncate table,changing metadata,plop,,permanent,,high |
405,2023-12-22T08:29:19.337225628Z,drop table,changing metadata,plop,,permanent,,high |
Формат сообщений через REST API
Сообщения о событиях отправляются в формате JSON со следующей схемой:
Наименование | Тип переменной | Описание | Обязательный |
---|---|---|---|
tags | string[] | Сквозные идентификаторы и метки, позволяющие группировать события | Да |
Datetime | integer | Время Unix. Время возникновения события в миллисекундах, прошедших с полуночи (00:00:00 UTC) 1 января 1970 года. (Fri Apr 03 2020 10:28:37 соответствует 1585909717000) | Да |
serviceName | string | Идентификатор службы | Да |
serviceVersion | string | Версия службы | Да |
name | string | Наименование события аудита | Да |
params | object[] | Список параметров события аудита в формате: Name (string) — наименование параметра события аудита, Value (string) — значение параметра события | Да |
sessionID | string | Идентификатор сеанса (если есть) | Нет |
userLogin | string | Логин пользователя | Да |
userName | string | Имя пользователя | Нет |
userNode | string | Узел (IP/FQDN), с которого пользователь выполняет действия | Нет |
Отслеживаемые события
- Попытки подключения клиентов.
- Запуск и останов кластера QHB.
- Восстановление данных после нештатного останова кластера QHB.
- Команды управления ролями и их привилегиями: CREATE/ALTER/DROP ROLE/USER/GROUP, CREATE/ALTER/DROP USER MAPPING, GRANT, REVOKE.
- Команды DDL: CREATE/ALTER/DROP DATABASE, CREATE/ALTER/TRUNCATE/DROP TABLE.
- Команды изменения конфигурации SET, ALTER SYSTEM и ALTER DATABASE
SET . - Нарушения целостности бинарных файлов (core и contrib) и каталога pg_proc (процедур).
- Команды управления процедурами и представлениями: CREATE/ALTER/DROP PROCEDURE, CREATE/ALTER/DROP VIEW, CREATE/ALTER/DROP MATERIALIZED VIEW.
Типы событий
Тип события | Краткое наименование | Важность |
---|---|---|
успешные и неуспешные попытки аутентификации пользователей системы управления базами данных | authentication control | medium |
создание учетных записей пользователей системы управления базами данных | user account management | medium |
изменение атрибутов учетных записей пользователей системы управления базами данных | user account management | medium |
восстановление базы данных | information recovery | medium |
запуск и остановка системы управления базами данных | instance start/stop control | high |
изменение конфигурации системы управления базами данных | changing instance settings | high |
создание и удаление базы данных, таблицы за исключением временных таблиц, создаваемых системой управления базами данных в служебных целях | changing metadata | high |
изменение правил разграничения доступа в системе управления базами данных | access attribute management | high |
создание и изменение процедур (программного кода), хранимых в базах данных, и представлений | procedure and view management | critical |
факты нарушения целостности объектов контроля | integrity violation | fatal |
Полный перечень событий аудита, сгруппированных по типам
Тип | События |
---|---|
authentication control | connection created connection refused |
user account management | create role alter role rename drop role alter role alter role set alter default privileges |
information recovery | crash recovery initiated archive recovery initiated |
instance start/stop control | server started server stopped |
changing instance settings | set param alter system alter database set |
changing metadata | create database alter database drop database create table alter table drop table truncate table |
access attribute management | grant grant role revoke revoke role create user mapping alter user mapping drop user mapping |
procedure and view management | create procedure alter procedure drop procedure create view alter view drop view create materialized view alter materialized view drop materialized view |
integrity violation | integrity check failure for catalog integrity check failure for files |