Как стать автором
Обновить

Комментарии 20

Спасибо за решительность и последовательность в воплощении того, что приносит пользу многим людям.
Прекрасная работа, recovery.conf нинужын.

Осталось pg_hba.conf выкинуть, перенеся информацию в БД, и будет совсем хорошо.
trust и ident — исключить как класс, ибо небезопасно.
local peer — прибить гвоздями, всё остальное — через CREATE/ALTER USER/ROLE CONNECT FROM <откуда> BY/VIA и/или GRANT CONNECT TO INSTANCE FROM <откуда> TO BY/VIA .
По умолчанию разрешить подключаться локально (и сокет, и 127.0.0.1) по через SCRAM-SHA-256.
PUBLIC-у по-умолчанию никаких грантов на подключение.

На самом деле мысль интересная (хоть и не возьмусь proposal писать)
Очевидный встречный вопрос от сообщества будет, а как сделать разные настройки для реплик (для начала «как» на уровне описания желаемого поведения). Это явный usecase, для, например, аналитической реплики с прямым доступом для сотрудников, но в то же время не пускать их на мастер. Да, можно через firewall отпилить доступ, но обосновать целесообразность ломания поведения правил доступа надо будет.

Да, с доступом только к реплике — это вопрос.
В рамках предлагаемого переноса видится такое решение:
INSTANCE использовать для доступа и к мастеру, и к репликам;
MASTER/REPLICA в TO использовать для ограничения только к мастеру (пока непонятно для зачем ограничивать только к мастеру, но мало ли) и реплике.
Запросы, соответственно, выполняются на мастере.

Для определения мастера/реплики использовать pg_is_in_recovery().

Определить кто сейчас не в recovery — это элементарный вызов RecoveryInProgress() и совсем не проблема. Их много по коду раскидано в нужных местах.

А вот придти с таким proposal к какому-то консенсусу — задача нетривиальная и я думаю будут противники поактивнее, чем для отпиливания recovery.conf. Пачка настроек вне GUC сообщество не устраивала уже не первый год, а вот про hba как-то не уверен.
Если кто почувствует в себе силы — настоятельно рекомендую сначала написать proposal в pgsql-hackers и только потом начинать сооружать патч. И разделить proposal на 3 разных: соответственно под спиливание trust/ident, не выдавать connect всем при создании базы, собственно замена pg_hba.
Посмотрите как сделано в HP Vertica, которая, кстати, была основана на кодовой базе PostgreSQL, но потом ушла сильно в сторону

Там есть два варианта — full backup / copy cluster или репликация, так вот в первом случае переносится вся база, включая гранты, а во втором случае переносятся только структура таблиц и данные, соответсвенно легко можно назначить разные права на master/replica.

Думаю такое же поведение можно продумать и для PostgreSQL — сделать два режима репликации — с переносом прав (системных таблиц) или нет.

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

p.s. но я не возьмусь даже за proposal, не то что за реализацию, к сожалению(((
физическая и логическая репликация соответственно. Логическая репликация уже появилась в postgresql 10.
Здесь можно много писать об их различиях, но и у того и у другого подхода есть как плюсы, так и ограничения. И против выбрасывания физической репликации я буду возражать очень сильно — она проста, надёжна и не требовательна ни к CPU ни к памяти. Взять страничку, записать страничку. Ну, ладно, чуть сложнее на самом деле из-за обработки конфликтов репликации. Но до сложностей логической репликации очень далеко. А игнорировать в физической репликации часть таблиц нельзя. И даже если сделать можно (против чего опять же даже я буду сильно возражать) — то проблем от этого добавится много. В частности, что делать с durability этой таблицы, раз её нет в wal (реплика свои wal писать не может и не должна).
Я говорю только о системных, специальных таблицах, которые являются аналогом hal, то есть это гранты, но в более гибком смысле. Они могут (и скорее всего даже должны) храниться отдельно, а не как типичная таблица и находиться после старта БД в памяти, но записываться на диск само собой

В таком случае WAL писать не нужно, как и ломать физическую репликацию, достаточно добавить ключ, вроде того — синхронизировать гранты или нет

Я бы тоже сильно возражал против изменения текущей схемы физической репликации, но её и не нужно ломать, просто заменить HAL на что-то более удобное и гибкое

Пример: www.vertica.com/docs/9.1.x/HTML/index.htm#Authoring/SQLReferenceManual/SystemTables/CATALOG/GRANTS.htm — весь Catalog хранится в datapath, но он отделен от данных, то есть таплы для grants можно копировать (fullbackup), а можно и не копировать
В таком случае WAL писать не нужно

Как их восстанавливать при сбое? Важно: согласованно с состоянием системного каталога и, особенно теми несколькими shared relations, например как раз pg_authid.
Сейчас все системные таблицы обязательно WAL-logged.
Они специальные, дополнительно защищены, ряд таблиц запинен даже в private memory каждого backend'а, а не только в shared_buffers.
Как делать rollback?

С внешним pg_hba.conf прячем голову в песок, это конфигурация, СУБД его читает при старте/reload, в остальное время он неважен и обязанность админа за ним следить, как и за основным конфигом. На уровне SQL это уже будет обязанность базы. Вы замечали, что даже postgresql.auto.conf пишется во временный файл и затем подменяет старый с fsync?
Тем более важно по той причине, что без postgresql.auto.conf работать можно, а вот без правил авторизации — уже нет, вы и подключиться к базе не сможете, чтобы перебить руками grant connect from из бекапа.
В общем да, соглашусь, что вопрос не простой. Можно вести отдельный WAL-лог — единственное что на ум приходит, с другой стороны очевидно, что это костыль
А отдельный WAL нельзя атомарно записать. Нет атомарного fsync на два файла сразу. И надо придумывать двухфазный коммит в пределах одной базы для этого или консистентно уже не встать: может быть ситуация, что мы записали один wal, но не записали второй.
Для таблицы вроде grants не нужна атомарность на уровне БД же.

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

Зачем тут атомарность? Мы просто заменим правку HAL + релоад на механизм хранения этих данных «рядом» с данными в БД

Ну не записали мы grant — свет выключили — во-первых у нас есть юзер postgres с полными правами (кстати в упомянутой Vertica есть dbadmin, он как root в Linux внутри БД) и мы можем накатить грантов после того как сервер оживет. Вариантов с непустой БД и отсутствием прав на нее для некоего админа представить сложно
То есть вы предлагаете исключить из механизма грантов на коннект суперпользователя? Почему? И при каких условиях он тогда должен проходить авторизацию, а когда — нет? Почему?

А если так получилось, что ему нужен сетевой доступ? Или, наоборот, хотим дать ему доступ только через unixsock? Дефолтом это сделать нельзя, unixsock существует не на всех поддерживаемых платформах.

Гранты на выполнение запросов и на доступ к объектам внутри конкретной базы есть и они обязаны быть транзакционными и wal-logged, об этом речи нет.
Расскажу на примере той же Вертики, очень уж нравится мне их архитектура, при том, что она остается в чем-то postgres-like

У них есть superuser, который просто системный пользователь и у него всегда тип авторизации только пароль, при этом он рекомендуется к использованию только для запуска/остановки базы, бэкапов и других сервисных функций + давать права pseudosuperuser'ам. При этом у него есть сетевой доступ

А вот как раз pseudosuperuser это уже роль и она хранится в самой БД и соответственно делегируется другим пользователям через GRANT pseudosuperuser TO username;

То есть тут четко разделяется сервисный уровень и уровень доступа к данным

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

Правда стоит отметить, что все-таки Вертика не реляционная база, хоть и ACID

UDP: ну да и у них нет авторизации типа ident и access
Осталось pg_hba.conf выкинуть

А что плохого в этом файлике. С применением параметров проблем нет, и ничего из вне не сможет добавить лишних доступов. ИМХО очень полезный файлик местами.
Да в общем-то ничего плохого. Для бекапа всё равно надо бекапить и основной конфиг, файлом больше/файлом меньше не сильная разница. Выставлять базу в мир нельзя, ddos'ом на авторизацию кладётся элементарно, а для своих рабочих подсетей нередко просто all/all по паролю есть правило будь то md5 или SCRAM-SHA-256. Или, что в моей практике встречается чаще — всё равно есть отдельный userlist на pgbouncer, а база на сетевом интерфейсе доступна для работы репликации.

Правила доступа непосредственно в базе рядом с самими пользователями имеют как преимущества (хотя бы не надо конфиг перезагружать, что не проблема, но надо помнить об этом и, что более важно, проверять по логу, успешно ли загрузился конфиг или где опечатались — популярная ошибка указать IP без маски сети), так и недостатки.
И вот поскольку pg_hba.conf есть уже — то любому, кому этот конфиг не нравится, придётся как раз описывать его недостатки и преимущества переноса правил в саму базу.

ничего из вне не сможет добавить лишних доступов

Вот, тоже полезная точка зрения.

А вот ограничить в использовании trust и не давать connect права всем на новую базу — это я бы поддержал.
Ну хотя бы что-то — перенесли параметры в postgresql.conf. Вообще слоник реально похож уже на слона, где проще надежно страдать, чем ненадежно жить без страданий
доковыряем и переключение primary_conninfo на лету. Я перенос настроек recovery в postgresql.conf раньше pg13 в принципе не ждал. От удивления статью написал даже
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации