permissions: зачем UPDATE нужен владелец таблицы в этом случае? - PullRequest
6 голосов
/ 12 декабря 2010

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

Это немного сбивает с толку, поэтому я привел пример моей проблемы.

createuser -U postgres testowner -DIRS --pwprompt
createdb -U postgres -O testowner testdb
createuser -U postgres testupdater -DIRS --pwprompt

psql -d testdb -U testowner
CREATE TABLE a ( id serial PRIMARY KEY );
CREATE TABLE b ( a_id integer REFERENCES a(id) );
GRANT SELECT,INSERT ON ALL TABLES IN SCHEMA public TO testupdater;
GRANT USAGE,UPDATE ON SEQUENCE a_id_seq TO testupdater;
REVOKE INSERT, UPDATE ON ALL TABLES IN SCHEMA public FROM testowner;
INSERT INTO a VALUES (DEFAULT);  -- as expected: ERROR:  permission denied for relation a
\q

psql -d testdb -U testupdater
INSERT INTO a VALUES (DEFAULT);
SELECT id FROM a LIMIT 1;  -- selects the first id (1)
INSERT INTO b VALUES (1); -- unexpected error: see below
\q

ERROR: permission denied for relation a

CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."a" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR SHARE OF x"

Однако эта вставка работает, если я верну testowner привилегию UPDATE (GRANT UPDATE ON a TO testowner;). Зачем testowner нужно ОБНОВЛЕНИЕ в этом случае?

ПРИМЕЧАНИЕ: GRANT UPDATE ON a TO testupdater; не помогает; Похоже, я должен предоставить ОБНОВЛЕНИЕ роли Testowner.

1 Ответ

6 голосов
/ 12 декабря 2010

Я предполагаю, что проблема заключается в «FOR SHARE OF» в этом операторе select - чтобы иметь возможность создать эту блокировку строки, вам необходим как минимум какой-то доступ на запись в таблицу.

например, если я создаю таблицу и предоставляю себе только SELECT доступ к ней:

postgres@testdb=# create table t(t1_id serial primary key, value text);
NOTICE:  CREATE TABLE will create implicit sequence "t_t1_id_seq" for serial column "t.t1_id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "t_pkey" for table "t"
CREATE TABLE
postgres@testdb=# insert into t(value) values('foo');
INSERT 0 1
postgres@testdb=# grant select on t to steve;
GRANT

сейчас, хотя я могу читать строки из таблицы, я не могу их заблокировать:

steve@testdb@[local] => select * from t;
 t1_id | value 
-------+-------
     1 | foo
(1 row)

steve@testdb@[local] => select * from t for share;
ERROR:  permission denied for relation t

Делая предположение сейчас ... предположительно, реализация внешних ключей работает, проверяя наличие целевых строк во внешних таблицах и устанавливая контекст авторизации для этого на основе владельца исходной таблицы или целевой таблицы ... TBH IЯ никогда не отменял привилегии владельца таблицы, поэтому я не сталкивался с этим раньше.

Я предполагаю, что это происходит потому, что вам не нужна учетная запись, которая имеет доступ ко всем таблицам просто потому, что они их создали?Я хотел бы предложить:

  • Выполнить изменения схемы как «postgres» или какой-либо другой суперпользователь, который имеет ограниченный доступ в pg_hba.conf
  • В качестве альтернативы, выполнить изменения схемы как некоторый пользователь (например, база данных)владелец), который не имеет доступа к логину, используя set session authorization из 'postgres' или другого суперпользователя
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...