Как предоставить разрешения / установить роль с триггером события ddl_command_start без явного выполнения sql?

Я столкнулся с проблемой при сбросе владельца таблицы всякий раз, когда для таблицы в psql создается индекс. Я делаю это программно, определяя ddl_command_start.

Последовательность событий:

  1. При выполнении / создании api серверная часть создает таблицу с помощью роли table_role и сбрасывает владельца на суперпользователя / администратора.
  2. При выполнении api / createIndex серверная часть пытается создать индекс, используя роль table_role, при этом он не может выполнить ddl_command_start, поскольку table_role не является владельцем созданной таблицы на шаге 1.

Есть ли способ предоставить временный доступ к созданной таблице в качестве владельца на втором этапе? (без выполнения явного sql из кода)

Можно ли вызвать функцию db или другие средства для сброса роли до того, как проверка разрешений произойдет в таблице?

Пожалуйста, дайте мне знать ваши комментарии. Спасибо.

permForIndexEndFunc := `CREATE OR REPLACE FUNCTION internal.trg_create_index_set_owner()
                    RETURNS event_trigger
                    LANGUAGE plpgsql
                    SECURITY DEFINER
                    AS $$
                    DECLARE
                    obj record;
                    tablename text;
                    BEGIN
                    FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag='CREATE INDEX' LOOP
                    tablename := substring(obj.object_identity from 1 for 10);
                    EXECUTE format('SET ROLE %s','admin');
                    EXECUTE format('ALTER TABLE %s OWNER TO table_role', tablename);
                    END LOOP;
                    END;
                    $$;`

    _, err = db.Exec(permForIndexEndFunc)
    if err != nil {
        return err
    }
    permForIndexEndTrigger := `CREATE EVENT TRIGGER trg_create_index_set_owner
                    ON ddl_command_start
                    WHEN tag IN ('CREATE INDEX')
                    EXECUTE PROCEDURE internal.trg_create_index_set_owner();`
    _, err = db.Exec(permForIndexEndTrigger)
    if err != nil {
    return err 
    }

В основном мое приложение создает общие схемы базы данных приема на основе конфигурации клиента (либо через вызовы grpc / rest api), поэтому клиент отправляет схему в форме json и создает идентичную схему базы данных в бэкэнде, затем клиент onwords отправляет данные в предопределенный формат json. Таким образом, в основном, когда схема создается на триггерах событий db, сохраняется rbac такой-то схемы, таблиц. Схема, создание таблицы происходит, принимая только роль создания путем сброса владельца на суперпользователя с использованием триггера события, поэтому время, когда владелец создания индекса таблицы был сброшен и завершился ошибкой.


person Mozhi    schedule 12.06.2020    source источник


Ответы (1)


Давайте назовем суперпользователя / администратора, владеющего таблицей, от пользователя шага 1 a.

Затем, чтобы table_role было разрешено создавать индекс для таблицы, он должен быть членом a. Таким образом, вам необходимо временно предоставить членство в роли:

BEGIN;
GRANT a TO table_role;
CREATE INDEX ...;
REVOKE a FROM table_role;
COMMIT;

Теперь, если a действительно суперпользователь, тогда, конечно, table_role не может этого делать, если только он не является суперпользователем (но в этом случае проблемы не будет, потому что суперпользователям разрешено делать что угодно).

Поэтому убедитесь, что a не является суперпользователем. Затем table_role необходимо иметь CREATEUSER, чтобы ему было разрешено делать то, что описано выше.

person Laurenz Albe    schedule 12.06.2020
comment
спасибо @ [Laurenz Albe], быстрый вопрос, можно ли сделать это на уровне триггера / уровне базы данных вместо того, чтобы делать это в коде. Я имею в виду, что в настоящее время я делаю db.Exec (Create Index), где db - это объект сеанса, созданный с помощью table_role, я намеревался избежать этого. - person Mozhi; 12.06.2020
comment
Понятно. Увы, вы можете предоставить членство на ddl_command_start и отозвать его ddl_command_end, но почему бы не предоставить членство сразу же? Это кажется очень сложным, но вы недостаточно рассказываете нам об основной идее и концепции, чтобы дать лучший совет. Я чувствую, что есть способ лучше, чем все это. - person Laurenz Albe; 12.06.2020
comment
@Laurez Albe в основном мое приложение создает общие схемы приема данных db на основе конфигурации клиента (либо через вызовы grpc / rest api), поэтому клиент отправляет схему в форме json, и я создаю идентичную схему db в бэкэнде, затем клиент отправляет onwords данные в предопределенном формате json. Таким образом, в основном, когда схема создается на триггерах событий db, сохраняется rbac такой-то схемы, таблиц. Схема, создание таблицы происходит путем принятия роли только создания путем сброса владельца на суперпользователя с использованием триггера события, поэтому к моменту создания индекса владелец таблицы был сброшен и не работает. - person Mozhi; 12.06.2020
comment
Не могли бы вы отредактировать вопрос и добавить эту информацию, чтобы ее было легче читать. Было бы также рад, если бы вы могли объяснить все термины, не связанные с базой данных (вы не помечали ничего, не связанного с базой данных, поэтому ожидайте, что это будут читать только люди, работающие с базой данных), например rbac. Пожалуйста, разбейте на абзацы и короткие предложения. - person Laurenz Albe; 12.06.2020
comment
спасибо, я имею в виду управление доступом на основе ролей на уровне базы данных с использованием триггеров событий - person Mozhi; 12.06.2020