Временное повышение прав в PostgreSQL: безопасные методы для мониторинга и управления процессами
Администраторы баз данных часто сталкиваются с задачей предоставления ограниченных привилегий обычным пользователям - например, права на просмотр всех активных соединений в pg_stat_activity и возможность завершать (kill) чужие процессы. При этом выдавать полные права суперпользователя (SUPERUSER) небезопасно. В PostgreSQL существует несколько механизмов для временного повышения прав, аналогичных indirect ролям в Sybase.
Как временно повысить привилегии без SUPERUSER
PostgreSQL не имеет встроенной конструкции indirect role, как в Sybase, но предлагает гибкие инструменты: предопределённые роли, атрибут SECURITY DEFINER и контекстные функции. Рассмотрим их по порядку.
Предопределённая роль pg_read_all_stats
Роль pg_read_all_stats предоставляет доступ к статистическим представлениям, включая pg_stat_activity. Выдача этой роли обычному пользователю безопасна, если вы доверяете ему чтение данных о производительности. Однако она не даёт права завершать процессы. Для киллинга потребуется дополнительный механизм.
Функции с SECURITY DEFINER для временного повышения прав
Атрибут SECURITY DEFINER позволяет функции выполняться с правами её владельца (обычно суперпользователя). Вопреки распространённому заблуждению, это работает не только для операций чтения - внутри такой функции можно выполнять любые действия, включая pg_terminate_backend(). Главное - ограничить входные параметры и добавить проверки.
Пример безопасной функции для киллинга процесса:
CREATE OR REPLACE FUNCTION public.kill_user_process(pid integer)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_stat_activity WHERE pid = $1) THEN
PERFORM pg_terminate_backend($1);
RETURN true;
ELSE
RETURN false;
END IF;
END;
$$;
REVOKE EXECUTE ON FUNCTION public.kill_user_process FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.kill_user_process TO username;Владельцем функции должен быть суперпользователь. После создания права на выполнение выдаются только конкретному пользователю. Такой подход безопасен, так как функция не позволяет выполнять произвольный SQL.
Комбинация pg_read_all_stats и функции-обёртки
Для полного решения задачи (просмотр всех процессов + киллинг) рекомендуется:
- Выдать пользователю роль
pg_read_all_stats- это даст доступ кpg_stat_activity. - Создать функцию с
SECURITY DEFINERдляpg_terminate_backend. - Назначить права на выполнение функции только нужному пользователю.
Безопасность и рекомендации
Временное повышение прав через SECURITY DEFINER считается безопасным, если:
- Функция не принимает динамический SQL (риск SQL-инъекции).
- Входные параметры строго проверяются.
- Функция выполняет только конкретную операцию (например, завершение процесса по PID).
Не рекомендуется выдавать роль pg_signal_backend напрямую обычным пользователям - она даёт право завершать любые процессы без дополнительных проверок. Используйте функцию-обёртку с логированием или ограничениями.
Альтернативные подходы
Если требуется более гибкое временное повышение прав, рассмотрите:
- Использование расширения pg_background для выполнения задач с повышенными привилегиями.
- Создание процедуры с SECURITY DEFINER (в PostgreSQL 11+ процедуры также поддерживают этот атрибут).
- Применение контекстных переменных через
SET SESSIONвнутри функции - это позволяет временно изменять параметры сессии.
Таким образом, в PostgreSQL нет встроенного механизма indirect role, но комбинация предопределённых ролей и функций с SECURITY DEFINER полностью решает задачу временного повышения прав для мониторинга и управления процессами.