pg_integrity_verifier#
pg_integrity_verifier
pg_integrity_verifier — проверка целостности баз данных Tantor
pg_integrity_verifier
pg_integrity_verifier
— это специализированный
инструмент, предназначенный для мониторинга целостности баз данных
PostgreSQL. Приложение предназначено для помощи администраторам СУБД
или специалистам по безопасности в контроле целостности баз данных.
Оно сохраняет записи состояний баз данных в указанной директории, а
в случае каких-либо изменений в наблюдаемых базах данных создает
снимок в формате sn_{database}_{datetime}.diff
.
Затем pg_integrity_verifier
выполняет команду,
указанную в run_command
в основном файле
конфигурации. В run_command
указывается команда,
скрипт или другое приложение, предназначенное для анализа изменений
и принятия решений. Например, если зафиксировано изменение структуры
какой-либо таблицы, может быть выполнена отправка уведомления
ответственным специалистам. Как и куда будет отправлено уведомление
должно определяться исключительно внешним приложением. Кроме
уведомлений могут быть выполнены действия, модифицирующие структуру
СУБД или ее конфигурации.
pg_integrity_verifier
может быть запущен любым
пользователем ОС Linux, имеющим полномочия на запуск исполняемого
файла. Важно отметить, что единственное допустимое место подключения
к базам данных для контроля целостности — это текущий хост, то есть
pg_integrity_verifier
должен быть запущен на
одном хосте с наблюдаемой базой данных. Это необходимо, так как для
контроля целостности файлов конфигурации PostgreSQL
postgresql.conf
и pg_hba.conf
приложению необходим локальный доступ к ним. Проверка целостности
может применяться к разным сущностям БД: пользователям,
конфигурациям, таблицам, функциям, триггерам и так далее.
Параметры запуска
Список параметров запуска для
pg_integrity_verifier
:
Параметр | Описание |
---|---|
-c , --config
| Указывает основной файл конфигурации. |
-l , --log
| Указывает файл конфигурации для ведения журнала. |
-v , --version
| Выводит версию приложения. |
-h , --help
| Выводит список доступных опций и информацию об использовании. |
Пример запуска:
./pg_integrity_verifier -l log4rs.yaml -c pg_integrity_verifier.yaml
Основной файл конфигурации
Конфигурация pg_integrity_verifier
задается в
параметре -c
через основной файл конфигурации в
формате yaml
. Этот файл позволяет устанавливать
различные параметры, определяющие взаимодействие приложения с
наблюдаемыми базами данных.
Структура файла:
mode: "<режим работы: one_time или daemon>" daemon_period: "<интервал в секундах для режима daemon>" databases: - db_url: "postgres://<имя пользователя>:<пароль>@<адрес БД>:<порт>/<имя БД>" snapshot_directory: "<каталог для снимков БД>" observed_objs: [<список объектов БД для мониторинга>] run_command: "<команда или скрипт для выполнения при обнаружении изменения> -f DIFF_FILE" - ...
Где:
mode
— режим работы приложения:one_time
— единоразовый запуск.daemon
— периодический запуск через заданные интервалы времени.
daemon_period
— интервал времени в секундах между периодическими запусками.databases
— список наблюдаемых баз данных и их параметры:db_url
— строка подключения к БД в форматеpostgres://<имя пользователя>:<пароль>@<адрес БД>:<порт>/<имя БД>
.Если пароль содержит специальные символы (
@
,%
,#
и так далее), то они должны быть закодированы в процентное кодирование (Percent-encoding). Например, парольpass#word
должен быть указан какpass%23word
.Пароли можно исключить из строк подключения и передавать в переменных окружения
DB<порядковый номер БД>_PASSWORD=<пароль>
. Например:export DB1_PASSWORD=12345 export DB2_PASSWORD=54321
Либо сразу при запуске:
DB1_PASSWORD=12345 DB2_PASSWORD=54321 ./pg_integrity_verifier \ -l log4rs.yaml -c pg_integrity_verifier.yaml
snapshot_directory
— каталог для сохранения снимков текущего состояния базы данных. Убедитесь, что каталог задан и отличается от каталогов, используемых для других наблюдаемых баз данных.observed_objs
— список объектов БД для мониторинга в одинарных кавычках через запятую:'config_file', 'pg_hba', 'pg_settings', 'pg_user', 'pg_proc', 'pg_trigger', 'pg_roles'
. Если пользователь, подключенный к базе данных, не имеет достаточных прав, приложение не будет проверять объектыpostgresql.conf
,pg_hba.conf
иpg_settings
. Еслиobserved_objs
не указан — будут проверяться все объекты, еслиobserved_objs: []
— объекты базы данных проверяться не будут.run_command
— команда или скрипт, который приложение выполнит при обнаружении нарушения целостности БД. Вызываемые команда или скрипт должны поддерживать аргумент-f DIFF_FILE
, в который передается имя конкретного файла, содержащего изменения. ЗаполнительDIFF_FILE
будет заменен на путь к файлу снимка, содержащему обнаруженные различия.
Пример основного файла конфигурации:
mode: "daemon" daemon_period: "5" databases: - db_url: "postgres://postgres:12345@localhost:5432/db1" snapshot_directory: "json1" observed_objs: ['config_file', 'pg_hba', 'pg_settings', 'pg_user', 'pg_proc', 'pg_trigger', 'pg_roles'] run_command: "tests/run_command.sh -f DIFF_FILE" - db_url: "postgres://postgres:54321@localhost:5432/db2" snapshot_directory: "json2" observed_objs: ['config_file', 'pg_hba', 'pg_settings', 'pg_user', 'pg_proc', 'pg_trigger', 'pg_roles'] run_command: "tests/run_command.sh -f DIFF_FILE"
Файл конфигурации для ведения журнала
Конфигурация ведения журнала событий и сообщений приложения
задается в параметре -l
также через файл в
формате yaml
.
Структура файла:
refresh_rate: "<интервал обновления конфигурации в секундах> seconds" appenders: <название компонента>: kind: <тип компонента: console, file, rolling_file, udp или tcp> encoder: pattern: "<шаблон вывода или записи>" path: "<путь к файлу лога>" # Только для типов компонентов file и rolling_file policy: # Только для типа компонентов rolling_file trigger: kind: <тип условия: size, time или compound> limit: <размера файла в байтах> # Только для типа условия size schedule: <расписание в формате cron с расширением для секунд> # Только для типа условия time roller: kind: <тип механизма ротации: fixed_window, delete или compound> base: <начальный индекс> # Только для типа механизма ротации fixed_window count: <количество файлов> # Только для типа механизма ротации fixed_window pattern: "<шаблон имени для ротации>" endpoint: "<адрес>:<порт>" # Только для типов компонентов udp и tcp reconnect: # Только для типа компонентов tcp strategy: <стратегия переподключения: immediate или fixed> delay_ms: <задержка перед попыткой переподключения в миллисекундах> # Только для стратегии fixed root: level: <минимальный уровень логирования: trace, debug, info, warn, error> appenders: - <название компонента 1> - <название компонента 2> ...
Где:
refresh_rate
— интервал времени в секундах между проверками изменения конфигурации наблюдаемых баз данных.appenders
— компоненты, которые определяют, куда будут выводится, записываться или отправляться логи:<название компонента>
— произвольное название компонента. Можно перечислить несколько компонентов со своими параметрами:kind
— тип компонента:console
— вывод в консоль.file
— запись в файл без ротации.rolling_file
— запись в файл с ротацией.udp
— отправка через UDP.tcp
— отправка через TCP.
encoder
— формат записи логов:pattern
— шаблон форматирования записей лога. Поддерживаются переменные:{m}
— сообщение лога.{l}
— уровень логирования.{M}
— имя модуля.{T}
— имя текущего компонента.{f}
— имя файла, в котором был вызван лог.{L}
— номер строки в исходном коде, в котором был вызван лог.{t}
— временная метка в Unix-формате.{I}
— идентификатор компонента.{d(...)}
— дата и время, указанные в круглых скобках с помощью параметров времени Bash. Например,{d(%Y-%m-%d %H:%M:%S)}
задает дату и время в форматеГГГГ-ММ-ДД ЧЧ:ММ:СС
.{h(...)}
— форматирование содержимого в круглых скобках в цветовые коды ANSI и свойства текста, указанные с помощью параметров:fg=<цвет>
— цвет текста.bg=<цвет>
— цвет фона.bold=true
— жирный шрифт.dim=true
— тусклый шрифт.italic=true
— курсив.
Параметры цвета могут принимать следующие значения:
black
,red
,green
,yellow
,blue
,magenta
,cyan
,white
иdefault
. Например,{h({d(%Y-%m-%d %H:%M:%S)} - {l} - {m}{n}, fg=red, bg=black, bold=true)}
выведет указанную в шаблоне запись красным жирным шрифтом на черном фоне.{n}
— перенос строки.
path
— путь к файлу лога. Только для типов компонентовfile
иrolling_file
. При типе компонентовrolling_file
в этот файл записываются логи до того, как сработает триггер ротации.policy
— набор правил для ротации файлов логов для типа компонентовrolling_file
:trigger
— условие, при котором начинается ротация:kind
— тип условия:size
— по размеру файлов.time
— по времени.compound
— комбинация нескольких типов условий. Например, условия по размеру файлов в 100 МБ и по расписанию каждый день в полночь будут выглядеть следующим образом:... kind: compound triggers: - kind: size limit: 104857600 # 100 MB - kind: time schedule: "0 0 0 * * *" # Every day at midnight ...
Файл будет ротирован при выполнение хотя бы одного из указанных условий.
limit
— размер файла при типе условияsize
. Значение размера файла указывается в байтах, но можно и в КБ, МБ и ГБ, явно написав размерность после значения, например:1048576kb
,1024mb
или1gb
соответственно. При превышении файлом указанного размера, файл будет ротирован.schedule
— расписание в формате cron с расширением для секунд при типе условияtime
. Например, выражение*/20 * * * * *
будет запускать ротацию каждые 20 секунд.
roller
— механизм ротации. Он определяет, как файлы будут обрабатываться после ротации.kind
— тип механизма ротации:fixed_window
— фиксированное количество ротационных файлов. Старые файлы будут переименовываться при создании нового файла, а при превышении указанного количества — удаляться.delete
— удаление старых файлов после ротации. Этот тип не предусматривает сохранение какого-либо количества старых файлов, как в случае сfixed_window
. Как только ротация происходит, старый файл удаляется, и на его месте создается новый.compound
— комбинация нескольких типов механизма ротации, каждый из которых будет применяться последовательно. Например, совмещение фиксированного количества ротационных файлов из 10 штук, начиная с 1-го, с шаблоном сохраненияlogs/my_app_{}.log
и удаление старых файлов после ротации будет выглядеть следующим образом:... kind: compound rollers: - kind: fixed_window base: 1 count: 10 pattern: "logs/my_app_{}.log" - kind: delete ...
base
— начальный индекс для нумерации файлов ротации для типа механизма ротацииfixed_window
.count
— количество файлов ротации для типа механизма ротацииfixed_window
. При превышении этого количества самый старый файл будет удален.pattern
— шаблон имени файлов ротации. Символы{}
используются для индекса файла. Например,logs/pg_integrity_{}.log
указывает, что файлы будут сохраняться в каталогlogs
с именамиpg_integrity_1.log
,pg_integrity_2.log
и так далее.
endpoint
— адрес и порт в формате<адрес>:<порт>
, на который будут отправляться логи, для типов компонентовudp
иtcp
.reconnect
— параметры переподключения при разрыве соединения для типа компонентовtcp
.strategy
— стратегия переподключения:immediate
— сразу после разрыва.fixed
— с фиксированной задержкой.
delay_ms
— задержка в миллисекундах перед попыткой переподключения для стратегии переподключенияfixed
.
root
— настройка логирования:level
— минимальный уровень серьезности сообщений, которые будут логироваться:trace
,debug
,info
,warn
илиerror
.appenders
— список описанных выше компонентов, которые необходимо задействовать при логировании.
Пример файла конфигурации для ведения журнала:
refresh_rate: 5 seconds appenders: stdout: kind: console encoder: pattern: "{d(%Y-%m-%d %H:%M:%S)} - {m}{n}" my_file_logger: kind: rolling_file path: "logs/pg_integrity.log" encoder: pattern: "{d(%Y-%m-%d %H:%M:%S)} - {m}{n}" policy: trigger: kind: size limit: 104857600 roller: kind: fixed_window base: 1 count: 10 pattern: "logs/pg_integrity_{}.log" root: level: info appenders: - stdout - my_file_logger
Пример использования
Создайте простой
bash
скрипт, чтобы приложениеpg_integrity_verifier
автоматически его запускало при нарушении целостности заданных типов объектов СУБД. Для этого создайте каталогexamples
, создайте в нем скриптalert_example.sh
и добавьте ему права на выполнение:mkdir -p examples && \ cat > examples/alert_example.sh << 'EOL' #!/bin/bash json_file="" # Function to print usage print_usage() { echo "Usage: $0 -f json_file" } while getopts 'f:' flag; do case "${flag}" in f) json_file="${OPTARG}" ;; *) print_usage exit 1 ;; esac done if [ -z "$json_file" ]; then echo "You must provide a JSON file." print_usage exit 1 fi echo "\n====================================" cat $json_file echo "\n====================================" EOL chmod +x examples/alert_example.sh
Скрипт
alert_example.sh
содержит следующие шаги:Указывается, что скрипт должен быть выполнен с помощью интерпретатора
bash
.Объявляется переменная
json_file
, которая будет содержать путь к JSON-файлу, переданному в скрипт через параметры.Определяется функция
print_usage()
, которая выводит сообщение о том, как правильно использовать скрипт.$0
— это имя скрипта, а-f json_file
указывает на то, что нужно передать флаг-f
, за которым следует путь к JSON-файлу.Опции командной строки обрабатываются в цикле
while
с использованиемgetopts
, что позволяет анализировать флаги и их аргументы.Если флаг
-f
обнаружен, путь к файлу сохраняется в переменнуюjson_file
.Если флаг неизвестен или отсутствует, вызывается функция
print_usage()
, и скрипт завершает работу с кодом ошибки1
.Если переменная
json_file
пуста (параметр не был передан или указан неверно), выводится сообщение, что необходимо передать JSON-файл, и скрипт завершает работу с кодом ошибки 1.Если JSON-файл указан корректно, его содержимое выводится на экран внутри разделительных линий для удобства отображения.
При вызове скрипта выполняется отображение в
stdout
переданного файла. Для практического применения требуется добавить логику по анализу изменений и выполнению конкретных действий, например отправки уведомлений.Создайте основной файл конфигурации
pg_integrity_verifier.yaml
с указанием скриптаexamples/alert_example.sh
. Например:mode: "daemon" daemon_period: "5" databases: - db_url: "postgres://postgres:12345@localhost:5432/db1" snapshot_directory: "json1" observed_objs: ['config_file', 'pg_hba', 'pg_settings', 'pg_user', 'pg_proc', 'pg_trigger', 'pg_roles'] run_command: "examples/alert_example.sh -f DIFF_FILE" - db_url: "postgres://postgres:54321@localhost:5432/db2" snapshot_directory: "json2" observed_objs: ['config_file', 'pg_hba', 'pg_settings', 'pg_user', 'pg_proc', 'pg_trigger', 'pg_roles'] run_command: "examples/alert_example.sh -f DIFF_FILE"
Создайте файл конфигурации для ведения журнала
log4rs.yaml
:refresh_rate: 5 seconds appenders: stdout: kind: console encoder: pattern: "{d(%Y-%m-%d %H:%M:%S)} - {m}{n}" my_file_logger: kind: rolling_file path: "logs/pg_integrity.log" encoder: pattern: "{d(%Y-%m-%d %H:%M:%S)} - {m}{n}" policy: trigger: kind: size limit: 104857600 roller: kind: fixed_window base: 1 count: 10 pattern: "logs/pg_integrity_{}.log" root: level: info appenders: - stdout - my_file_logger
Запустите
pg_integrity_verifier
с созданными конфигурационными файлами:./pg_integrity_verifier \ -l log4rs.yaml \ -c pg_integrity_verifier.yaml
Результат:
2024-05-04 00:14:12 - db1 - The verifying started 2024-05-04 00:14:12 - db1 - No changes found! 2024-05-04 00:14:12 - db1 - The verifying finished 2024-05-04 00:14:12 - db2 - The verifying started 2024-05-04 00:14:12 - db2 - No changes found! 2024-05-04 00:14:12 - db2 - The verifying finished 2024-05-04 00:14:17 - db1 - The verifying started 2024-05-04 00:14:17 - db1 - No changes found! 2024-05-04 00:14:17 - db1 - The verifying finished 2024-05-04 00:14:17 - db2 - The verifying started 2024-05-04 00:14:17 - db2 - No changes found! 2024-05-04 00:14:17 - db2 - The verifying finished ...
Выполните любой SQL-запрос, меняющий структуру БД. Например, запрос на создание пользователя:
su - postgres -c "psql -p 5432 -d db1 -U postgres -c \"CREATE USER test_user_tmp;\""
Убедитесь, что в выводе
pg_integrity_verifier
появилась запись о создании нового пользователя:2024-05-04 00:15:02 - db1 - The verifying started 2024-05-04 00:15:02 - db1 - Added new element with 40975 usesysid: pg_user (usesysid: 40975, usename: test_user_tmp, userecreated: false, useuper: false, userepl: false, usebypassrcls: false, valuntil: None, useconfig: [None]) 2024-05-04 00:15:02 - db1 - Changes have been written to file: json1n_db1.05-04-2024_00:15:02.diff 2024-05-04 00:15:02 - db1 - `examples/alert_example.sh -f /opt/tantor/db/15/tools/ pg_integrity_verifier/json1n_db1_05-04-2024_00:15:02.diff` executed successfully with exit status 0 2024-05-04 00:15:02 - db1 - ==================================== { "database": "db1", "datetime": "05-04-2024_00:15:02", "functions": null, "hba_conf": null, "pg_class": null, "pg_settings": null, "postgresql_conf": null, "triggers": null, "users": [ { "new": { "usebypassrls": false, "useconfig": null, "usecreatedb": false, "usename": "test_user_tmp", "userepl": false, "usesuper": false, "usesysid": 40975, "valuntil": null }, "usesysid": 40975 } ] } ==================================== 2024-05-04 00:15:02 - db1 - The verifying finished 2024-05-04 00:15:02 - db2 - The verifying started 2024-05-04 00:15:02 - db2 - No changes found! 2024-05-04 00:15:02 - db2 - The verifying finished
Таким образом, для информирования администраторов СУБД можно
использовать скрипты, которые будут вызваны приложением
pg_integrity_verifier
при фиксировании
изменений в наблюдаемой БД. В рассмотренном примере
alert_example.sh
принимает через аргумент
-f
файл, содержащий перечень изменений, и
отображает его содержимое. Для реального применения содержимое
входящего файла должно быть интерпретировано, и на основе
изменений должна быть вызвана внешняя система, выполняющая функции
уведомлений, например, отправка e-mail или оповещение в
мессенджере.