zubkov-andrei / pg_profile

Postgres historic workload reports
Other
212 stars 31 forks source link

Добавить возможность использования методов беспарольной аутентификации для подключения к серверам. #89

Open monok0 opened 2 months ago

monok0 commented 2 months ago

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

Рассматривался ли вариант с возможность обнаруживать наличие строго определенной SECURITY DEFINER функции, которая должна будет вызывать только dblink_connect с передаваемыми в нее аргументами соединения, а возвращать имя созданного подключения? Права суперпользователя нужны будут только для открытия соединения, после этого пользоваться им может любой пользователь. Это позволит использовать почти любые методы аутентификации, в том числе TLS.

Пользователь сможет создать такую функцию в схеме pg_profile под супером, выдав пользователю-владельцу pg_profile права на execute. Если функция не будет обнаружена, то использовать обычный вызов dblink_connect как сейчас.

Для безопасности можно также требовать, чтобы у функции был строго определенный код, проверять, например, через routine_definition из information_schema.routines.

Если реализация будет рассматриваться, то хотелось бы еще попросить поддержать указание параметров подключения в виде имени foreign server. Сейчас при попытке это сделать падает парсинг строки подключения из таблицы серверов, т.к. он ждет пару "ключ=значение," а при использовании имени сервера нужно только имя, т.е. "значение".

zubkov-andrei commented 2 months ago

Добрый день! Как-то всего много и сразу.. Я не изучал тему, но всё-таки, а что dblink не поддерживает TLS? Какой смысл защищаться от владельца pg_profile, если его задача - только автоматическое выполенние снимков. Живые люди не должны работать с этой ролью. Для сбора отчётов достаточно привилегии pg_read_all_stats, и быть владельцем pg_profile не обязательно. Можно даже использовать роль public, но некоторые данные в отчёте тогда будут не видны.

Foreign server, насколько я понимаю, не подойдёт для наших целей, поскольку профайлу надо подставлять туда имя базы данных для сбора данных по объектам схем разных баз кластера.

Короче, надо больше подробностей.

monok0 commented 2 months ago

Добрый день. Тогда подробности по пунктам:

  1. Dblink поддерживает TLS, но подключение с аутентификацией по сертификату (без пароля) может установить только суперпользователь, иначе вылетит стандартное "... password is required...". После открытия это подключение можно использовать уже без прав супера.
  2. В соответствии с политикой безопасности требуется, чтобы вся аутентификация происходила по сертификатам без использования паролей. Гипотетическое решение "над" профайлом с оборачиванием его вызовов выливалось в то, что владелец мог бы выполнять произвольный код под супером, потому решили предложить это как общую доработку.
  3. (Эта часть больше "вдогонку" к предыдущей, так как тоже касается настройки подключения) Если правильно понял замечание, у foreign_server можно указать бд (пример: CREATE SERVER if not exists server_name FOREIGN DATA WRAPPER dblink_fdw OPTIONS (hostaddr '%s', dbname '%s', port '%s')). Он, цитируя доки, "can have the same options that libpq accepts in connection strings" за исключением нескольких полей, которые уже хранятся в маппинге конкретного пользователя (см. подробнее). Т.е. это почти полный эквивалент строки подключения для dblink, но, при использовании через суперпользователя, это позволяет хранить пароли не в базе, а в файле .pgpass, куда он полезет, если не увидит пароля в маппинге пользователя. Если же речь про то, что профайлу нужно вытаскивать имя базы, то можно дернуть их, опять же, из опций сервера
    select 
    srvname as name, 
    srvoptions as options
    from pg_foreign_server;

Готов ответить на любые дополнительные вопросы.

zubkov-andrei commented 2 months ago

Мне создание такого функционала кажется вполне возможным, но я всё еще не вполне понимаю от какой угрозы вы пытаетесь защититься с её помощью.

Я правильно понимаю, что вы не можете исполнять снимки pg_profile от суперпользователя, но при этом хотите чтобы он мог работать без упоминания каких-либо паролей?

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