PostgreSQL SELECT-RULES, наследование, разрешения на уровне строк

Вот что я читал:

 http://www.postgresql.org/docs/9.2/static/rules-views.html
 http://www.postgresql.org/docs/9.2/static/rules-privileges.html

Моя цель - позволить логину видеть только те строки, которые ему, так сказать, «принадлежат».

Допустим, каждая таблица в базе данных наследуется от этой таблицы:

   create table WHOAMI
   ( 
      tenant varchar(25) not null default current_user
   );

Например:

   create table FOO
   (
     id int primary key,
     invoicedate date
   ) inherits (WHOAMI);

    insert into FOO(id, invoicedate) values(1,now()::date);

    select * from FOO;

    --abclogin|1|2013-02-01

Есть ли в PostgreSQL такая вещь, как правило выбора на уровне схемы, влияющее на все таблицы и представления в схеме, которое добавляет к каждому оператору выбора, вставки, обновления или удаления условие, которое гласит: эффект, ..AND WHERE TENANT = current_user? Если такого глобального правила нет, можно ли его применять для каждой таблицы? Мои попытки не увенчались успехом, и, вероятно, я неправильно понимаю некоторые вещи о том, как создаются правила. Вот что я пытался сделать:

Я пытаюсь создать правило выбора:

  CREATE RULE "_RETURN" AS ON SELECT TO FOO DO INSTEAD
  SELECT * FROM FOO where tenant = current_user;

но получаю эту ошибку: ERROR: could not convert table "foo" to a view because it has indexes

Я пытаюсь создать представление с барьером безопасности:

       CREATE VIEW TENANTFOO WITH (security_barrier) AS
       SELECT * FROM FOO WHERE tenant=current_user;

а затем попробуйте вставить:

        insert into TENANTFOO(id,invoicedate)
        values(2,(now()::date);

но получите эту ошибку:

        `ERROR:  cannot insert into view "tenantfoo"
         HINT:  You need an unconditional ON INSERT DO INSTEAD rule
         or an INSTEAD OF INSERT trigger.`

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


person Tim    schedule 09.02.2013    source источник


Ответы (2)


В последнем примере вам нужно будет запустить INSERT для таблицы или создать другое ПРАВИЛО: ON INSERT TO TENANTFOO DO INSTEAD.

person Erwin Brandstetter    schedule 09.02.2013

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

Между тем, некоторое время назад я работал со следующим дизайном.

Требования были аналогичны, представления должны были доставлять только те строки, которые предназначены для CURRENT_USER. В нашем случае доступ был сделан довольно просто: таблица, в которой указывалось, имеет ли данный пользователь доступ для данного отношения и данного ключа, что-то вроде:

CREATE TABLE user_grants (
    user_id     integer,
    entity_name text, -- should exist in pg_class
    entity_id   integer
);

Затем, скажем, для tasks было создано следующее представление:

CREATE VIEW tasks_v AS
SELECT t.*
  FROM tasks t
  JOIN user_grants ug ON t.user_id = ug.user_id
   AND ug.entity_name='TASKS' AND ug.entity_id = t.task_id;

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

person vyegorov    schedule 09.02.2013