Postgres защита на уровне строк для анонимных блочных сценариев - PullRequest
0 голосов
/ 30 марта 2020

У меня есть игра, над которой я работаю, с Postgres в качестве бэкэнда. Одна из особенностей, с которыми я боролся, - это способ позволить игрокам писать сценарии определенных аспектов игрового процесса. Эти сценарии будут храниться в таблице (текстовом столбце), и в конце каждого хода сценарии будут выполняться с помощью хранимой процедуры.

Я могу выбрать код сценария из этой таблицы и запустить его с помощью оператор что-то вроде этого:

do [script-code-here] language whatever-pl-language; 
--haven't decided which languages to allow, might give them choice of several

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

Примеры create policy в документации Postgres немногочисленны. Мне не удалось найти предложение USING, которое не выполняет простую проверку x = current_user (с ролью, под которой запускается код: current_user).

Если в таблице скриптов есть столбец player_id и во всех других таблицах скрипты могут быть затронуты, есть ли способ сформулировать оператор create policy, который не заставляет меня создавать новую роль postgres для каждого игрока (из которых может быть произвольно большое число)? Блок анонимного кода может (например) установить некоторую переменную в player_id выполняемого скрипта, за исключением того, что оператор set может устанавливать пользовательские параметры или переменные. Также я не могу найти неважное, которое можно изменить и установить на это значение (даже не похоже, что на него можно ссылаться в pl sql).

Есть ли какая-то особенность или трюк, которые позволили бы мне сформулировать create policy утверждения, используя таблицы / столбцы, которые я описал, без создания новых ролей для каждого игрока? * Расширения Postgres приветствуются.

1 Ответ

1 голос
/ 30 марта 2020

Вы можете создать расширение C, которое вводит новый параметр базы данных, который может быть установлен только один раз, и выдаст ошибку, если вы попытаетесь изменить его. Для этого вы должны создать функцию _PG_init, которая вызывает DefineCustomStringVariable с соответствующей функцией проверки. Убедитесь, что полученный модуль добавлен в shared_preload_libraries, так что параметр всегда определен.

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

Но я думаю, что вся идея непродуманна. Я бы никогда не позволил пользователю запускать произвольные операторы SQL в моей базе данных. Для любого пользователя было бы тривиально запустить атаку типа «отказ в обслуживании» на базу данных, либо перегружая процессор, либо заполняя файловую систему случайными данными. И если вы не удалите привилегию CREATE в схеме public ОТ PUBLIC, злоумышленник может также создавать объекты и наносить еще больший ущерб.

SQL слишком мощен, чтобы вы могли разумно ограничить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...