Отключение маскирования полей usename и client_addr в Performance Insights
Описание
Проблемы анализа инцидентов
При сохранении данных активности сессий для исключения несанкционированного доступа к этим данным в процессе выполнения функций Performance Insights происходит маскирование следующих полей представлений pg_stat_activity и pg_locks (при включенном параметре performance_insights.masking):
- параметры запросов;
client_addr- адрес и/или имя хоста, с которого была открыта сессия;usename- имя пользователя, открывшего сессию.
Маскирование внутри функциональности Performance Insights происходит независимо от общего маскирования. Но при заданном маскировании запросов (masking_mode = full) маскирование запросов в Performance Insight будет выполняться независимо от значения параметра performance_insights.masking. Это связано с тем, что Performance Insights пользуется текстами запросов, помещенных в представление pg_stat_activity, и при включенном маскировании тексты запросов в представлении находятся уже в замаскированном виде. Подробнее про общее маскирование описано в разделе «Маскирование запросов».
Так как цель функциональности Performance Insights предоставить администратору СУБД, администратору АС, а также разработчику приложений возможность анализа истории активности СУБД Pangolin, маскирование полей usename и client_addr в выводе функций Performance Insights существенно затрудняет разбор инцидентов, так как делает вывод функций pg_stat_get_activity_history, pg_stat_get_activity_history_last и pg_stat_get_activity_and_lock_status_history неинформативным.
Например:
-
Запрос на вывод снимка
pg_stat_activity(запрос выполняется от суперпользователя):SELECT datname, usename, client_addr, query, state FROM pg_stat_get_activity_history(NULL, NULL, NULL) ORDER BY query_start DESC LIMIT 6;Пример вывода команды:
datname | usename | client_addr | query | state
----------+---------+-------------+-----------------------------------------------------+--------------------
test_db | *** | *** | BEGIN; | idle in transaction
test_db | *** | *** | INSERT INTO test_schema.test_table VALUES(***, ***);| idle in transaction
test_db | *** | *** | INSERT INTO test_schema.test_table VALUES(***, ***);| idle in transaction
test_db | *** | *** | BEGIN; | idle in transaction
test_db | *** | *** | DELETE FROM test_schema.test_table WHERE id=***; | idle in transaction
test_db | *** | *** | DELETE FROM test_schema.test_table WHERE id=***; | idle in transaction
(6 rows)Из данного вывода невозможно установить от имени какого пользователя производятся действия по изменению таблицы
test_schema.test_tableв базе данныхtest_db, а также IP-адрес хоста, с которого пользователь выполняет данные действия. -
Запрос на вывод снимка
pg_stat_activityиpg_locksс отметками времени выборки (запрос выполняется от суперпользователя):SELECT datname, usename, client_addr, query, state, locktype FROM pg_stat_get_activity_and_lock_status_history(NULL, NULL, NULL) ORDER BY query_start DESC LIMIT 4;Пример вывода команды:
datname | usename | client_addr | query | locktype | state
----------+---------+-------------+------------------------------------------------------------------+---------------+---------------------
test_db | *** | *** | BEGIN; | virtualxid | idle in transaction
test_db | *** | *** | DELETE FROM test_schema.test_table WHERE id BETWEEN *** AND ***; | transactionid | idle in transaction
test_db | *** | *** | DELETE FROM test_schema.test_table WHERE id BETWEEN *** AND ***; | virtualxid | idle in transaction
test_db | *** | *** | DELETE FROM test_schema.test_table WHERE id BETWEEN *** AND ***; | virtualxid | idle in transaction
(4 rows)Из данного вывода также невозможно установить ни имени пользователя, выполняющего действия по изменению таблицы
test_schema.test_tableв базе данныхtest_db, ни IP-адрес хоста, с которого данные действия выполняются.
Настройка
Для обеспечения удобства расследования возможных инцидентов разработано дополнительное значение partial параметра performance_insights.masking для отключения маскирования полей usename и client_addr в выводе работы функций. Маскирование других полей будет производиться без изменения.
Дополнительно изменено значение по умолчанию параметра performance_insights.masking на off после установки СУБД вручную (для уменьшения нагрузки на систему), и на partial, после установки при помощи скриптов автоматизации.
Также для удобства в HTML-отчете выводится имя пользователя в поле User в незамаскированном виде при значении параметра performance_insights.masking = 'partial'/'off'. Значение oid в поле UserOid выводится всегда не зависимо от параметра performance_insights.masking.
Управление
При значении параметра performance_insights.masking = on маскирование остается без изменений.
-
Пример вывода функции
pg_stat_get_activity_historyпри значении параметраperformance_insights.masking = 'partial':SELECT datname, usename, client_addr, query, state FROM pg_stat_get_activity_history(NULL, NULL, NULL) ORDER BY query_start DESC LIMIT 5;Вывод:
datname | usename | client_addr | query | state
--------+-----------+-------------+------------------------------------------------------ +------------------
test_db | test_user | 0.0.0.0 | BEGIN; | idle in transaction
test_db | test_user | 0.0.0.0 | INSERT INTO test_schema.test_table VALUES(***, ***); | idle in transaction
test_db | test_user | 0.0.0.0 | INSERT INTO test_schema.test_table VALUES(***, ***); | idle in transaction
test_db | test_user | 0.0.0.0 | BEGIN; | idle in transaction
test_db | test_user | 0.0.0.0 | DELETE FROM test_schema.test_table WHERE id=***; | idle in transaction
(5 rows)Поля
usenameиclient_addrне замаскированы в выводе, параметры запросов замаскированы. -
Пример вывода функции
pg_stat_get_activity_history_lastпри значении параметраperformance_insights.masking = 'partial':SELECT datname, usename, client_addr, query, state FROM pg_stat_get_activity_history_last(NULL);Вывод:
datname | usename | client_addr | query | state
--------+-----------+-------------+-------------------------------------------------- +--------------------
test_db | test_user | 0.0.0.0 | DELETE FROM test_schema.test_table WHERE id=***; | idle in transaction
(1 row)Поля
usenameиclient_addrне замаскированы в выводе, параметры запросов замаскированы. -
Пример вывода функции
pg_stat_get_activity_and_lock_status_historyпри значении параметраperformance_insights.masking = 'partial':SELECT datname, usename, client_addr, query, state, locktype FROM pg_stat_get_activity_and_lock_status_history(NULL, NULL, NULL) ORDER BY query_start DESC LIMIT 4;Вывод:
datname | usename | client_addr | query | locktype | state
----------+-------------+-------------+------------------------------------------------------------------ +---------------+---------------------
test_db | test_user | 0.0.0.0 | BEGIN; | virtualxid | idle in transaction
test_db | test_user | 0.0.0.0 | DELETE FROM test_schema.test_table WHERE id BETWEEN *** AND ***; | transactionid | idle in transaction
test_db | test_user | 0.0.0.0 | DELETE FROM test_schema.test_table WHERE id BETWEEN *** AND ***; | virtualxid | idle in transaction
test_db | test_user | 0.0.0.0 | DELETE FROM test_schema.test_table WHERE id BETWEEN *** AND ***; | virtualxid | idle in transaction
(4 rows)Поля
usenameиclient_addrне замаскированы в выводе, параметры запросов замаскированы.
Сценарии использования
Маскирование параметров запросов в выводе функций при значении параметра performance_insights.masking = partial
-
От имени суперпользователя проверьте значение параметра
performance_insights.masking:SHOW performance_insights.masking;Параметр имеет значение
partialпо умолчанию:performance_insights.masking
------------------------------
partial
(1 row) -
От имени тестового пользователя
perfins_msk_userв тестовой базе данныхperfins_msk_dbначните транзакцию и вставьте в тестовую таблицу новую запись:BEGIN;
INSERT INTO perfins_msk_schema.perfins_msk_table VALUES(1, 'test data 1');Транзакция начинает выполняться:
BEGIN
INSERT 0 1 -
От имени суперпользователя выведите последнюю запись с данными об активности сессий:
SELECT sample_time, datname, pid, usesysid, usename, client_addr, query
FROM pg_stat_get_activity_history(NULL, NULL, NULL)
WHERE datname = 'perfins_msk_db' AND state = 'idle in transaction'
ORDER BY query_start DESC LIMIT 1 \gxПоля
usenameиclient_addrв выводе не замаскированы, параметры запроса в полеqueryзамаскированы. Пример вывода:-[ RECORD 1 ]-------------------------------------------------------------------
sample_time | 2025-08-07 14:01:01.400833+03
datname | perfins_msk_db
pid | 19656
usesysid | 26458
usename | perfins_msk_user
client_addr | <IP-Address>
query | INSERT INTO perfins_msk_schema.perfins_msk_table VALUES(***, ***); -
От имени суперпользователя выведите последнюю запись с данными об активности сессий за последний период обновления истории:
SELECT sample_time, datname, pid, usesysid, usename, client_addr, query
FROM pg_stat_get_activity_history_last(NULL) \gxПоля
usenameиclient_addrв выводе не замаскированы, параметры запроса в полеqueryзамаскированы. Пример вывода:sample_time | 2025-08-07 14:01:47.900393+03
datname | perfins_msk_db
pid | 19656
usesysid | 26458
usename | perfins_msk_user
client_addr | <IP-Address>
query | INSERT INTO perfins_msk_schema.perfins_msk_table VALUES(***, ***); -
От имени тестового пользователя завершите транзакцию:
COMMIT;Транзакция успешно завершена:
COMMIT -
От имени суперпользователя очистите историю:
SELECT pg_stat_activity_history_reset();История очищена:
pg_stat_activity_history_reset
--------------------------------
(1 row) -
От имени тестового пользователя заблокируйте тестовую таблицу и удалите из нее несколько записей:
BEGIN;
LOCK TABLE perfins_msk_schema.perfins_msk_table IN ACCESS EXCLUSIVE MODE;
DELETE FROM perfins_msk_schema.perfins_msk_table WHERE ID%3=0;Транзакция начинает выполняться:
BEGIN
LOCK TABLE
DELETE 3 -
От имени суперпользователя выведите последнюю запись с данными об активности текущих сессий вместе с данными блокировок и затраченными ресурсами:
SELECT sample_time, datname, pid, usesysid, usename, client_addr, query, locktype, mode
FROM pg_stat_get_activity_and_lock_status_history(NULL, NULL, NULL)
WHERE datname = 'perfins_msk_db' AND state = 'idle in transaction'
ORDER BY query_start DESC LIMIT 1 \gxПоля
usenameиclient_addrв выводе не замаскированы, параметры запроса в полеqueryзамаскированы. Пример вывода:-[ RECORD 1 ]-------------------------------------------------------------------
sample_time | 2025-08-07 14:02:55.000837+03
datname | perfins_msk_db
pid | 19656
usesysid | 26458
usename | perfins_msk_user
client_addr | <IP-Address>
query | DELETE FROM perfins_msk_schema.perfins_msk_table WHERE ID%***=***;
locktype | virtualxid
mode | ExclusiveLock -
Отмените транзакцию от имени тестового пользователя:
ROLLBACK;Транзакция успешно отменена:
ROLLBACK -
От имени суперпользователя очистите историю:
SELECT pg_stat_activity_history_reset();История очищена:
pg_stat_activity_history_reset
--------------------------------
(1 row)