Thread: Разделение прав

Разделение прав

From
"Andrey N. Oktyabrski"
Date:
Здравствуйте.

Стоит такая задача:
есть несколько таблиц, записи в них имеют признак типа "такой-то юзер
постгреса имеет право на select/update этой записи", надо сделать
как-то, чтобы юзер не мог сделать то, что ему запрещено.

Я планировал сделать это так:
create table _tbl (...);
create view tbl as select * from _tbl where owner = session_user();
revoke all on tbl from <юзер>;
grant select on tbl to <юзер>;
revoke all on _tbl from <юзер>;
grant insert, update, delete on _tbl to <юзер>;

Но тогда
update _tbl set fld = 123 where id = 21;
не работает - постгрес говорит, что нет прав. grant select on _tbl to
<юзер> спасает, но я не хочу чтобы юзер читал из таблицы, для этого
сделано представление-подмножество таблицы.

Как выйти из положения? Или есть какое-то решение без view?

Re: Разделение прав

From
Sergey Suleymanov
Date:
>>>>> Andrey N Oktyabrski writes:

 Andrey> Как выйти из положения? Или есть какое-то решение без view?

         Мудрённо :) А не проще всю работу организовать через функции
         с 'security definer', а там уж проверять как угодно?

--
  Sergey Suleymanov

Re: Разделение

From
"Andrey N. Oktyabrski"
Date:
Sergey Suleymanov wrote:
>  Andrey> Как выйти из положения? Или есть какое-то решение без view?
>
>          Мудрённо :) А не проще всю работу организовать через функции
>          с 'security definer', а там уж проверять как угодно?
Оно-то может и проще, но только для меня. Как заставить потом этим
пользоваться программеров, трудно себе представить. Потому что будет
утеряна гибкость запросов.

Re: Разделение прав

From
"Andrey N. Oktyabrski"
Date:
Andrey N. Oktyabrski wrote:
> Здравствуйте.
>
> Стоит такая задача:
> есть несколько таблиц, записи в них имеют признак типа "такой-то юзер
> постгреса имеет право на select/update этой записи", надо сделать
> как-то, чтобы юзер не мог сделать то, что ему запрещено.
>
> Я планировал сделать это так:
> create table _tbl (...);
> create view tbl as select * from _tbl where owner = session_user();
> revoke all on tbl from <юзер>;
> grant select on tbl to <юзер>;
> revoke all on _tbl from <юзер>;
> grant insert, update, delete on _tbl to <юзер>;
>
> Но тогда
> update _tbl set fld = 123 where id = 21;
> не работает - постгрес говорит, что нет прав. grant select on _tbl to
> <юзер> спасает, но я не хочу чтобы юзер читал из таблицы, для этого
> сделано представление-подмножество таблицы.
>
> Как выйти из положения? Или есть какое-то решение без view?
Да, мысль пришла... Может ли кто-нибудь подсказать, в каком месте хачить
исходники постгреса на предмет разрешения update без прав на select? С
целью соорудить патч и попытаться попросить Олега закоммитить его :-)
Если это, конечно, politically correct solution.

Re: Разделение прав

From
Oleg Bartunov
Date:
Андрей,

ты бы не поленился, а сделал бы примитивный пример для cut'n paste
технологии, чтобы не корячиться самому. А то написал что-то на псевдоязыке
(да еще и неправильно), и хочешь, чтобы тебе помогли.
То, что ьы хочешь называется 'updateable view'. В pgsql нет полной реализации
'create view', поэтому вот так просто ничего не сделаешь
Но если не ты поленишься и пойдешь на
http://pgsql.ru/db/pgsearch/index.html?q=updateable+view&tmpl=%F0%D2%C9%D7%C5%D4&ps=10&set=&group=2&site=
то найдешь кучу полезного. В частности
http://www.varlena.com/varlena/GeneralBits/111.php


     Олег
On Tue, 14 Feb 2006, Andrey N. Oktyabrski wrote:

> Andrey N. Oktyabrski wrote:
>> Здравствуйте.
>>
>> Стоит такая задача:
>> есть несколько таблиц, записи в них имеют признак типа "такой-то юзер
>> постгреса имеет право на select/update этой записи", надо сделать как-то,
>> чтобы юзер не мог сделать то, что ему запрещено.
>>
>> Я планировал сделать это так:
>> create table _tbl (...);
>> create view tbl as select * from _tbl where owner = session_user();
>> revoke all on tbl from <юзер>;
>> grant select on tbl to <юзер>;
>> revoke all on _tbl from <юзер>;
>> grant insert, update, delete on _tbl to <юзер>;
>>
>> Но тогда
>> update _tbl set fld = 123 where id = 21;
>> не работает - постгрес говорит, что нет прав. grant select on _tbl to
>> <юзер> спасает, но я не хочу чтобы юзер читал из таблицы, для этого сделано
>> представление-подмножество таблицы.
>>
>> Как выйти из положения? Или есть какое-то решение без view?
> Да, мысль пришла... Может ли кто-нибудь подсказать, в каком месте хачить
> исходники постгреса на предмет разрешения update без прав на select? С целью
> соорудить патч и попытаться попросить Олега закоммитить его :-) Если это,
> конечно, politically correct solution.
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: Don't 'kill -9' the postmaster
>

     Regards,
         Oleg
_____________________________________________________________
Oleg Bartunov, Research Scientist, Head of AstroNet (www.astronet.ru),
Sternberg Astronomical Institute, Moscow University, Russia
Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/
phone: +007(495)939-16-83, +007(495)939-23-83

Re: Разделение

From
"Andrey N. Oktyabrski"
Date:
Oleg Bartunov wrote:
> ты бы не поленился, а сделал бы примитивный пример для cut'n paste
> технологии, чтобы не корячиться самому. А то написал что-то на псевдоязыке
Так пойдёт?
qq=# CREATE USER qq;
CREATE ROLE
qq=# CREATE TABLE t (i serial not null primary key, a text);
NOTICE:  CREATE TABLE создаст подразумеваемую последовательность
"t_i_seq" для serial-колонки "t.i"
NOTICE:  CREATE TABLE / PRIMARY KEY создаст подразумеваемый индекс
"t_pkey" для таблицы "t"
CREATE TABLE
qq=# CREATE VIEW v AS SELECT * FROM t WHERE a = session_user;
CREATE VIEW
qq=# INSERT INTO t (a) VALUES ('qq');
INSERT 0 1
qq=# INSERT INTO t (a) VALUES ('ano');
INSERT 0 1
qq=# REVOKE ALL ON t, v FROM qq;
REVOKE
qq=# GRANT insert, update, delete ON t TO qq;
GRANT
qq=# GRANT select ON v TO qq;
GRANT
qq=# GRANT select, update ON t_i_seq TO qq;
GRANT
qq=# \c qq qq
Вы подсоединились к базе данных "qq" как пользователь "qq".
qq=> INSERT INTO t (a) VALUES ('qq');
INSERT 0 1
qq=> SELECT * FROM t;
ERROR:  доступ запрещён для связи t
qq=> SELECT * FROM v;
  i  | a
----+----
   1 | qq
   3 | qq
(записей: 2)
qq=> UPDATE t SET a = 'ano' where i = 3;
ERROR:  доступ запрещён для связи t
qq=> DELETE FROM t where i > 2;
ERROR:  доступ запрещён для связи t

Потому я и хочу возможность update/delete без необходимости разрешения
select.

> (да еще и неправильно), и хочешь, чтобы тебе помогли. То, что ьы хочешь
А что там неправильно?

> называется 'updateable view'. В pgsql нет полной реализации
> 'create view', поэтому вот так просто ничего не сделаешь
Эт я в курсе, не первый год жду, как и переменных для транзакций :-)
Потому и пытаюсь найти более-менее эквивалентную замену.

> Но если не ты поленишься и пойдешь на
> http://pgsql.ru/db/pgsearch/index.html?q=updateable+view&tmpl=%F0%D2%C9%D7%C5%D4&ps=10&set=&group=2&site=
> то найдешь кучу полезного. В частности
> http://www.varlena.com/varlena/GeneralBits/111.php
Был и там, и там. Если не выйдет как-то более красиво, придётся
придумать что-то подобное. Но это получится громоздко и сильно зависимо
от структуры базы. Если в какой-то момент времени одна из таблиц
изменится, надо будет проверить и поправить всё это нагромождение.

Тогда уж мне больше подойдёт вот это
http://pgfoundry.org/projects/veil/

Правда, тоже не особо красивое произведение (пока?), да и смущает вот что:
#  Development Status: 3 - Alpha
...
Registered: 2005-09-13 18:45
Activity Percentile: 0%

>>> Стоит такая задача:
>>> есть несколько таблиц, записи в них имеют признак типа "такой-то юзер
>>> постгреса имеет право на select/update этой записи", надо сделать
>>> как-то, чтобы юзер не мог сделать то, что ему запрещено.
>>>
>>> Я планировал сделать это так:
>>> create table _tbl (...);
>>> create view tbl as select * from _tbl where owner = session_user();
>>> revoke all on tbl from <юзер>;
>>> grant select on tbl to <юзер>;
>>> revoke all on _tbl from <юзер>;
>>> grant insert, update, delete on _tbl to <юзер>;
>>>
>>> Но тогда
>>> update _tbl set fld = 123 where id = 21;
>>> не работает - постгрес говорит, что нет прав. grant select on _tbl to
>>> <юзер> спасает, но я не хочу чтобы юзер читал из таблицы, для этого
>>> сделано представление-подмножество таблицы.
>>>
>>> Как выйти из положения? Или есть какое-то решение без view?
>> Да, мысль пришла... Может ли кто-нибудь подсказать, в каком месте
>> хачить исходники постгреса на предмет разрешения update без прав на
>> select? С целью соорудить патч и попытаться попросить Олега
>> закоммитить его :-) Если это, конечно, politically correct solution.


Re: Разделение

From
"Andrey N. Oktyabrski"
Date:
Andrey N. Oktyabrski wrote:
> qq=> UPDATE t SET a = 'ano' where i = 3;
> ERROR:  доступ запрещён для связи t
> qq=> DELETE FROM t where i > 2;
> ERROR:  доступ запрещён для связи t
>
> Потому я и хочу возможность update/delete без необходимости разрешения
> select.
Тут вот человек патчик соорудил, который даёт нужную функциональность,
но мы не уверены, что он не делает где-то дырку в безопасности. Надо,
чтобы его проверил человек, хорошо знакомый с дизайном постгреса:

--- postgresql-8.1.2/src/backend/executor/execMain.c    2005-11-22
21:23:08.000000000 +0300
+++ postgresql/src/backend/executor/execMain.c  2006-02-17
13:19:29.000000000 +0300
@@ -460,6 +460,16 @@
         bool            do_select_into;
         TupleDesc       tupType;

+       if ( operation == CMD_UPDATE )
+       {
+               ListCell   *l;
+               foreach(l, parseTree->rtable)
+               {
+                       RangeTblEntry *rte = lfirst(l);
+                       rte->requiredPerms ^= ACL_SELECT;
+               }
+       }
+
         /*
          * Do permissions checks.  It's sufficient to examine the
query's top
          * rangetable here --- subplan RTEs will be checked during