【问题标题】:permissions: why is UPDATE needed by the table owner in this case?权限:为什么在这种情况下表所有者需要 UPDATE ?
【发布时间】:2010-12-12 20:56:18
【问题描述】:

我有两张桌子。一个有一个外键引用另一个表中的序列字段。我已将 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"

但是,如果我将 UPDATE 权限 (GRANT UPDATE ON a TO testowner;) 还给 testowner,则上述插入工作。为什么在这种情况下测试所有者需要 UPDATE?

注意:GRANT UPDATE ON a TO testupdater; 没有帮助;看来我必须对 testowner 角色进行 GRANT UPDATE。

【问题讨论】:

  • 如果您授予用户对 testowner 的读取权限,它是否有效? testupdater 上的插入需要读取 testowner 中的外键值,以确保插入有效。
  • @Macy 我从未撤销过testowner 角色的 SELECT 权限。 testupdater 也被授予 SELECT 权限,因此它似乎应该能够读取表 a 以检查参考。
  • 这里运行良好,没有意外错误。
  • @Frank Weird - 我使用的是 v9.0;你在用什么?

标签: sql postgresql permissions


【解决方案1】:

我认为问题在于该 select 语句中的“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 中具有有限访问权限的超级用户身份执行架构更改
  • 或者,使用来自“postgres”或其他超级用户的set session authorization 以某些没有登录访问权限的用户(例如数据库所有者)身份执行架构更改

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-08
    • 2016-07-17
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    相关资源
    最近更新 更多