Журналирование и аудит#

Для журналирования и аудита событий безопасности используется модифицированное расширение pgAudit. Оно обеспечивает детальное журналирование сессий и объектов для целей аудита. События подключения и события настройки механизма защиты данных включаются в отдельные классы регистрируемых событий для предоставления возможности гибкой настройки аудита. Расширение pgAudit заменяет стандартное средство журналирования PostgreSQL.

Внимание!

Для аудирования действий пользователя в версиях Pangolin до 4.3.0 использовалось расширение pgaudit в варианте, предоставляемом сообществом PostgresSQL. В рамках подготовки к сертификации ФСТЭК в версии 4.3.0 этот инструмент был интегрирован в ядро и получил ряд доработок, расширяющих функциональные возможности аудирования. Начиная с версии 4.4.0 для аудита появилась возможность задавать настройки, применяемые к ролям, включая групповые.

Дополнительные события аудита#

В СУБД Pangolin реализованы дополнительные события аудита. Их мониторинг определяется включением параметра pgaudit.legal.

Формат#

Примечание:

Выходные данные соответствуют формату CSV только в том случае, если префикс строки журнала каждой записи удален.

Записи аудита записываются в стандартное средство ведения журнала и содержат столбцы в формате CSV:

LOG:  AUDIT: <AUDIT_TYPE>,<STATEMENT ID>,<SUBSTATEMENT ID>,<CLASS>,<STATEMENT_TYPE>,<OBJECT_TYPE>,<OBJECT_NAME>,<COMMAND_TEXT>,<PARAMETER_LIST>,ERROR: <ERROR_MESSAGE>

  • AUDIT_TYPE - тип, может быть SESSION (аудит действий пользователя для всех запросов) или OBJECT (аудит действий над каким либо отношением (таблицей));

  • STATEMENT ID - номер запроса;

  • SUBSTATEMENT ID - номер подзапроса;

  • CLASS - класс: DDL, READ, WRITE и т.д. (см. ниже подраздел pgaudit.log);

  • STATEMENT_TYPE - тип запроса CREATE TABLE, ALTER TABLE, SELECT, INSERT, UPDATE, DELETE и т.д.;

  • OBJECT_TYPE - тип объекта, если есть (TABLE, INDEX, VIEW и т.д.);

  • OBJECT_NAME - имя объекта, если есть (например, public.account);

  • COMMAND_TEXT - текст команды;

  • PARAMETER_LIST - список параметров, если есть;

  • ERROR_MESSAGE - сообщение об ошибке, если есть.

Пример:

LOG:  AUDIT: SESSION,1,1,READ,SELECT,,, SELECT * FROM ext.test_table;,<not logged>,ERROR: permission denied for table test_table

У записей класса CONNECTION свой формат:

AUDIT: <AUDIT_TYPE>,<CLASS>,<EVENT>,<SESSION_TIME>,<DATA_BASE>,<USER>, <ID>
  • AUDIT_TYPE — всегда SESSION.

  • CLASS — всегда CONNECTION.

  • EVENTOPEN, CLOSED, FAILED, CHANGE USER.

  • SESSION_TIME — только для события CLOSED. Формат записи: «session time: %d:%02d:%02d.%03d» — часы, минуты, секунды, миллисекунды соответственно.

  • DATA_BASE — имя базы данных, к которой осуществляется подключение. Формат записи: - «database = %s» (имя базы данных).

  • USER — имя пользователя, подключающегося к базе данных. Формат записи: — «user = %s» (имя пользователя).

Пример:

LOG:  AUDIT: SESSION, CONNECTION, OPEN,database = First_db,user = user_test2
LOG:  AUDIT: SESSION, CONNECTION, CLOSED, session time: 0:14:43.261,database = First_db,user = user_test2

Для событий включения и выключения трассировки сессии, записи в журнале имеют формат:

  • AUDIT_TYPE - всегда SESSION;

  • CLASS - всегда MISC;

  • STATEMENT_TYPE - всегда SET;

  • OBJECT_TYPE - всегда TRACING;

  • OBJECT_NAME - пусто;

  • COMMAND_TEXT — зависит от события:

    • для события включения трассировки сессии сообщение вида: \"<start,числовое_значение_уровня_логирования,имя_лог-файла>\". Слово start является константой;

    • для события выключения трассировки сессии содержит константу stop: \"<stop>\".

Пример:

LOG:  AUDIT: SESSION,1,1,MISC,SET,TRACING,,\"<start,15,/pgdata/06/data/tracing/trace1.log>\",<not logged>
LOG:  AUDIT: SESSION,2,1,MISC,SET,TRACING,,\"<stop>\",<not logged>

Для добавления любых других полей, необходимых для удовлетворения требований к журналу аудита, может использоваться префикс строки журнала (log_line_prefix):

Спецсимвол

Назначение

Только для пользовательского процесса

%a

Имя приложения (application_ name)

да

%u

Имя пользователя

да

%d

Имя базы данных

да

%r

Имя удаленного узла или IP-адрес, а также номер порта

да

%h

Имя удаленного узла или IP-адрес

да

%p

Идентификатор процесса

нет

%t

Штамп времени, без миллисекунд

нет

%m

Штамп времени, с миллисекундами

нет

%n

Штамп времени, с миллисекундами (в виде времени Unix)

нет

%i

Тег команды: тип текущей команды в сессии

да

%e

Код ошибки SQLSTATE

нет

%c

Идентификатор сессии. Подробности ниже

нет

%l

Номер строки журнала для каждой сессии или процесса. Начинается с 1

нет

%s

Штамп времени начала процесса

нет

%v

Идентификатор виртуальной транзакции (backendID/ localXID)

нет

%x

Идентификатор транзакции (0 если не присвоен)

нет

%q

Ничего не выводит. Непользовательские процессы останавливаются в этой точке. Игнорируется пользовательскими процессами

нет

%%

Выводит %

нет

Пример префикса строки журнала: «%m %u %d \[%p\]:» - включить дату/время, имя пользователя, имя базы данных и идентификатор процесса для каждой записи журнала аудита.

В качестве идентификатора используется uuidv4 (формируется случайным образом). Для получения идентификатора используется функция gen_random_uuid. Формат идентификатора:

xxxxxxxxxxxxMxxxNxxxxxxxxxxxxxxx
Значения на позициях M и N определяют соответственно версию и вариант UUID

Примечание:

В случае, если опция pgaudit.legal отключена, то записи формируются по старым правилам, и их формат приводится к начальному виду.

Событие восстановления базы данных#

Добавлен новый класс событий RECOVERY, который имеет формат:

AUDIT: <AUDIT_TYPE>,<CLASS>,<ACTION>,<TYPE>,<PHASE>,<DBNAME>,<FILE>,<TIME>,<RESULT>,<ID>,<IMPORTANCE>

Поля:

  • AUDIT_TYPE - тип аудита, всегда SESSION;

  • CLASS - класс события, всегда RECOVERY;

  • ACTION - одно из следующих значений: pg_dump / pg_restore / pg_dumpall / pg_basebackup / pg_probackup / pg_backup_start / pg_backup_stop;

  • TYPE - тип события:

    • BACKUP - создание копии;

    • RESTORE - восстановление из копии;

  • PHASE - фаза:

    • START - начало операции;

    • STOP - завершение операции;

  • DBNAME - имя базы данных;

  • FILE - имя файла / каталога резервной копии;

  • TIME - продолжительность операции в минутах (для фазы START всегда ноль);

  • RESULT - результат операции:

    • SUCCESS - операция успешно завершена;

    • FAIL - операция завершена с ошибкой (для фазы START всегда SUCCESS);

  • ID - идентификатор события;

  • IMPORTANCE - важность события, всегда HIGH.

События RECOVERY возникают при использовании утилит:

  • pg_dump - событие создания резервной копии;

  • pg_restore - событие восстановления из резервной копии;

  • pg_dumpall - событие создания резервной копии;

  • pg_basebackup - событие создания резервной копии;

  • pg_probackup - событие создания резервной копии (событие аудита формируется только в режиме backup);

  • manage_backup - событие создания резервной копии.

Примечание:

События RECOVERY возникают при использовании сторонних утилит, если они используют pg_backup_start / pg_backup_stop (поле ACTION принимает значение pg_backup_start / pg_backup_stop).

Каждая из утилит в процессе своей работы передает на сервер информацию о событии RECOVERY при помощи одной из функций:

  • start_recovery_event;

  • stop_recovery_event;

  • pg_backup_start;

  • pg_backup_stop.

Если в работе утилит не возникает ошибок, то формируется два события RECOVERY, отвечающих за начало процесса (PHASE=START) и за его завершение (PHASE=STOP). Если в процессе работы утилит возникают ошибки, то второе событие может отсутствовать в журнале аудита, либо содержать информацию об ошибке.

Событие нарушение целостности объектов контроля#

Добавлен новый класс событий INTEGRITY, который имеет формат:

AUDIT: <AUDIT_TYPE>,<CLASS>,<INTEGRITY_SUBJECT>,<INTEGRITY_OBJECT>,<INTEGRITY_ERROR>,<INTEGRITY_MODE>,<INTEGRITY_ACTION>,<ID>,<IMPORTANCE>

Поля:

  • AUDIT_TYPE - тип аудита, всегда SESSION;

  • CLASS - класс события, всегда INTEGRITY;

  • INTEGRITY_SUBJECT - субъект контроля:

    • MODULE - контроль загрузки модулей;

    • CORE - контроль целостности объектов базы данных;

    • CONFIG - контроль целостности конфигурации базы данных.

  • INTEGRITY_OBJECT - объекта контроля: путь к файлу или имя базы / каталога;

  • INTEGRITY_ERROR - тип изменения:

    • NOT_ALLOWED - объект запрещен;

    • DELETED - объект удален;

    • CHECK_SUM - контрольная сумма объекта не совпала с ожидаемой;

    • INTERNAL - внутренняя ошибка механизмов контроля целостности (в поле INTEGRITY_OBJECT будет записана расшифровка ошибки).

  • INTEGRITY_MODE - метод контроля, всегда SHA256;

  • INTEGRITY_ACTION - реакция на изменение:

    • SKIP - плагин не загружается/расширение не используется;

    • BLOCK_CONNECTION - блокировка подключения пользователей (кроме суперпользователей);

  • ID - идентификатор события;

  • IMPORTANCE - важность события, всегда EMERGENCY.

События INTEGRITY возникают, когда для объекта контроля обнаруживается одна из ошибок:

  • Объект контроля запрещен к использованию, если настройка не позволяется использовать объект контроля. Например, если расширение не содержится в списке для контроля загрузки модулей. Если список модулей пуст или отсутствует на диске, то при попытке загрузить любой модуль будет возникать данная ошибка.

  • Объект контроля удален (нет доступа).

  • Контрольная сумма объекта контроля не совпадает с ожидаемой.

Для формирования таких событий в модуль pgaudit добавлена функция pgaudit_integrity_violation_event:

/* Integrity subject type */
typedef enum
{
    INTEGRITY_SUBJECT_MODULE,
    INTEGRITY_SUBJECT_CORE
}
IntegritySubjectType;

/* Integrity error type */
typedef enum
{
    INTEGRITY_ERROR_NOT_ALLOWED,
    INTEGRITY_ERROR_DELETED,
    INTEGRITY_ERROR_CHECK_SUM
}
IntegrityErrorType;

/* Integrity mode type */
typedef enum
{
    INTEGRITY_MODE_SHA256
}
IntegrityModeType;

/* Integrity action type */
typedef enum
{
    INTEGRITY_ACTION_SKIP,
    INTEGRITY_ACTION_BLOCK_CONNECTION
}
IntegrityActionType;

/* Integrity violation occurred */
extern void
pgaudit_integrity_violation_event(
    IntegritySubjectType  subject,
    const char           *object,
    IntegrityErrorType    error,
    IntegrityModeType     mode,
    IntegrityActionType   action);

События запуска/остановки базы данных с причиной остановки#

Добавлен новый класс событий ACTION, который имеет формат:

AUDIT: <AUDIT_TYPE>,<CLASS>,<ACTION>,<WHAT>,<ID>,<IMPORTANCE>

Поля:

  • AUDIT_TYPE - тип аудита, всегда SESSION;

  • CLASS - класс события, всегда ACTION;

  • ACTION - действие:

    • START - запуск базы данных;

    • STOP - остановка базы данных;

  • WHAT - причина остановки базы данных (для действия START не заполняется);

  • ID - идентификатор события;

  • IMPORTANCE - важность события, всегда HIGH.

События ACTION возникают при запуске и остановке базы данных.

События изменения конфигурации системы управления базами данных#

Добавлен новый класс событий PARAMETER, который имеет формат:

AUDIT: <AUDIT_TYPE>,<CLASS>,<WHAT>,<ID>,<IMPORTANCE>
  • AUDIT_TYPE - тип аудита, всегда SESSION;

  • CLASS - класс события, всегда PARAMETER;

  • WHAT - сообщение об изменении параметра: "parameter "%name" changed from "%old_value" to "%new_value"":

    • %name - название параметра;

    • %old_value - предыдущее значение параметра;

    • %new_value - новое значение параметра;

  • ID - идентификатор события;

  • IMPORTANCE - важность события, всегда HIGH.

События PARAMETER возникают после перечитывании конфигурации, если:

  1. Параметр был изменен в файле конфигурации СУБД;

  2. Параметр был изменен при помощи ALTER SYSTEM SET name = value; или ALTER SYSTEM RESET name.

Запись событий происходит при включенном параметре `pgaudit.log_parameter.

Действия по изменению параметров для пользователя или сессии (ALTER USER user SET name = value; или SET name = value;) попадают в аудит в рамках класса ROLE или MISC соответственно.

В СУБД Pangolin предусмотрена настройка механизма оповещения администратора системы управления базами данных, администратора базы данных (администратора информационной системы) о событиях безопасности. Далее приведен скрипт оповещения администраторов:

#!/bin/sh
 
# Адрес/адреса администраторов
admins="admin@localhost admin1@localhost admin2@localhost"
 
# В зависимости от конфигурации аудита указывается множество файлов журнала
# Например, если
#     pgaudit.log_filename = 'audit-%u.log'
#     pgaudit.log_directory = '/pgdata/06/data/audit'
# то audit_files=/pgdata/06/data/audit/audit-*.log
audit_files={множество_файлов_журнала}
 
# Каталог для хранения временных файлов, которые создаются в процессе работы скрипта
# Необходимы права для модификации данного каталога
audit_tmp_directory={каталог_для_хранения_временных_файлов}
 
# Пересоздание каталога для хранения временных файлов
rm -rf $audit_tmp_directory
mkdir $audit_tmp_directory
 
# Проверка наличия необходимых утилит для скрипта
t="inotifywait sendmail"
if [ "$(which $t &>/dev/null; echo $?)" != 0 ]
  then
    echo "ERROR: [$t] tools not available! Exiting..."
    exit 1
fi
 
# Сохранение референцных файлов аудита
cp $audit_files $audit_tmp_directory
 
 
while true; do
 
# Ожидание изменений в любом из файлов журнала, возвращает полный путь до измененного файла
file_path=$(inotifywait --format %w -e modify $audit_files)
# Имя файла без пути
file_name=${file_path##*/}
  
# Сохранение измененного файла во временный каталог
# Последующие изменения журнала попадут в новые сообщения
cp $file_path $audit_tmp_directory/audit.tmp
# Сообщение для администратора - это новые данные аудита, добавленные в файл (относительно референцных)
audit_message=$(diff --changed-group-format='%<' --unchanged-group-format='' $audit_tmp_directory/audit.tmp $audit_tmp_directory/$file_name)
 
# Подготовка и отправка письма
# Для конструкции EOF в качестве отступов использовать <tab>
echo "send mail: $audit_message"
 
cat <<EOF | sendmail -t
To: $admins
Subject: audit event occurred
 
$audit_message
EOF
 
# Сохранение файла (после старого event'а) для последующего сравнения
mv $audit_tmp_directory/audit.tmp $audit_tmp_directory/$file_name
 
done

Примечание:

Для обеспечения возможности отправлять email-сообщения с серверов PG требуется наличие утилит: inotifywaitи sendmail.

Параметры#

pgaudit.log#

Настройки аудита хранятся в файле:

  • конфигурация без Pangolin Manager: $PGDATA/postgresql.conf;

  • конфигурация c Pangolin Manager: /etc/pangolin-manager/postgres.yml.

Для возможности мониторинга включения аудита реализована функция проверки check_pg_audit_is_on():

# SELECT * FROM check_pg_audit_is_on();
check_pg_audit_is_on
----------------------
t
(1 row)

Настраиваемый параметр конфигурации pgaudit.log указывает, какие классы операторов будут регистрироваться при ведении журнала аудита сессии. Возможные значения:

  • READSELECT и COPY, если источник — отношение или запрос;

  • WRITEINSERT, UPDATE, DELETE, TRUNCATE и COPY, если цель — отношение;

  • FUNCTION – вызовы функций и блоки DO;

  • ROLE – операторы, связанные с ролями и привилегиями: GRANT, REVOKE, CREATE/ALTER/DROP ROLE;

  • DDL – все DDL, не входящие в класс ROLE;

  • MISC – прочие команды, включая DISCARD, FETCH, CHECKPOINT, VACUUM, SET;

  • MISC_SET – прочие команды SET, включая SET ROLE;

  • CONNECTION – события, связанные с подключением к серверу. Существуют 4 типа таких событий: OPEN, CLOSED, FAILED, CHANGE USER. Событие FAILED регистрируется в случае неудачной попытки аутентификации по паролю и независимо от значения gaudit.log;

  • PROTECTION – функции настройки механизма защиты от привилегированных пользователей;

  • ALL – включить все вышеперечисленное.

Можно включить несколько классов, перечислив их через запятую, или исключить определенные классы, поставив перед ними знак - (см. подраздел «Ведение журнала аудита сессии»).

Значение по умолчанию - none.

Включение/отключение расширенных возможностей аудита: запись логов аудита в отдельный файл, регистрация дополнительных событий аудита, использование нового формата событий аудита. Параметр может быть установлен в значения on/off, применяется при перезапуске сервера.

Значение по умолчанию - off.

pgaudit.log_syslog#

Включение / отключение записи логов аудита в системный журнал при включенной записи в файл. Принимает значение on/off. По умолчанию - off.

pgaudit.log_directory#

Путь к каталогу для сохранения файлов аудита. Это может быть абсолютный путь или заданный относительно каталога данных ($PGDATA). Значение по умолчанию - audit (файлы аудита будут созданы в каталоге $PGDATA/audit).

Если задана пустая строка, то файлы аудита будут создаваться в каталоге $PGDATA.

pgaudit.log_filename#

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

Шаблон может содержать спецпоследовательности, определяющие временную метку, которые начинаются со знака %. Значение по умолчанию audit-%Y-%m-%d_%H%M%S.log.

pgaudit.log_rotation_size#

Максимальный размер файла CSV-журнала в килобайтах.

При достижении установленного лимита для записи событий безопасности создается новый файл. Если параметр равен 0, новый файл в зависимости от размера текущего создаваться не будет. Значение по умолчанию 10 МБ.

pgaudit.log_rotation_age#

Максимальное время жизни файла журнала в минутах.

По истечении этого времени создается новый файл для записи событий безопасности. Если параметр равен 0, создание новых файлов журналов по времени отключается. Значение по умолчанию - 1 день.

pgaudit.log_truncate_on_rotation#

Определяет, должны ли усекаться файлы журналов при переключении записи на уже существующий файл журнала.

Если значение параметра off, запись продолжается в конец файла. Значение по умолчанию - off.

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

pgaudit.log_file_mode#

Определяет права на файл аудита при создании и задается в восьмеричном виде. Значение по умолчанию - 0600.

pgaudit.log_recovery#

Параметр включает или отключает обработку фатальных ошибок, которые могут возникнуть при работе с файлами аудита.

Значение по умолчанию - off.

Для изменения параметров аудита требуются права суперпользователя.

pgaudit.log_catalog#

Указывает, должно ли быть включено ведение журнала сессии в том случае, если все отношения в операторе находятся в pg_catalog. Отключение этого параметра уменьшит шум в журнале от таких инструментов, как psql и pgAdmin, которые часто обращаются к каталогу.

Значение по умолчанию - on.

pgaudit.log_client#

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

Обратите внимание, что pgaudit.log_level включен только тогда, когда pgaudit.log_client включен.

Значение по умолчанию - off.

pgaudit.log_level#

Указывает уровень журналирования, который будет использоваться для записей журнала (см. Уровни важности событий аудита). Обратите внимание, что значения ERROR, FATAL и PANIC не допускаются. Этот параметр используется для регрессионного тестирования, а также может быть полезен конечным пользователям для тестирования или других целей.

pgaudit.log_level включен только тогда, когда pgaudit.log_client включен; в противном случае будет использоваться значение по умолчанию.

Значение по умолчанию - log.

pgaudit.log_parameter#

Указывает, что ведение журнала аудита должно включать параметры, переданные вместе с оператором. При наличии параметров они будут включены в формате CSV после текста оператора.

При включенном параметре (pgaudit.log_parameter = on) в аудит попадают записи о событиях изменения конфигурации системы управления базами данны.

Значение по умолчанию - off.

pgaudit.log_relation#

Указывает, должно ли ведение журнала аудита сессии создавать отдельную запись журнала для каждого отношения (TABLE, VIEW и т.д.), на которое ссылается оператор SELECT или DML. Это полезный прием для исчерпывающего ведения журнала без использования журнала аудита объектов.

Значение по умолчанию - off.

pgaudit.log_statement_once#

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

Значение по умолчанию - off.

pgaudit.role#

Указывает главную роль, используемую для ведения журнала аудита объектов. Можно определить несколько ролей аудита, предоставив их главной роли. Это позволяет нескольким группам отвечать за различные аспекты ведения журнала аудита.

Значения по умолчанию нет.

Ротация файлов аудита#

Файлы аудита могут быть ротированы в процессе записи событий аудита. В функциональность встроено четыре механизма ротации файлов аудита:

  • по запросу (сигнал SIGUSR1);

  • при изменении параметров pgaudit.log_directory, pgaudit.log_filename;

  • по времени (период ротации настраивается параметром pgaudit.log_rotation_age);

  • по размеру файла (размер файла, по превышении которого произойдет ротация, настраивается параметром pgaudit.log_rotation_size).

Примечание:

Размер ротированного файла с логом аудита будет превышать значение pgaudit.log_rotation_size, так как ротация происходит по факту превышения, после записи сообщения аудита.

Такое поведение совпадает с логикой ротации файлов с логами базы данных.

Если файл со сформированным при ротации именем уже существует на диске, то запуск очистки старого содержимого будет зависеть от значения параметра pgaudit.log_truncate_on_rotation:

Параметр

Ротация по запросу

Ротация при изменении параметров

Ротация по размеру

Ротация по времени

on

дозапись

дозапись

дозапись

дозапись

off

дозапись

дозапись

дозапись

очистка

Если во время ротации по времени или размеру происходит ошибка, то эти механизмы ротации отключаются. Чтобы вновь включить ротацию по времени или размеру, выполните ротацию по запросу или обновите параметры, влияющие на имя файла аудита.

Логика механизма ротации приведена ниже:

Примечание:

Данное поведение совпадает с механизмом ротации логов базы данных.

Обработка ошибок#

Если при запуске базы данных и включении функциональности происходит ошибка открытия файла аудита, база данных не стартует.

Если во время ротации файла аудита происходит ошибка, то реакция зависит от параметра pgaudit.log_recovery:

  • включен — лог аудита продолжает записываться в текущий файл, при этом в лог базы данных выводятся предупреждения о невозможности ротации:

    WARNING: Could not rotate audit file: ошибка
    WARNING: Recovery mode is on: continue writing to the current file "текущее имя файла"
    
  • выключен — Pangolin останавливается с фатальной ошибкой:

    FATAL: Could not rotate audit file: ошибка
    

Если во время записи в файл происходит ошибка, то реакция зависит от параметра pgaudit.log_recovery и кода ошибки.

При включенном pgaudit.log_recovery:

errno

Описание

Реакция auditlogger

Сообщение в лог

EAGAIN

Установлен флаг O_NONBLOCK

Ошибка не ожидается, обработка неопределенной ошибки

Не выводится

EBADF

Запись происходит в невалидный дескриптор

Повторная запись во временный файл

Не выводится

EFBIG

Попытка записи в файл, превышающий максимальный размер (лимит), доступный в системе

Повторная запись во временный файл

Не выводится

EINTR

Операция записи прервана

Повторная запись в текущий файл

Не выводится

EIO

Ошибка записи на физическом уровне

Повторная запись во временный файл

Не выводится

ENOSPC

На устройстве нет памяти

Фатальная ошибка

FATAL:  An unhandled error occurred: ошибка, Fail to write audit data: сообщенние аудита

EPIPE

Ошибка записи в pipe

Ошибка не ожидается, обработка неопределенной ошибки

Не выводится

ENOMEM

На устройстве нет памяти

Фатальная ошибка

FATAL:  An unhandled error occurred: ошибка, Fail to write audit data: сообщенние аудита

?

Неопределенная ошибка

Повторная запись во временный файл

WARNING: Unknown error: ошибка

Имя временного файла получается из имени текущего файла с припиской .recovery. При создании временного файла выводится предупреждение:

WARNING:  Create recovery audit file имя временного файла

Повторная ошибка при записи во временный файл приводит к остановке Pangolin:

FATAL: Fail to write audit data: сообщение аудита

Если pgaudit.log_recovery выключен, то попытки создать и записать сообщение во временный файл не происходит, Pangolin останавливается сразу:

FATAL: Fail to write audit data: сообщение аудита

Ошибка может произойти при отправке сообщения аудита, реакция зависит от параметра pgaudit.log_recovery:

  • включен — сообщение аудита будет отправлено в лог Pangolin, который так же будет содержать предупреждение:

    WARNING: Could not write audit message: ошибка
    
  • выключен — процесс, который отправляет сообщение аудита, завершается с ошибкой:

    FATAL: Could not write audit message: ошибка
    

Уровни важности событий аудита#

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

Уровень важности

Признаки событий

Аварийный EMERGENCY

События полной блокировки пользовательского доступа пользователей к СУБД или отдельным БД. Например, скомпроментированы двоичные файлы ядра СУБД / в память СУБД загружен недоверенный код / перезаписана контролируемая функция

Фатальный FATAL

События блокировки одиночного объекта или ограничения доступа к объекту. Например, превышено количество неуспешных попыток авторизации / пользователь заблокирован по параметру парольной политики

Критический CRITICAL

События отказа в неавторизованном доступе. Например, отклонена попытка подключения с неверным паролем / суперпользователь попробовал без разрешения прочитать или изменить данные в объекте под защитой от действий пользователя

Высокий HIGH

События изменения объектов защиты и прав на них (пользовательские УЗ и пароли, параметры политик, права на объекты, системные привилегии и др.), а также вызов команд для изменения БД, схем, отношений, кода, когда есть возможность задать / сменить владельца объекта, схему, права доступа. Добавление / изменение фильтров, умеющих просматривать параметры или результаты, менять поведение других команд. Например, ALTER USER (GROUP), CREATE DATABASE, CREATE EVENT TRIGGER..

Cредний MEDIUM

События получения разрешенных привилегий для их применения (SET - включение SET ROLE). Прочие действия, разрешенные только суперпользователю (перезапуск сервера, снятие и восстановление резервной копии и др.), администратору безопасности (просмотр политики) или существующему владельцу объекта (настройка индексов, триггеров и т.п.). При условии, что действия не ведут к изменению объектов / прав / кода. Например, подключение / отключение сессии, вызов CREATE INDEX

Низкий LOW

Нормальное, постоянное использование полученных привилегий: SELECT / INSERT / UPDATE / DELETE и прочие пользовательские действия

Отладочный DEBUG

Внутренняя информация о деятельности механизмов защиты

Настройка доступа к журналу событий безопасности#

Журнал событий аудита представляет собой коллекцию текстовых файлов. Файлы можно просмотреть средствами операционной системы. Чтобы разграничить доступ к этим файлам необходимо настроить чтение файлов журнала на уровне SQL. Для этого рекомендуется использовать расширение file_fdw — обертку сторонних данных для обращения к файлам на сервере.

Инструкция по разграничению доступа к журналу аудита:

  1. Установите file_fdw и создайте определение стороннего сервера:

CREATE EXTENSION file_fdw;
CREATE SERVER pangolin_audit_server FOREIGN DATA WRAPPER file_fdw;
  1. Создайте стороннюю таблицу, определив ее столбцы и указав абсолютный путь к файлу журнала. Фактический путь определяется параметрами pgaudit.log_directory и pgaudit.log_filename:

CREATE FOREIGN TABLE pangolin_audit
      ( audit_time timestamp(3) with time zone,
        role_name text,
        database_name text,
        process_id bigint,
        remote_host_port text,
        session_id text,
        session_line_num bigint,
        ps_display text,
        session_start_time timestamp(3) with time zone,
        virtual_transaction_id text,
        transaction_id bigint,
        error_severity text,
        sql_state text,
        audit_data text,
        audit_detailed text,
        audit_hint text,
        internal_query text,
        internal_query_position text,
        context text,
        user_query text,
        user_query_position text,
        file_position text,
        app_name text,
        backend_type text,
        leader_id text,
        query_id bigint)
SERVER pangolin_audit_server
OPTIONS (filename 'абсолютный_путь_к_файлу_журнала_аудита', FORMAT 'csv' );
> **Примечание:**
>
> Если журнал аудита состоит из множества файлов (настройка `pgaudit.log_filename` содержит временные метки, а также включена ротация файлов по времени или размеру), то необходимо создавать одну родительскую таблицу, определяющую формат, с множеством дочерних таблиц для доступа к отдельным файла журнала. Количество файлов зависит от настроек аудита.
  1. Сделайте файлы журнала аудита доступными только для владельца и установите в значение 0600 (значение по умолчанию) параметр pgaudit.log_file_mode.

    Если файлы уже созданы, то для каждого из них выполните команду:

    chmod 600 файл_журнала_аудита
    
  2. Настройте ограничения доступа к определенным записям журнала: создайте отдельные представления на базе таблицы pangolin_audit и разрешите чтение этих представлений, используя встроенные механизмы управления доступом СУБД Pangolin.

Далее приведен пример по разграничению доступа к журналу аудита, разбитому по дням недели:

  1. Выполните пункт 1 из инструкции по разграничению доступа к журналу аудита, приведенной выше.

  2. Настройте параметры аудита для включения ротации по дням недели:

    pgaudit.log_filename = 'audit-%u.log'
    pgaudit.log_directory = '/pgdata/06/data/audit'
    pgaudit.log_rotation_age = 1440
    pgaudit.log_rotation_size = 0
    pgaudit.log_truncate_on_rotation = on
    
  3. Создайте пустые файлы журнала аудита для семи дней недели и сделайте их доступными только для владельца:

    touch /pgdata/06/data/audit/audit-1.log
    touch /pgdata/06/data/audit/audit-2.log
    touch /pgdata/06/data/audit/audit-3.log
    touch /pgdata/06/data/audit/audit-4.log
    touch /pgdata/06/data/audit/audit-5.log
    touch /pgdata/06/data/audit/audit-6.log
    touch /pgdata/06/data/audit/audit-7.log
    chmod 600 /pgdata/06/data/audit/audit-*.log
    
  4. Создайте таблицу для чтения записей журнала:

    CREATE TABLE pangolin_audit
       ( audit_time timestamp(3) with time zone,
         role_name text,
         database_name text,
         process_id bigint,
         remote_host_port text,
         session_id text,
         session_line_num bigint,
         ps_display text,
         session_start_time timestamp(3) with time zone,
         virtual_transaction_id text,
         transaction_id bigint,
         error_severity text,
         sql_state text,
         audit_data text,
         audit_detailed text,
         audit_hint text,
         internal_query text,
         internal_query_position text,
         context text,
         user_query text,
         user_query_position text,
         file_position text,
         app_name text,
         backend_type text,
         leader_id text,
         query_id bigint);
    
  5. Создайте для таблицы pangolin_audit семь дочерних сторонних таблиц (для каждого дня недели):

    CREATE FOREIGN TABLE pangolin_audit_1 () INHERITS (pangolin_audit) SERVER pangolin_audit_server
    OPTIONS (filename '/pgdata/06/data/audit/audit-1.log',  FORMAT 'csv');
    CREATE FOREIGN TABLE pangolin_audit_2 () INHERITS (pangolin_audit) SERVER pangolin_audit_server
    OPTIONS (filename '/pgdata/06/data/audit/audit-2.log',  FORMAT 'csv');
    CREATE FOREIGN TABLE pangolin_audit_3 () INHERITS (pangolin_audit) SERVER pangolin_audit_server
    OPTIONS (filename '/pgdata/06/data/audit/audit-3.log',  FORMAT 'csv');
    CREATE FOREIGN TABLE pangolin_audit_4 () INHERITS (pangolin_audit) SERVER pangolin_audit_server
    OPTIONS (filename '/pgdata/06/data/audit/audit-4.log',  FORMAT 'csv');
    CREATE FOREIGN TABLE pangolin_audit_5 () INHERITS (pangolin_audit) SERVER pangolin_audit_server
    OPTIONS (filename '/pgdata/06/data/audit/audit-5.log',  FORMAT 'csv');
    CREATE FOREIGN TABLE pangolin_audit_6 () INHERITS (pangolin_audit) SERVER pangolin_audit_server
    OPTIONS (filename '/pgdata/06/data/audit/audit-6.log',  FORMAT 'csv');
    CREATE FOREIGN TABLE pangolin_audit_7 () INHERITS (pangolin_audit) SERVER pangolin_audit_server
    OPTIONS (filename '/pgdata/06/data/audit/audit-7.log',  FORMAT 'csv');
    
  6. Выполните пункт 4 из инструкции по разграничению доступа к журналу аудита выше.

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

Для архивирования журнала возможно использовать утилиту logrotate.

Далее приведена инструкция по настройке архивирования журнала при помощи утилиты logrotate:

  1. Добавьте конфигурационный файл pangolin_audit в каталог /etc/logrotate.d/. Содержимое pangolin_audit:

    {путь к файлам журнала аудита}
    {
    missingok
    daily
    copytruncate
    notifempty
    size 1G
    compress
    }
    

    Опции:

    • missingok – не выдавать ошибки, если лог-файла не существует;

    • daily – обрабатывать журнал каждый день (с возможностью установить другой интервал проверки):

      • hourly - каждый час;

      • weekly - каждую неделю;

      • monthly - каждый месяц;

      • yearly - каждый год.

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

    • notifempty – не ротировать файл лога, если он пуст;

    • compress — сжатие логов;

    • size — размер лога, при достижении которого он будет перемещен (в примере выше указан 1 Гбайт).

    Путь к файлам журнала аудита зависит от настроек, например, для настроек, приведенных далее, путь будет соответствовать /pgdata/06/data/audit/audit-*.log.

  2. Проверьте конфигурационный файл при помощи команды:

    sudo logrotate /etc/logrotate.conf --debug
    

    В каталоге аудита будут появляться архивированные логи аудита.

Минорное обновление#

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

DO $$
DECLARE
  text_type_id integer;
  bool_type_id integer;
  int4_type_id integer;
 
BEGIN

-- Create new functions
CREATE FUNCTION pg_catalog.stop_recovery_event(text, text, text, bool, int4, bool)
 RETURNS void
 LANGUAGE internal
 STABLE PARALLEL SAFE STRICT
AS $function$stop_recovery_event$function$;

CREATE FUNCTION pg_catalog.start_recovery_event(text, text, text, bool)
 RETURNS boolean
 LANGUAGE internal
 STABLE PARALLEL SAFE STRICT
AS $function$start_recovery_event$function$;

SELECT oid INTO text_type_id FROM pg_type WHERE typname='text';
SELECT oid INTO bool_type_id FROM pg_type WHERE typname='bool';
SELECT oid INTO int4_type_id FROM pg_type WHERE typname='int4';

-- Update params for new functions
UPDATE pg_catalog.pg_proc AS pp SET
proallargtypes = ARRAY[text_type_id,text_type_id,text_type_id,bool_type_id,int4_type_id,bool_type_id],
proargmodes = '{i,i,i,i,i,i}',
proacl = '{postgres=X/postgres}'
WHERE pp.oid = (select oid from pg_catalog.pg_proc where proname = 'stop_recovery_event');

UPDATE pg_catalog.pg_proc AS pp SET
proallargtypes = ARRAY[text_type_id,text_type_id,text_type_id,bool_type_id],
proargmodes = '{i,i,i,i}',
proacl = '{postgres=X/postgres}'
WHERE pp.oid = (select oid from pg_catalog.pg_proc where proname = 'start_recovery_event');

GRANT EXECUTE ON FUNCTION pg_catalog.stop_recovery_event(text, text, text, bool, int4, bool) TO PUBLIC;
GRANT EXECUTE ON FUNCTION pg_catalog.start_recovery_event(text, text, text, bool) TO PUBLIC;

EXCEPTION
  WHEN duplicate_function THEN
  NULL;
END$$;

Рекомендации#

В зависимости от настроек журнал pgAudit может достигать очень больших объемов. Следует максимально точно определить, что именно должно быть записано в журнал аудита в вашей среде, чтобы избежать слишком большого количества записей.

Например, при работе в среде OLAP не лучшим решением станет проверять вставки журналов в большую таблицу фактов. Размер файла журнала, скорее всего, будет во много раз больше фактического размера данных вставок, поскольку файл журнала хранится в текстовом виде. И так как журналы обычно хранятся на диске вместе с ОС, это может привести к очень быстрому исчерпанию дискового пространства.

В тех случаях, когда невозможно ограничить ведение журнала аудита определенными таблицами, следует обязательно оценить влияние на производительность во время тестирования и выделить достаточно места на томе журнала. Это также может быть верно для сред OLTP. Даже если объем операций вставки не так высок, влияние журнала аудита на производительность все равно может привести к заметному росту задержки.

Чтобы ограничить количество записей аудита отношений для операторов SELECT и DML, рассмотрите возможность использования журнала аудита объектов (см. ниже подраздел «Ведение журнала аудита объектов»). Ведение журнала аудита объектов позволяет выбрать отношения, которые будут регистрироваться, что позволяет уменьшить общий объем журнала. Однако все новые создаваемые отношения должны быть явно добавлены в журнал аудита объектов. В этом случае хорошим вариантом может быть программное решение, в котором некоторые определенные таблицы исключаются из ведения журнала, а все остальные включаются.

Внимание!

Настройки pgaudit могут быть изменены только суперпользователем.

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

Настройки не наследуются через обычное наследование ролей, и SET ROLE не изменит настройки pgaudit пользователя. Это ограничение системы ролей, а не особенность pgaudit.

Настройки могут быть заданы:

  • глобально – в файле postgresql.conf или с помощью ALTER SYSTEM ... SET;

  • на уровне базы данных – с помощью ALTER DATABASE ... SET;

  • на уровне роли – с помощью ALTER ROLE ... SET.

Чтобы логи аудита выводились в журнал, в файле postgresql.conf задайте параметры:

pgaudit.log = 'ddl, role, connection, misc_set, protection'
pgaudit.log_client = 'on'
pgaudit.log_level = 'log'

Ведение журнала аудита сессии#

Журнал аудита сессии отображает подробные записи всех операций, выполняемых пользователем на сервере.

Конфигурирование#

Ведение журнала сессии включается с помощью параметра pgaudit.log.

Включить ведение журнала сессии для всех DML и DDL и протоколировать все отношения в операторах DML:

set pgaudit.log = 'write, ddl';

set pgaudit.log_relation = on;

Включить ведение журнала сессии для всех команд, кроме MISC, и выводить сообщения журнала аудита с пометкой NOTICE:

set pgaudit.log = 'all, -misc';

set pgaudit.log_level = notice;

В примере ниже ведение журнала аудита сессии используется для ведения журнала операторов DDL и SELECT. Обратите внимание, что оператор INSERT не регистрируется, так как класс WRITE не включен.

Пример:

set pgaudit.log = 'read, ddl';

create table account
(
    id int,
    name text,
    password text,
    description text
);

insert into account (id, name, password, description)
             values (1, 'user1', 'HASH1', 'blah, blah');

select *
    from account;

Вывод в журнале:

AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.account,create table account
(
    id int,
    name text,
    password text,
    description text
);,<not logged>
AUDIT: SESSION,2,1,READ,SELECT,,,select *
    from account,,<not logged>

Ведение журнала аудита объектов#

Журнал аудита объектов регистрирует операторы, влияющие на определенное отношение. Поддерживаются только команды SELECT, INSERT, UPDATE и DELETE. Операция TRUNCATE не включается в журнал аудита объектов.

Ведение журнала аудита объектов — более подробная альтернатива pgaudit.log = 'read, write'. Таким образом, возможно, нет смысла использовать их вместе, но можно, например, использовать ведение журнала сеансов для регистрации каждого оператора, а затем дополнить его ведением журнала объектов, чтобы получить более подробную информацию о конкретных отношениях.

Конфигурирование#

Ведение журнала аудита на уровне объектов осуществляется через систему ролей. Параметр pgaudit.role определяет роль, которая будет использоваться для ведения журнала аудита. Отношение (TABLE, VIEW) будет записываться в журнал аудита, если роль аудита имеет разрешения для выполняемой команды или наследует разрешения от другой роли. Это позволяет эффективно использовать несколько ролей аудита, даже если в любом контексте существует одна главная роль.

Задайте для pgaudit.role значение auditor и наделите ее правами SELECT и DELETE над таблицей account. Теперь операции SELECT и DELETE над таблицей account будут заноситься в журнал:

set pgaudit.role = 'auditor';

grant select, delete
   on public.account
   to auditor;

В примере ниже ведение журнала аудита объектов используется для иллюстрации того, как может быть применен детализированный подход к журналированию операторов SELECT и DML. Обратите внимание, что ведение журнала операций над таблицей account контролируется разрешениями на уровне столбцов, а ведение журнала операций над таблицей account_role_map — на уровне таблиц.

Пример:

set pgaudit.role = 'auditor';

create table account
(
    id int,
    name text,
    password text,
    description text
);

grant select (password)
   on public.account
   to auditor;

select id, name
  from account;

select password
  from account;

grant update (name, password)
   on public.account
   to auditor;

update account
   set description = 'yada, yada';

update account
   set password = 'HASH2';

create table account_role_map
(
    account_id int,
    role_id int
);

grant select
   on public.account_role_map
   to auditor;

select account.password,
       account_role_map.role_id
  from account
       inner join account_role_map
            on account.id = account_role_map.account_id

Вывод в журнале:

AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.account,select password
  from account,<not logged>
AUDIT: OBJECT,2,1,WRITE,UPDATE,TABLE,public.account,update account
   set password = 'HASH2',<not logged>
AUDIT: OBJECT,3,1,READ,SELECT,TABLE,public.account,select account.password,
       account_role_map.role_id
  from account
       inner join account_role_map
            on account.id = account_role_map.account_id,<not logged>
AUDIT: OBJECT,3,1,READ,SELECT,TABLE,public.account_role_map,select account.password,
       account_role_map.role_id
  from account
       inner join account_role_map
            on account.id = account_role_map.account_id,<not logged>

Лог Pangolin Manager#

Перенаправление записи лога из системного журнала в файл#

Функциональность позволяет перенаправить запись лога Pangolin Manager в файл, вместо системного журнала (journald).

Для включения перенаправления лога в файл необходимо в postgres.yml настроить параметры в секции log:

log:
destination: file
file_name: pangolin-manager.log
file_mode: 644
redirect_min_size: 10

Описание параметров:

  • destination: file – отвечает за вывод в лог-файл, значение по умолчанию file. Если значение установлено в syslog вывод осуществляется в journald. Соответствует переменной окружения PATRONI_LOG_DESTINATION. Для применения параметра достаточно выполнения reload.

  • file_name: pangolin-manager.log – отвечает за имя лог-файла, значение по умолчанию pangolin-manager.log. Соответствует переменной окружения PATRONI_LOG_FILE_NAME. Применение параметра производится только после остановки/перезапуска Pangolin средствами systemctl.

  • file_mode: 644 – устанавливает права доступа к лог-файлу. Применение параметра производится только после остановки/перезапуска Pangolin средствами systemctl.

  • redirect_min_size: 10 – устанавливает размер минимально свободного места (в Кб) в системе для логирования, при достижении которого происходит переключение потока логирования в системный журнал. При установке redirect_min_size: 0, для ускорения работы Pangolin Manager, проверка свободного места не осуществляется. После освобождения места в папке логирования необходимо выполнить команду reload и логирование продолжится в файл.

Одновременно может быть активен только один канал вывода: или системный журнал, или лог-файл. Для переключения вывода лога достаточно команды reload (параметр destination).

Примечание:

Если Pangolin Manager не имеет доступа к директории, указанной в параметре dir или не может создать файл, указанный в параметре file_name, то вывод осуществляется в системный журнал.

Для повышения удобства эксплуатации, в старое место назначения записи лога выводится информационная строка, сообщающая куда именно будет проводиться дальнейший вывод логированной информации (syslog или полное имя файла). Это строчка может быть не последней – это специфика работы буферизации вывода.

Табличное представление параметров (включает присвоение значение из переменной окружения – внимание, для сервиса источником переменных окружения являются только настройки .service-файла):

Параметр

Переменная окружения

Значение по умолчанию

Влияние

log: destination

PATRONI_LOG_DESTINATION

file

Применяется при загрузке/релоаде сервиса и демона (systemctl –user daemon-reload)

log: file_name

PATRONI_LOG_FILE_NAME

pangolin-manager.log

Применяется при загрузке/перезагрузке сервиса и демона (systemctl –user daemon-reload)

log: file_mode

PATRONI_LOG_FILE_MODE

644

Применяется при загрузке/перезагрузке сервиса и демона (systemctl –user daemon-reload)

log: redirect_min_size

PATRONI_LOG_REDIRECT_MIN_SIZE

10

Применяется при загрузке/релоаде сервиса и демона (systemctl –user daemon-reload)

Примечание:

Дополнительные параметры, отвечающие за директорию и настройки ротации остались без изменений относительно ванильной реализации.