Thread: Разделение прав
Здравствуйте. Стоит такая задача: есть несколько таблиц, записи в них имеют признак типа "такой-то юзер постгреса имеет право на 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?
>>>>> Andrey N Oktyabrski writes: Andrey> Как выйти из положения? Или есть какое-то решение без view? Мудрённо :) А не проще всю работу организовать через функции с 'security definer', а там уж проверять как угодно? -- Sergey Suleymanov
Sergey Suleymanov wrote: > Andrey> Как выйти из положения? Или есть какое-то решение без view? > > Мудрённо :) А не проще всю работу организовать через функции > с 'security definer', а там уж проверять как угодно? Оно-то может и проще, но только для меня. Как заставить потом этим пользоваться программеров, трудно себе представить. Потому что будет утеряна гибкость запросов.
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.
Андрей, ты бы не поленился, а сделал бы примитивный пример для 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
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.
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