разрешения: почему в этом случае требуется обновление владельцем таблицы?
у меня есть две таблицы. Один имеет внешний ключ, ссылающийся на последовательное поле в другой таблице. Я дал привилегию INSERT роли, отличной от владельца, но я все еще не могу вставить в таблицу, содержащую внешний ключ, если я не предоставлю владельцу привилегии обновления таблицы в таблице, содержащей указанное поле. Я не совсем понимаю, почему владелец должен иметь разрешение на обновление, чтобы другая отдельная роль (с привилегией 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.=) FOR SHARE OF x"
однако вышеуказанная вставка работает, если я возвращаю testowner привилегию обновления (GRANT UPDATE ON a TO testowner;
). Почему testowner нуждается в обновлении в этом случае?
Примечание: GRANT UPDATE ON a TO testupdater;
не помогает; кажется, что я должен предоставить обновление роли testowner.
1 ответов
Я предполагаю, что проблема заключается в "For SHARE OF" В этом операторе 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 я никогда не отменял привилегии владельца таблицы, поэтому я не сталкивался с этим раньше.
Я предполагаю, что это происходит потому что вы не хотите, чтобы учетная запись, которая имеет доступ ко всем таблицам, просто потому, что они их создали? Я бы предложил:
- выполните изменения схемы как "postgres" или какой-либо другой суперпользователь, который имеет ограниченный доступ в файл pg_hba.conf
- кроме того, выполните изменения схемы как некоторый пользователь (например, владелец базы данных), который не имеет доступа для входа, используя
set session authorization
из "postgres" или другого суперпользователя