# Занятие 15: Безопасность / Аудит

> Исходная страница в нативном Markdown: Безопасность / Аудит

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

<!-- Generated by scripts/generate_skeleton.py. -->

> [!NOTE]
> Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета.
> **HTML source:** [pgpro_15_audit.html](https://edu.postgrespro.ru/16/pgpro-16/pgpro_15_audit.html)
> **Archive:** [PGPRO-handouts-16.zip](https://edu.postgrespro.ru/16/PGPRO-handouts-16.zip)
> **Страниц PDF:** 21

## Page 1: Безопасность / Аудит {#source-page-001}

### Авторские права

© Postgres Professional, 2023–2026 Авторы: Алексей Береснев, Илья Баштанов, Павел Толмачев, Игорь Гнатюк Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
### Использование материалов курса

Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.
### Обратная связь

Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru
### Отказ от ответственности

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

## Page 2: Темы {#source-page-002}

- Расширение pg\_proaudit
- Возможности pg\_proaudit
- Аудит ролей и объектов
- Сохранение настроек
- Запись событий аудита

## Page 3: Расширение pg_proaudit {#source-page-003}

**Аудит — средство сбора событий безопасности**
  - не отладка (поиск ошибок и неисправностей)
  - не мониторинг (выявление аномалий и проблем)
- Не зависит от обычного журнала сообщений
  - отдельный фоновый процесс
  - отдельный журнал событий безопасности
- Доступ к расширению и журналу событий безопасности должен быть предоставлен только уполномоченным ролям

### Комментарии преподавателя

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

Расширение pg\_proaudit разработано в Postgres Professional для регистрации событий, связанных с безопасностью. Оно реализует концепцию независимости подсистемы аудита. Для этого запускается отдельный фоновый процесс pg\_proaudit logging worker, который регистрирует события безопасности независимо от записи в обычный журнал сообщений сервера.

Место размещения журнала событий безопасности (журнал аудита) в файловой системе и настройки для передачи сообщений в syslog или во внешнюю систему определяются параметрами конфигурации расширения pg\_proaudit. Каждое событие описывается фиксированным набором полей, для него формируется отдельная строка журнала или отдельное сообщение.

Доступ к расширению pg\_proaudit и журналам аудита следует предоставлять только пользователям, исполняющим роль администратора информационной безопасности (например, администратору безопасности; см. тему «Защищенная схема»).

<https://postgrespro.ru/docs/enterprise/16/pg-proaudit#PG-PROAUDIT>

## Page 4: Установка расширения pg_proaudit {#source-page-004}

Создадим базу данных.
```sql
=> CREATE DATABASE pgpro_audit;
```
```sql
CREATE DATABASE
```
Расширение pg\_proaudit требует загрузки одноименной разделяемой библиотеки:
```sql
=> ALTER SYSTEM SET shared_preload_libraries = 'pg_proaudit';
```
```sql
ALTER SYSTEM
```
Необходимо рестартовать СУБД.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
```sh
student$ psql -d pgpro_audit
```
Создадим расширение pg\_proaudit:
```sql
=> CREATE EXTENSION pg_proaudit;
```
```sql
CREATE EXTENSION
```
В результате в списке процессов экземпляра должен быть виден процесс pg\_proaudit logging worker.
```sh
student$ ps -o pid,command --ppid 828958
```
```text
    PID COMMAND
 828960 postgres: logger
 828961 postgres: checkpointer
 828962 postgres: background writer
 828964 postgres: walwriter
 828965 postgres: autovacuum launcher
 828966 postgres: cfs-worker-0
 828967 postgres: pg_proaudit logging worker
 828968 postgres: logical replication launcher
 829006 postgres: student pgpro_audit [local] idle
```

## Page 5: Возможности pg_proaudit {#source-page-005}

![Source slide page 5: Возможности pg_proaudit](images/page-005.png){#source-figure-005 caption="Source slide page 5: Возможности pg_proaudit"}

**Классы фиксируемых событий**
  - команды DDL — создание, изменение и удаление объектов баз данных
  - команды DCL — управление доступом к объектам баз данных
  - команды DML — обращение к объектам баз данных
  - подключения и отключения
  - действия, выполняемые заданной ролью

### Комментарии преподавателя

Расширение pg\_proaudit позволяет отслеживать действия заданных ролей, а также следить за операциями с заданными объектами (например, конкретными таблицами) или с определенными классами объектов и событий:

● команды создания, изменения и удаления объектов СУБД;

● команды управления доступом к объектам баз данных;

● команды обращения к объектам баз данных;

● события аутентификации или отключения от баз данных;

● любые команды, выполняемые заданным пользователем.

В том числе можно регистрировать в журнале аудита обращения к системному каталогу и отслеживать работу с профилями. Есть возможность исключить аудит временных объектов.

Полный список регистрируемых событий и классов событий: <https://postgrespro.ru/docs/enterprise/16/pg-proaudit#PG-PROAUDIT-EVEN> T-TYPES

## Page 6: Аудит ролей и объектов {#source-page-006}

**Управление аудитом ролей, объектов или типов объектов**
  - pg\_proaudit\_set\_rule()
  - pg\_proaudit\_remove\_rule()
- Отключение аудита всех событий
  - pg\_proaudit\_reset()
- Текущие настройки
  - представление pg\_proaudit\_settings

### Комментарии преподавателя

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

● pg\_proaudit\_set\_rule — создание правила регистрации;

● pg\_proaudit\_remove\_rule — удаление правила регистрации.

Функция pg\_proaudit\_reset отключает регистрацию всех событий.

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

Текущие настройки аудита (список правил) можно получить с помощью представления pg\_proaudit\_settings.

## Page 7: Аудит ролей и объектов {#source-page-007}

Включим аудит всех событий, связанных с управлением ролями — для текущей базы, для всех объектов и всех ролей:
```sql
=> SELECT pg_proaudit_set_rule(
  db_name => current_database(),
  event_type => 'ALL',
  object_type => 'ROLE',
  object_name => NULL,
  role_name => NULL
);
```
```text
 pg_proaudit_set_rule
----------------------
 t
(1 row)
```
Аудит включается немедленно.
Для проверки настроек аудита используется представление:
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```text
   db_name   | event_type | object_type | object_name | role_name | comment
-------------+------------+-------------+-------------+-----------+---------
 pgpro_audit | ALL        | role        |             |           |
(1 row)
```
Зарегистрируем нового пользователя и отдельной командой дадим право начинать сеанс.
```sql
=> CREATE ROLE alice;
```
```sql
CREATE ROLE
```
```sql
=> ALTER ROLE alice LOGIN;
```
```sql
ALTER ROLE
```
Теперь назначим пользователю пароль:
```sql
=> ALTER ROLE alice PASSWORD 'alice';
```
```sql
ALTER ROLE
```
Ожидаем, что в журнал аудита попали три записи, по числу выполненных команд. Выведем последние строки из журнала аудита, имеющего самую свежую дату модификации:
```sh
student$ sudo tail -10 /var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-27_234348.log
```
```sql
2026-07-27 23:43:49.533 MSK,"student","pgpro_audit",829006,INFO,1,1,"CREATE
ROLE","ROLE","alice",SUCCESS,"","CREATE ROLE
alice;",,"student",019FA551-CD9D-7F02-B259-AD66B00330DB,964,4/9,,[local]
2026-07-27 23:43:49.583 MSK,"student","pgpro_audit",829006,INFO,2,1,"ALTER
ROLE","ROLE","alice",SUCCESS,"","ALTER ROLE alice
LOGIN;",,"student",019FA551-CDCF-7465-91E4-C9A68E5391D5,965,4/10,,[local]
2026-07-27 23:43:49.728 MSK,"student","pgpro_audit",829006,INFO,3,1,"ALTER
ROLE","ROLE","alice",SUCCESS,"","ALTER ROLE alice password
<REDACTED>",,"student",019FA551-CE60-734F-A2B0-C02883666153,966,4/11,,[local]
```
Обратите внимание, что конфиденциальная информация (в данном случае — пароли) скрыта за пометкой <REDACTED>.
Текстовый CSV-файл удобен для автоматизированной обработки, но для ручного анализа может быть удобнее обращаться к журналу с помощью SQL, используя обертку сторонних данных. Установим расширение file\_fdw и определим сторонний сервер.
```sql
=> CREATE EXTENSION file_fdw;
```
```sql
CREATE EXTENSION
```
```sql
=> CREATE SERVER pg_proaudit_server FOREIGN DATA WRAPPER file_fdw;
```
```sql
CREATE SERVER
```
Создадим стороннюю таблицу:

## Page 8: Page 8 {#source-page-008}

```sql
=> CREATE FOREIGN TABLE pg_proaudit_log(
  log_time timestamp(3) with time zone,
  current_usr_name text,
  database_name text,
  session_pid text,
  error_severity text,
  session_line_num bigint,
  session_line_subcommand_num bigint,
  event_type text,
  object_type text,
  object_name text,
  status text,
  error_message text,
  query_text text,
  query_args text,
  session_usr_name text,
  uuid text,
  xid text,
  vxid text,
  rows text,
  host text
)
SERVER pg_proaudit_server
OPTIONS (filename '/var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-27_234348.log',
         format 'csv' );
```
```sql
CREATE FOREIGN TABLE
```
И прочитаем из нее записи, касающиеся изменений в данных таблицы tab1:
```sql
=> SELECT log_time, current_usr_name, event_type, status, query_text
FROM pg_proaudit_log
LIMIT 3 \gx
```
```sql
-[ RECORD 1 ]----+-------------------------------------
log_time         | 2026-07-27 23:43:49.533+03
current_usr_name | student
event_type       | CREATE ROLE
status           | SUCCESS
query_text       | CREATE ROLE alice;
-[ RECORD 2 ]----+-------------------------------------
log_time         | 2026-07-27 23:43:49.583+03
current_usr_name | student
event_type       | ALTER ROLE
status           | SUCCESS
query_text       | ALTER ROLE alice LOGIN;
-[ RECORD 3 ]----+-------------------------------------
log_time         | 2026-07-27 23:43:49.728+03
current_usr_name | student
event_type       | ALTER ROLE
status           | SUCCESS
query_text       | ALTER ROLE alice password <REDACTED>
```
Включим аудит всех событий подключения. Здесь функции pg\_proaudit\_set\_rule вместо типа объекта передаем NULL.
```sql
=> SELECT pg_proaudit_set_rule(
  db_name => current_database(),
  event_type => 'AUTHENTICATE',
  object_type => NULL,
  object_name => NULL,
  role_name => NULL
);
```
```text
 pg_proaudit_set_rule
----------------------
 t
(1 row)
```
Что теперь покажет представление pg\_proaudit\_settings?
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```text
   db_name   |  event_type  | object_type | object_name | role_name | comment
-------------+--------------+-------------+-------------+-----------+---------
 pgpro_audit | ALL          | role        |             |           |
 pgpro_audit | authenticate | ALL         |             |           |
(2 rows)
```

## Page 9: Page 9 {#source-page-009}

Начнем другой сеанс от имени Алисы:
```sh
student$ psql 'host=localhost dbname=pgpro_audit user=alice password=alice'
```
И снова проверим журнал аудита:
```sql
=> SELECT log_time, current_usr_name, event_type, status
FROM pg_proaudit_log
ORDER BY log_time DESC
LIMIT 1 \gx
```
```text
-[ RECORD 1 ]----+---------------------------
log_time         | 2026-07-27 23:43:51.497+03
current_usr_name | alice
event_type       | AUTHENTICATE
status           | SUCCESS
```
Следующая задача — включить регистрацию всех действий Алисы. Для этого укажем имя роли в соответствующем параметре функции pg\_proaudit\_set\_rule:
```sql
=> SELECT pg_proaudit_set_rule(
  db_name => current_database(),
  event_type => 'ALL',
  object_type => NULL,
  object_name => NULL,
  role_name => 'alice'
);
```
```text
 pg_proaudit_set_rule
----------------------
 t
(1 row)
```
Как это отобразилось в представлении pg\_proaudit\_settings?
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```text
   db_name   |  event_type  | object_type | object_name | role_name | comment
-------------+--------------+-------------+-------------+-----------+---------
 pgpro_audit | ALL          | role        |             |           |
 pgpro_audit | authenticate | ALL         |             |           |
 pgpro_audit | ALL          | ALL         |             | alice     |
(3 rows)
```
Алиса собирается создать таблицу в схеме public, предоставим ей такие полномочия:
```sql
=> GRANT CREATE ON SCHEMA public TO alice;
```
```text
GRANT
```
Алиса создает таблицу в своем сеансе:
```sql
=> CREATE TABLE tab1(
  id integer,
  msg text
);
```
```sql
CREATE TABLE
```
...и сведения об этом сразу появляются в журнале аудита:
```sql
=> SELECT log_time, current_usr_name, event_type, object_type, object_name, status, query_text
FROM pg_proaudit_log
ORDER BY log_time DESC
LIMIT 1 \gx
```
```sql
-[ RECORD 1 ]----+---------------------------
log_time         | 2026-07-27 23:43:51.946+03
current_usr_name | alice
event_type       | CREATE TABLE
object_type      | TABLE
object_name      | public.tab1
status           | SUCCESS
query_text       | CREATE TABLE tab1(        +
                 |   id integer,             +
                 |   msg text                +
                 | );
```
Сосредоточимся теперь на отслеживании изменений данных в таблице tab1. Отменим аудит всех действий Алисы и

## Page 10: Page 10 {#source-page-010}

добавим для таблицы регистрацию событий ALL\_MOD, которые соответствуют вставке, обновлению и удалению строк, а также опустошению таблицы.
```sql
=> SELECT pg_proaudit_remove_rule(
  db_name => current_database(),
  event_type => 'ALL',
  object_type => NULL,
  object_name => NULL,
  role_name => 'alice'
);
```
```text
 pg_proaudit_remove_rule
-------------------------
 t
(1 row)
```
```sql
=> SELECT pg_proaudit_set_rule(
  db_name => current_database(),
  event_type => 'ALL_MOD',
  object_type => 'TABLE',
  object_name => 'public.tab1',
  role_name => NULL
);
```
```text
 pg_proaudit_set_rule
----------------------
 t
(1 row)
```
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```text
   db_name   |  event_type  | object_type | object_name | role_name | comment
-------------+--------------+-------------+-------------+-----------+---------
 pgpro_audit | ALL          | role        |             |           |
 pgpro_audit | authenticate | ALL         |             |           |
 pgpro_audit | ALL_MOD      | table       | public.tab1 |           |
(3 rows)
```
В сеансе Алисы выполним вставку в таблицу tab1 и проверим журнал аудита.
```sql
=> INSERT INTO tab1 VALUES (1984, 'Big brother is watching you...');
```
```sql
INSERT 0 1
```
```sql
=> SELECT * FROM tab1;
```
```text
  id  |              msg
------+--------------------------------
 1984 | Big brother is watching you...
(1 row)
```
```sql
=> SELECT log_time, current_usr_name, event_type, status, query_text
FROM pg_proaudit_log
ORDER BY log_time DESC
LIMIT 1 \gx
```
```sql
-[ RECORD 1 ]----+------------------------------------------------------------------
log_time         | 2026-07-27 23:43:53.391+03
current_usr_name | alice
event_type       | INSERT
status           | SUCCESS
query_text       | INSERT INTO tab1 VALUES (1984, 'Big brother is watching you...');
```
Обратите внимание на отсутствие записи о выполнении SELECT.
Создадим второго пользователя:
```sql
=> CREATE USER bob PASSWORD 'bob';
```
```sql
CREATE ROLE
```
Откроем от его имени еще один сеанс, в котором Боб попытается опустошить таблицу tab1:
```sh
student$ psql 'host=localhost dbname=pgpro_audit user=bob password=bob'
```
```text
=> TRUNCATE TABLE tab1;
```
```text
ERROR:  permission denied for table tab1
```

## Page 11: Page 11 {#source-page-011}

Поскольку у Боба нет доступа к таблице, в журнале аудита увидим ошибку:
```sql
=> SELECT log_time, current_usr_name, event_type, status, query_text
FROM pg_proaudit_log
ORDER BY log_time DESC
LIMIT 3 \gx
```
```sql
-[ RECORD 1 ]----+------------------------------------
log_time         | 2026-07-27 23:43:53.802+03
current_usr_name | bob
event_type       | TRUNCATE TABLE
status           | FAILURE
query_text       | TRUNCATE TABLE tab1;
-[ RECORD 2 ]----+------------------------------------
log_time         | 2026-07-27 23:43:53.753+03
current_usr_name | bob
event_type       | AUTHENTICATE
status           | SUCCESS
query_text       |
-[ RECORD 3 ]----+------------------------------------
log_time         | 2026-07-27 23:43:53.65+03
current_usr_name | student
event_type       | CREATE ROLE
status           | SUCCESS
query_text       | CREATE USER bob password <REDACTED>
```

## Page 12: Настройки {#source-page-012}

**Настройки, сделанные функциями, необходимо сохранить в файле PGDATA/pg\\\_proaudit.conf**
  - pg\_proaudit\_save()
- Файл настроек аудита можно отредактировать напрямую, но после этого надо перечитать
  - pg\_proaudit\_reload()

### Комментарии преподавателя

Настройки аудита, произведенные вызовами функций расширения pg\_proaudit, будут потеряны после перезагрузки сервера, если не сохранить их в файле настроек pg\_proaudit.conf.

Файл pg\_proaudit.conf размещается в каталоге кластера данных (PGDATA), изменить его расположение нельзя.

Для сохранения текущих настроек в этот файл предназначена функция pg\_proaudit\_save. Аудит можно настраивать и непосредственным редактированием файла pg\_proaudit.conf, но это не так удобно, как вызов функций расширения.

Если изменить настройки непосредственно в файле pg\_proaudit.conf, их нужно прочитать и применить функцией pg\_proaudit\_reload.

При запуске сервера настройки из файла считываются автоматически.

## Page 13: Настройки {#source-page-013}

Функция pg\_proaudit\_save записывает настройки аудита в файл pg\_proaudit.conf. Если не сохранить настройки, они будут потеряны при остановке сервера.
```sql
=> SELECT pg_proaudit_save();
```
```text
 pg_proaudit_save
------------------
(1 row)
```
Заглянем в файл pg\_proaudit.conf:
```text
/var/lib/pgpro/ent-16/pg_proaudit.conf
```
```text
"pgpro_audit",ALL,role,"","",""
"pgpro_audit",authenticate,,"","",""
"pgpro_audit",ALL_MOD,table,"public.tab1","",""
```
А теперь сбросим все настройки аудита:
```sql
=> SELECT pg_proaudit_reset();
```
```text
 pg_proaudit_reset
-------------------
(1 row)
```
Никакие настройки не действуют:
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```text
 db_name | event_type | object_type | object_name | role_name | comment
---------+------------+-------------+-------------+-----------+---------
(0 rows)
```
Можно (хотя это не очень удобно) изменять файл pg\_proaudit.conf любыми средствами редактирования текста. Например, удалим строку конфигурации аудита событий подключения:
```text
/var/lib/pgpro/ent-16/pg_proaudit.conf
```
```text
"pgpro_audit",ALL,role,"","",""
"pgpro_audit",ALL_MOD,table,"public.tab1","",""
```
А теперь считаем настройки из файла:
```sql
=> SELECT pg_proaudit_reload();
```
```text
 pg_proaudit_reload
--------------------
(1 row)
```
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```text
   db_name   | event_type | object_type | object_name | role_name | comment
-------------+------------+-------------+-------------+-----------+---------
 pgpro_audit | ALL        | role        |             |           |
 pgpro_audit | ALL_MOD    | table       | public.tab1 |           |
(2 rows)
```
Настройки аудита восстановлены, за исключением регистрации подключений.

## Page 14: Запись событий аудита {#source-page-014}

![Source slide page 14: Запись событий аудита](images/page-014.png){#source-figure-014 caption="Source slide page 14: Запись событий аудита"}


### Комментарии преподавателя

Параметр расширения pg\_proaudit.log\_destination определяет способ регистрации (один или несколько) событий безопасности:

● csvlog — записывать события в файл CSV.

Параметр pg\_proaudit.log\_filename задает шаблон имен файлов CSV, а параметр pg\_proaudit.log\_rotation\_size — максимальный размер файла в килобайтах. Другой способ настройки ротации файлов журнала — по времени — устанавливается параметром pg\_proaudit.log\_rotation\_age.

● ceflog — передавать события в SIEM-систему в формате CEF.

Поддержка открытого формата событий CEF (Common Event Format) позволяет отправлять собранные данные различным системам управления информацией и событиями безопасности (SIEM, Security Information and Event Management).

● syslog и cefsyslog — передавать события в службу syslog в формате syslog или CEF.

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

Полный список параметров конфигурации записи событий аудита в журнал содержится в документации: <https://postgrespro.ru/docs/enterprise/16/pg-proaudit#PG-PROAUDIT-SECU> RITY-EVENT-LOG-CONFIGURATION-PARAMETERS

## Page 15: Настройка записи событий аудита {#source-page-015}

Посмотрим значения параметров регистрации событий по умолчанию:
```sql
=> SELECT name, setting
FROM pg_settings
WHERE name LIKE 'pg_proaudit.log_%';
```
```text
                 name                 |            setting
--------------------------------------+--------------------------------
 pg_proaudit.log_catalog_access       | off
 pg_proaudit.log_command_text         | on
 pg_proaudit.log_destination          | csvlog
 pg_proaudit.log_directory            | pg_proaudit
 pg_proaudit.log_file_mode            | 0600
 pg_proaudit.log_filename             | postgresql-%Y-%m-%d_%H%M%S.log
 pg_proaudit.log_rotation_age         | 1440
 pg_proaudit.log_rotation_size        | 10240
 pg_proaudit.log_rows                 | off
 pg_proaudit.log_truncate_on_rotation | off
(10 rows)
```
Добавим запись в журнал аудита количества строк, затронутых SQL-командой:
```sql
=> ALTER SYSTEM SET pg_proaudit.log_rows = on;
```
```sql
ALTER SYSTEM
```
Перечитаем конфигурацию.
```sql
=> SELECT pg_reload_conf();
```
```text
 pg_reload_conf
----------------
 t
(1 row)
```
Удалим строки в таблице tab1 в сеансе Алисы:
```sql
=> DELETE FROM tab1;
```
```sql
DELETE 1
```
Теперь в конце записи о событии появилось еще одно поле. Сравните последнюю запись с записью вставки: удалена одна строка.
```sql
=> SELECT log_time, current_usr_name, event_type, status, query_text, rows
FROM pg_proaudit_log
WHERE event_type IN ('INSERT', 'DELETE') \gx
```
```sql
-[ RECORD 1 ]----+------------------------------------------------------------------
log_time         | 2026-07-27 23:43:53.391+03
current_usr_name | alice
event_type       | INSERT
status           | SUCCESS
query_text       | INSERT INTO tab1 VALUES (1984, 'Big brother is watching you...');
rows             |
-[ RECORD 2 ]----+------------------------------------------------------------------
log_time         | 2026-07-27 23:43:54.98+03
current_usr_name | alice
event_type       | DELETE
status           | SUCCESS
query_text       | DELETE FROM tab1;
rows             | 1
```

## Page 16: Итоги {#source-page-016}

**Расширение pg\\\_proaudit регистрирует события аудита независимо от обычного журнала сообщений**
- Аудиту подлежат подключения и отключения, операции с объектами баз данных и действия ролей
- Журнал аудита может сохраняться как в формате CSV, так и передаваться службам SIEM или syslog

## Page 17: Практика {#source-page-017}

1. Настройте аудит для записи в CSV и syslog одновременно. Включите аудит регистрации ролей и создания таблиц. В следующих заданиях сравните сообщения, попадающие в CVS и в syslog. 2. Зарегистрируйте новую роль observed1 и настройте аудит подключений и отключений для этой роли. 3. Создайте таблицу tab1 так, чтобы роль observed1 могла выполнять команды DML с этой таблицей; владельцем таблицы должен быть другой пользователь. 4. Настройте регистрацию команд DML, выполненных любым пользователем, для таблицы tab1.

### Комментарии преподавателя

1. После подключения аудита используйте команду

```sql
ALTER SYSTEM SET pg_proaudit.log_destination = 'csvlog,syslog';
```

для записи сообщений аудита и в файл, и в syslog.

Для настройки аудита используйте функцию pg\_proaudit\_set\_rule.

В заданиях с 2 по 4 просматривать сообщения аудита в файле CSV нужно в каталоге /var/lib/pgpro/ent-16/pg\_proaudit.

Идентификатор, заранее записанный в параметр сервера syslog\_ident, поможет отфильтровать необходимые строки журнала сообщений syslog, который находится в файле /var/log/syslog. Воспользуйтесь следующей командой:

```text
sudo grep -a идентификатор /var/log/syslog | tail
```

## Page 18: 1. Настройка аудита {#source-page-018}

Создадим базу данных:
```sql
=> CREATE DATABASE pgpro_audit;
```
```sql
CREATE DATABASE
```
Загрузим библиотеку:
```sql
=> ALTER SYSTEM SET shared_preload_libraries = 'pg_proaudit';
```
```sql
ALTER SYSTEM
```
Подключение библиотеки требует перезагрузки СУБД.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
```sh
student$ psql -d pgpro_audit
```
Создадим расширение pg\_proaudit:
```sql
=> CREATE EXTENSION pg_proaudit;
```
```sql
CREATE EXTENSION
```
Настроим запись сообщений аудита одновременно в CSV-файл и syslog:
```sql
=> ALTER SYSTEM SET pg_proaudit.log_destination = 'csvlog,syslog';
```
```sql
ALTER SYSTEM
```
Установим имя программы — идентификатор в записях syslog:
```sql
=> ALTER SYSTEM SET syslog_ident = 'MY_audit';
```
```sql
ALTER SYSTEM
```
```sql
=> SELECT pg_reload_conf();
```
```text
 pg_reload_conf
----------------
 t
(1 row)
```
Наличие идентификатора облегчит поиск записей аудита в журнале сообщений.
Настроим аудит регистрации пользователей и создания новых таблиц.
Аудит всех событий, связанных с управлением ролями:
```sql
=> SELECT pg_proaudit_set_rule(current_database(), 'ALL', 'ROLE', NULL, NULL);
```
```text
 pg_proaudit_set_rule
----------------------
 t
(1 row)
```
Аудит событий создания таблиц:
```sql
=> SELECT pg_proaudit_set_rule(current_database(), 'CREATE TABLE', 'TABLE', NULL, NULL);
```
```text
 pg_proaudit_set_rule
----------------------
 t
(1 row)
```
Получившиеся настройки аудита:
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```sql
   db_name   |  event_type  | object_type | object_name | role_name | comment
-------------+--------------+-------------+-------------+-----------+---------
 pgpro_audit | ALL          | role        |             |           |
 pgpro_audit | create table | table       |             |           |
(2 rows)
```

## Page 19: 2. Регистрация событий создания и управления пользователями {#source-page-019}

Регистрация нового пользователя:
```sql
=> CREATE ROLE observed1 LOGIN PASSWORD 'obs123';
```
```sql
CREATE ROLE
```
Второй сеанс от имени observed1:
```sh
student$ psql 'dbname=pgpro_audit user=observed1 password=obs123'
```
Командой ls -ltr $PGDATA/pg\_proaudit можно получить список файлов аудита, отсортированный по времени модификации:
```sh
student$ sudo ls -ltr /var/lib/pgpro/ent-16/pg_proaudit
```
```text
total 4
-rw------- 1 postgres postgres 228 июл 28 00:16 postgresql-2026-07-28_001605.log
```
Проверяем CSV-файл аудита, который был изменен последним:
```sh
student$ sudo tail -1 /var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-28_001605.log
```
```sql
2026-07-28 00:16:06.494 MSK,"student","pgpro_audit",887175,INFO,1,1,"CREATE
ROLE","ROLE","observed1",SUCCESS,"","CREATE ROLE observed1 LOGIN password
<REDACTED>",,"student",019FA56F-5BDE-7215-80D8-E869B0DBA039,964,4/13,,[local]
```
Получим последние две записи в журнале /var/log/syslog по установленному идентификатору MY\_audit:
```sh
student$ sudo grep -a MY_audit /var/log/syslog | tail -2
```
```sql
2026-07-28T00:16:06.494916+03:00 course MY_audit[887175]: AUDIT [1-1] INFO: USER:
student, DB: pgpro_audit, PID: 887175, EVENT TYPE: CREATE ROLE, OBJECT TYPE: ROLE, OBJECT
NAME: observed1, SUCCESS, SESSION USER: student, UUID:
019FA56F-5BDE-7215-80D8-E869B0DBA039, XID: 964, VXID: 4/13, SRC: [local]
2026-07-28T00:16:06.495262+03:00 course MY_audit[887175]: AUDIT [1-1] STATEMENT: CREATE
ROLE observed1 LOGIN password <REDACTED>
```
### 3. Создание таблицы и предоставление прав на нее
Суперпользователь student создает таблицу и выдает на нее права observed1.
```sql
=> CREATE TABLE tab1(n integer, txt text);
```
```sql
CREATE TABLE
```
```sql
=> GRANT SELECT,INSERT,UPDATE,DELETE ON tab1 TO observed1;
```
```text
GRANT
```
Проверяем CSV-файл аудита: должно быть видно CREATE TABLE, но не GRANT.
```sh
student$ sudo tail -1 /var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-28_001605.log
```
```sql
2026-07-28 00:16:07.975 MSK,"student","pgpro_audit",887175,INFO,2,1,"CREATE
TABLE","TABLE","public.tab1",SUCCESS,"","CREATE TABLE tab1(n integer, txt
text);",,"student",019FA56F-61A7-716F-ABB1-ABA3E461C9D9,965,4/14,,[local]
```
Поиск записей в журнале /var/log/syslog по установленному идентификатору MY\_audit:
```sh
student$ sudo grep -a MY_audit /var/log/syslog | tail -2
```
```sql
2026-07-28T00:16:07.975974+03:00 course MY_audit[887175]: AUDIT [2-1] INFO: USER:
student, DB: pgpro_audit, PID: 887175, EVENT TYPE: CREATE TABLE, OBJECT TYPE: TABLE,
OBJECT NAME: public.tab1, SUCCESS, SESSION USER: student, UUID:
019FA56F-61A7-716F-ABB1-ABA3E461C9D9, XID: 965, VXID: 4/14, SRC: [local]
2026-07-28T00:16:07.976100+03:00 course MY_audit[887175]: AUDIT [2-1] STATEMENT: CREATE
TABLE tab1(n integer, txt text);
```
### 4. Регистрация команд DML с таблицей tab1
Установка регистрации команд DML для tab1.
```sql
=> SELECT pg_proaudit_set_rule(current_database(), 'ALL_DML', 'TABLE', 'public.tab1', NULL);
```
```text
 pg_proaudit_set_rule
----------------------
 t
(1 row)
```

## Page 20: Page 20 {#source-page-020}

Получившиеся настройки аудита:
```sql
=> SELECT * FROM pg_proaudit_settings;
```
```sql
   db_name   |  event_type  | object_type | object_name | role_name | comment
-------------+--------------+-------------+-------------+-----------+---------
 pgpro_audit | ALL          | role        |             |           |
 pgpro_audit | create table | table       |             |           |
 pgpro_audit | ALL_DML      | table       | public.tab1 |           |
(3 rows)
```
Выполним несколько команд в сеансе observed1, сразу проверяя CSV-файл и журнал событий:
```sql
=> INSERT INTO tab1 VALUES (1, 'Один');
```
```sql
INSERT 0 1
```
```sh
student$ sudo tail -1 /var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-28_001605.log
```
```sql
2026-07-28 00:16:09.474
MSK,"observed1","pgpro_audit",887533,INFO,1,1,"INSERT","TABLE","public.tab1",SUCCESS,"","I
NSERT INTO tab1 VALUES (1,
'Один');",,"observed1",019FA56F-6782-7868-B88C-EEF51B601E9C,,5/4,,[local]
```
```sh
student$ sudo grep -a MY_audit /var/log/syslog | tail -2
```
```sql
2026-07-28T00:16:09.475221+03:00 course MY_audit[887533]: AUDIT [1-1] INFO: USER:
observed1, DB: pgpro_audit, PID: 887533, EVENT TYPE: INSERT, OBJECT TYPE: TABLE, OBJECT
NAME: public.tab1, SUCCESS, SESSION USER: observed1, UUID:
019FA56F-6782-7868-B88C-EEF51B601E9C, XID: 0, VXID: 5/4, SRC: [local]
2026-07-28T00:16:09.475452+03:00 course MY_audit[887533]: AUDIT [1-1] STATEMENT: INSERT
INTO tab1 VALUES (1, 'Один');
```
```sql
=> SELECT * FROM tab1;
```
```text
 n | txt
---+------
 1 | Один
(1 row)
```
```sh
student$ sudo tail -1 /var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-28_001605.log
```
```sql
2026-07-28 00:16:10.719
MSK,"observed1","pgpro_audit",887533,INFO,2,1,"SELECT","TABLE","public.tab1",SUCCESS,"","S
ELECT * FROM tab1;",,"observed1",019FA56F-6C5F-7365-AE2B-B6716031846C,,5/5,,[local]
```
```sh
student$ sudo grep -a MY_audit /var/log/syslog | tail -2
```
```sql
2026-07-28T00:16:10.719912+03:00 course MY_audit[887533]: AUDIT [2-1] INFO: USER:
observed1, DB: pgpro_audit, PID: 887533, EVENT TYPE: SELECT, OBJECT TYPE: TABLE, OBJECT
NAME: public.tab1, SUCCESS, SESSION USER: observed1, UUID:
019FA56F-6C5F-7365-AE2B-B6716031846C, XID: 0, VXID: 5/5, SRC: [local]
2026-07-28T00:16:10.719996+03:00 course MY_audit[887533]: AUDIT [2-1] STATEMENT: SELECT *
FROM tab1;
```
```sql
=> UPDATE tab1 SET n=2;
```
```sql
UPDATE 1
```
```sh
student$ sudo tail -1 /var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-28_001605.log
```
```sql
2026-07-28 00:16:11.970
MSK,"observed1","pgpro_audit",887533,INFO,3,1,"UPDATE","TABLE","public.tab1",SUCCESS,"","U
PDATE tab1 SET n=2;",,"observed1",019FA56F-7142-743C-9EF1-92E5AA3AED8A,,5/6,,[local]
```
```sh
student$ sudo grep -a MY_audit /var/log/syslog | tail -2
```
```sql
2026-07-28T00:16:11.971276+03:00 course MY_audit[887533]: AUDIT [3-1] INFO: USER:
observed1, DB: pgpro_audit, PID: 887533, EVENT TYPE: UPDATE, OBJECT TYPE: TABLE, OBJECT
NAME: public.tab1, SUCCESS, SESSION USER: observed1, UUID:
019FA56F-7142-743C-9EF1-92E5AA3AED8A, XID: 0, VXID: 5/6, SRC: [local]
2026-07-28T00:16:11.971413+03:00 course MY_audit[887533]: AUDIT [3-1] STATEMENT: UPDATE
tab1 SET n=2;
```
```sql
=> DELETE FROM tab1;
```
```sql
DELETE 1
```
```sh
student$ sudo tail -1 /var/lib/pgpro/ent-16/pg_proaudit/postgresql-2026-07-28_001605.log
```
```text
2026-07-28 00:16:13.201
```

## Page 21: Page 21 {#source-page-021}

```sql
MSK,"observed1","pgpro_audit",887533,INFO,4,1,"DELETE","TABLE","public.tab1",SUCCESS,"","D
ELETE FROM tab1;",,"observed1",019FA56F-7611-7DC3-BBA7-6D315A10132C,,5/7,,[local]
```
```sh
student$ sudo grep -a MY_audit /var/log/syslog | tail -2
```
```sql
2026-07-28T00:16:13.202695+03:00 course MY_audit[887533]: AUDIT [4-1] INFO: USER:
observed1, DB: pgpro_audit, PID: 887533, EVENT TYPE: DELETE, OBJECT TYPE: TABLE, OBJECT
NAME: public.tab1, SUCCESS, SESSION USER: observed1, UUID:
019FA56F-7611-7DC3-BBA7-6D315A10132C, XID: 0, VXID: 5/7, SRC: [local]
2026-07-28T00:16:13.203005+03:00 course MY_audit[887533]: AUDIT [4-1] STATEMENT: DELETE
FROM tab1;
```
### Уборка
Удалим созданную базу данных и роль, уберем каталог журналов аудита и сбросим настройки параметров конфигурации.
```sql
=> \c student
```
```text
You are now connected to database "student" as user "student".
```
```sql
=> DROP DATABASE pgpro_audit WITH (FORCE);
```
```sql
DROP DATABASE
```
```sql
=> DROP ROLE observed1;
```
```sql
DROP ROLE
```
```sh
student$ sudo rm -rf /var/lib/pgpro/ent-16/pg_proaudit
```
```sql
=> ALTER SYSTEM RESET ALL;
```
```sql
ALTER SYSTEM
```
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
