Перейти к основному содержимому

Задание 1: Защита системного каталога pg_proc

В этом задании мы изучим устройство защиты целостности, поставим системный каталог pg_proc под защиту и проверим целостность данных.

Примечание

Для удобства рекомендуем открыть на сервере три отдельных терминала, распределив задачи следующим образом:

  • Терминал 1: для мониторинга логов.
  • Терминал 2: для работы от имени системного пользователя postgres.
  • Терминал 3: для действий от имени пользователя student.

Инфраструктура подсистемы​

В сеансе postgres проверим наличие и содержимое каталога pg_integrity:

[student@srv1 ~]$ sudo -iu postgres
===============================================================
You are connected to Pangolin Cluster (Pobeda)
- Hostname : srv1
- IP Address : <IP-Address1>
---------------------------------------------------------------
- node ( master ) : <IP-Address1>
- node ( replica ) : <IP-Address2>
- arbiter : <IP-Address3>
- Manager version : 2.1.13
- Pangolin version : 6.7.0
===============================================================
[postgres@srv1 ~]$ cd /pgdata/06/data/
[postgres@srv1 data]$ ls -l pg_integrity/
total 8
-rw------- 1 postgres postgres 26 Feb 1 17:35 integrity_files.json
-rw------- 1 postgres postgres 26 Feb 1 17:35 integrity_relations.json

Сохраним каталог pg_integrity вместе с его содержимым в домашнем каталоге пользователя postgres:

[postgres@srv1 data]$ cp -av pg_integrity/ ~postgres/
'pg_integrity/' -> '/var/lib/postgres/pg_integrity'
'pg_integrity/integrity_files.json' -> '/var/lib/postgres/pg_integrity/integrity_files.json'
'pg_integrity/integrity_relations.json' -> '/var/lib/postgres/pg_integrity/integrity_relations.json'

Посмотрим, что находится в этих файлах:

[postgres@srv1 data]$ cat pg_integrity/integrity_files.json
{
"integrity" : null
}
[postgres@srv1 data]$ cat pg_integrity/integrity_relations.json
{
"integrity" : null
}

Постановка pg_proc под защиту​

Системный каталог pg_proc содержит метаданные о функциях и процедурах.

Внимание!

Если pg_proc поставлен под защиту, то любое изменение, связанное с любой функцией и процедурой приведет:

  • к разрыву всех текущих сессий;
  • к блокировке доступа всех пользователей, кроме администратора СУБД.

Информация о нарушении целостности системного каталога pg_proc также будет записана в журнал сообщений.

Для проверки создадим в сеансе student функцию:

[postgres@srv1 ~]$ exit
[student@srv1 ~]$ psql -p 5433 -h srv1
psql (15.5)
Type "help" for help.
student=> CREATE FUNCTION vcheras() RETURNS timestamp AS
$$
SELECT now() - '1 day'::interval;
$$ LANGUAGE SQL;
Выдает ошибку. Что делать?

Если вышла ошибка вида:

ERROR: no schema has been selected to create in

В файле конфигурации /etc/pangolin-manager/postgres.yml необходимо исправить параметр:

[student@srv1 ~]$ sudo vi /etc/pangolin-manager/postgres.yml
search_path: public,ext
[student@srv1 ~]$ sudo systemctl restart pangolin-manager

Затем повторите создание функции.

CREATE FUNCTION
student=> \df vcheras
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+---------+-----------------------------+---------------------+------
public | vcheras | timestamp without time zone | | func
(1 row)
student=> SELECT now(); SELECT vcheras();
now
-------------------------------
2026-09-14 13:44:23.730486+03
(1 row)

vcheras
----------------------------
2026-09-13 13:44:23.730816
(1 row)
student=> SELECT now(), vcheras();
now | vcheras
-------------------------------+----------------------------
2026-09-14 13:44:41.744621+03 | 2026-09-13 13:44:41.744621
(1 row)

Посмотрим, как выглядит информация о функции vcheras() в системном каталоге pg_proc:

student=> SELECT * FROM pg_proc WHERE proname = 'vcheras' \gx
-[ RECORD 1 ]---+----------------------------------
oid | 16390
proname | vcheras
pronamespace | 2200
proowner | 16388
prolang | 14
procost | 100
prorows | 0
provariadic | 0
prosupport | -
prokind | f
prosecdef | f
proleakproof | f
proisstrict | f
proretset | f
provolatile | v
proparallel | u
pronargs | 0
pronargdefaults | 0
prorettype | 1114
proargtypes |
proallargtypes |
proargmodes |
proargnames |
proargdefaults |
protrftypes |
prosrc | +
| SELECT now() - '1 day'::interval;+
|
probin |
prosqlbody |
proconfig |
proacl |

Столбец prosecdef содержит false.

Включение контроля целостности pg_proc​

Откроем в эмуляторе терминала еще одну сессию пользователя ОС postgres, в которой запустим мониторинг записей в журнале сообщений:

[postgres@srv1 data]$ tail -f `cut -d' ' -f2 $PGDATA/current_logfiles` -n 20
...
2026-09-23 12:25:35 MSK [177743]: [4-1] app=psql,user=postgres,db=postgres,client=<IP-Address1>,type=client backend LOG: AUDIT: SESSION, CONNECTION, OPEN,database = postgres,user = postgres
2026-09-23 12:26:47 MSK [177743]: [5-1] app=psql,user=postgres,db=postgres,client=<IP-Address1>,type=client backend ERROR: function vcheras() does not exist
2026-09-23 12:26:47 MSK [177743]: [6-1] app=psql,user=postgres,db=postgres,client=<IP-Address1>,type=client backend STATEMENT: ALTER FUNCTION vcheras() SECURITY DEFINER;
2026-09-23 12:27:38 MSK [177759]: [1-1] app=[unknown],user=[unknown],db=[unknown],client=<IP-Address1>,type=not initialized LOG: connection received: host=<IP-Address1> port=32904
...

В сеансе суперпользователя установим контроль целостности pg_proc:

postgres=# SELECT pg_integrity_add_catalog('student','pg_catalog.pg_proc');
pg_integrity_add_catalog
--------------------------
t
(1 row)

В результате появится запись в журнале сообщений:

2026-09-23 12:29:59 MSK [177778]: [1-1] app=object of calculation sha256,user=postgres,db=student,client=[bgworker],type=object of calculation sha256 LOG: Relation hash successfully added "student" "pg_catalog.pg_proc"

Проверим, что записалось в файл pg_integrity/integrity_relations.json:

postgres=# \! cat $PGDATA/pg_integrity/integrity_relations.json
{
"integrity" : [
{
"db" : "student",
"hash" : "2b25e48f14ea486954f8adc360d9ece913641ee22297d7147053c368535a30bd",
"name" : "pg_catalog.pg_proc",
"type" : "relation"
}
]
}

В сеансе student изменим параметр SECURITY функции vcheras():

student=> ALTER FUNCTION vcheras() SECURITY DEFINER;
ALTER FUNCTION
student=> SELECT proname, prosecdef FROM pg_proc WHERE proname = 'vcheras';
proname | prosecdef
---------+-----------
vcheras | t
(1 row)

Сеанс пользователя пока не прерван. Убедимся в этом:

student=> SELECT pg_backend_pid();
pg_backend_pid
----------------
177759
(1 row)

Проверка целостности​

Если выполнить проверку целостности, то все сеансы будут заблокированы.

В сеансе суперпользователя:

postgres=# SELECT pg_integrity_check();
pg_integrity_check
--------------------
f
(1 row)

Проверим, существует ли сеанс student:

student=> SELECT pg_backend_pid();
FATAL: terminating connection due to administrator command
SSL connection has been closed unexpectedly
The connection to the server was lost. Attempting reset: Failed.
The connection to the server was lost. Attempting reset: Failed.
!?>

Вот, что записалось в журнал сообщений:

2026-09-23 12:29:59 MSK [177778]: [1-1] app=integrity check worker,user=,db=,client=[bgworker],type=integrity check worker WARNING: The hash is different for the catalog object: pg_catalog.pg_proc
2026-09-23 12:29:59 MSK [177778]: [2-1] app=integrity check worker,user=,db=,client=[bgworker],type=integrity check worker WARNING: Disconnect proc pid 177759 roleId 16390 rolename student
2026-09-23 12:29:59 MSK [177759]: [7-1] app=psql,user=student,db=student,client=<IP-Address1>,type=client backend FATAL: terminating connection due to administrator command

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

postgres=# SELECT pg_integrity_add_catalog('student','pg_catalog.pg_proc');
pg_integrity_add_catalog
--------------------------
t
(1 row)
postgres=# SELECT pg_integrity_check();
pg_integrity_check
--------------------
t
(1 row)

Отслеживаемая контрольная сумма изменилась:

postgres=# \! cat $PGDATA/pg_integrity/integrity_relations.json
{
"integrity" : [
{
"db" : "student",
"hash" : "fb4c67a66029f1e51de6aebc46ce59b83a338025e65bf72e69f9c89d393fe25b",
"name" : "pg_catalog.pg_proc",
"type" : "relation"
}
]
}

Теперь снова можно открыть сеанс роли student:

[student@srv1 ~]$ psql -p 5433 -h srv1
psql (15.5)
Type "help" for help.
student=> SELECT pg_backend_pid();
pg_backend_pid
----------------
177981
(1 row)

Подведем итоги​

Вопрос 1

Вопрос 1: Какой процесс управляет проверкой целостности объектов в Pangolin?

Вопрос 2

Вопрос 2: Посмотрите на команду:

postgres=# SELECT pg_integrity_add_catalog('student','pg_catalog.pg_proc');
 pg_integrity_add_catalog 
--------------------------
 t
(1 row)

Выберите все верные ответы: