不允许基于Postgresql基于角色的只读用户从基于角色的完全访问权限用户读取

时间:2019-04-24 15:17:12

标签: postgresql

我有一个PG数据库并创建了两个角色:

  1. 对数据库和所有模式的完全访问角色
  2. 对所有模式的只读访问权限

然后我创建用户,并为其中一个用户分配具有完全访问权限的第一个角色,为另一个用户分配只读访问权限。

接下来,我以具有完全访问权限的用户身份创建一个表,现在该表归用户所有。

然后,我尝试以只读用户身份访问表(选择)并获得拒绝权限。

我已经尝试了以下代码段:

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO READONLY_ROLE;
ALTER DEFAULT PRIVILEGES FOR ROLE FULL_ROLE IN SCHEMA public GRANT SELECT ON TABLES TO READONLY_ROLE;

我认为主要的问题是,表不是由角色拥有,而是由分配了角色的用户拥有。但是我不想将只读用户连接到完整用户。

使用这种基于角色的方法是否可行? 是否有可能将表的默认所有者以及功能表更改为完全角色而不是用户(在“创建表”之前没有“设置角色”)?


更新25.04.2019

以下是生成角色和用户的sql语句:

创建写角色:

CREATE ROLE write_role;
GRANT ALL PRIVILEGES ON DATABASE test_db TO write_role;
GRANT ALL ON SCHEMA public TO write_role;

创建阅读角色:

CREATE ROLE read_role;
GRANT CONNECT ON DATABASE test_db TO read_role;
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO read_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_role;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO read_role;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO read_role;
ALTER DEFAULT PRIVILEGES FOR ROLE write_role IN SCHEMA public GRANT SELECT ON TABLES TO read_role;

创建写用户:

CREATE USER write_user WITH ENCRYPTED PASSWORD '';
GRANT write_role TO write_user;

创建读取用户:

CREATE USER read_user WITH ENCRYPTED PASSWORD '';
GRANT read_role TO read_user;

以write_user身份创建表并插入数据:

CREATE TABLE link (
 ID serial PRIMARY KEY,
 url VARCHAR (255) NOT NULL,
 name VARCHAR (255) NOT NULL,
 description VARCHAR (255),
 rel VARCHAR (50)
);
INSERT INTO link (url, name)
VALUES
 ('http://www.postgresqltutorial.com','PostgreSQL Tutorial');

有关表格的信息:

\dt
                 List of relations
 Schema | Name | Type  |           Owner
--------+------+-------+---------------------------
 public | link | table | write_user

选择为read_user:

$ select * from link;
ERROR:  permission denied for table link

更新01.05.2019

多亏了一位同事在工作,我们找到了一个不是计划A而是计划Z的解决方案。本文的灵感来自:Change Ownership via Trigger

本文之所以非常重要的原因是,其他具有write_role的用户也无法删除其他用户创建的表。

这是我稍作调整的事件触发器:

CREATE OR REPLACE FUNCTION trg_create_set_owner()
 RETURNS event_trigger
 LANGUAGE plpgsql
AS $$
DECLARE
  obj record;
BEGIN
  FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag='CREATE TABLE' LOOP
    EXECUTE format('ALTER TABLE %s OWNER TO write_role', obj.object_identity);
    EXECUTE format('GRANT SELECT ON ALL TABLES IN SCHEMA %s to read_role', obj.schema_name);
  END LOOP;
END;
$$;

CREATE EVENT TRIGGER trg_create_set_owner
 ON ddl_command_end
 WHEN tag IN ('CREATE TABLE')
 EXECUTE PROCEDURE trg_create_set_owner();

1 个答案:

答案 0 :(得分:0)

要检查的几件事:

  • 您是否在公共模式中创建了表?如果不是,那么READONLY_ROLE是否对表所在的模式具有USAGE特权?
  • 更改默认权限仅更改运行此权限后创建的对象的权限。您在运行此表之前创建表了吗?
  • 您是要从具有readonly_role的表中选择还是要为其分配了readonly_role的用户进行选择?如果是后者,则用户是否继承特权(默认设置)?

编辑: 感谢您提供所有其他信息。更改默认权限仅适用于一个角色,并且不会被继承(如果用户是具有不同默认特权的多个角色的成员,我认为弄清楚对新对象应用哪些特权并不容易)。

在以写用户身份创建表之前,只需运行:

SET ROLE write_role;