【问题标题】:How to use default schema privileges on functions in Postgres in right way?如何以正确的方式对 Postgres 中的函数使用默认模式权限?
【发布时间】:2018-08-14 23:03:20
【问题描述】:

我很难理解默认模式权限在 Postgres 中的工作方式。对我来说,它们应该通过自动发布权限来减轻管理负担,但我发现它们有点不可用。我从documentation 中发现了一些根本不明显的东西。

我希望多个用户能够在架构中创建和修改对象。我创建了一个将成为所有者的角色,并将该角色授予多个(一般)用户:

create schema my_schema;
create role my_schema_owner;
alter schema my_schema owner to my_schema_owner;
create user my_user password 'xxx';
grant my_schema_owner to my_user;
create role my_role;
alter default privileges in schema my_schema grant execute on functions to my_role;
create function my_schema.my_func1() returns int as
  $$ begin return 3; end; $$ language plpgsql;

请注意,我是在自己的(管理)帐户下执行此操作的。

接下来,我检查我得到了什么。我使用这个视图:

create or replace view pg_functions_grants as
select proname, n.nspname, coalesce(nullif(s[1], ''), 'public') as grantee,
       s[2] as privileges, s[3] as grantor
from pg_proc p
join pg_namespace n on n.oid = p.pronamespace
join pg_roles r on r.oid = p.proowner
join pg_type rt on p.prorettype = rt.oid,
unnest(coalesce(p.proacl::text[], format('{%s=arwdDxt/%s}', r.rolname, r.rolname)::text[])) acl,
regexp_split_to_array(acl, '=|/') s

并为创建的对象请求权限:

select * from pg_functions_grants where proname = 'my_func1' order by 1;

my_func1    my_schema   public      X       <me>
my_func1    my_schema   <me>        X       <me>
my_func1    my_schema   my_role     X       <me>

a) 我们看到它在 func1 上被授予 PUBLIC 执行。没关系,文档说它是默认的。 b)它授予我执行权限。没关系,但似乎多余,因为我已经是所有者。 c)它按照我的要求授予 my_role 执行权限。完美。

现在我假装自己是被授予所有权的用户:

set role my_user;
create function my_schema.my_func2() returns int as
  $$ begin return 3; end; $$ language plpgsql;

select * from pg_functions_grants where proname = 'my_func2' order by 1;

my_func2    my_schema   my_user     arwdDxt my_user

d) 为什么不授予 PUBLIC 执行权限?

e) 为什么它没有应用默认权限?

我试图弄清楚发生了什么:

create or replace view pg_namespaces_default_grants as
select n.nspname, r.rolname, d.defaclobjtype, coalesce(nullif(s[1], ''), 'public') as grantee,
       s[2] as privileges, s[3] as grantor
from pg_default_acl d
join pg_namespace n on d.defaclnamespace = n.oid
join pg_roles r on r.oid = n.nspowner,
unnest(coalesce(d.defaclacl::text[], format('{%s=arwdDxt/%s}', r.rolname, r.rolname)::text[])) acl,
regexp_split_to_array(acl, '=|/') s;

select * from pg_namespaces_default_grants where nspname = 'my_schema';

my_schema   my_schema_owner f   my_role X   <me>

嗯...我看到这里提到的设保人...可能这很重要吗?让我们在我的用户下设置默认值:

set role my_user;
alter default privileges in schema my_schema grant execute on functions to my_role;
create function my_schema.my_func3() returns int as
  $$ begin return 3; end; $$ language plpgsql;

select * from pg_functions_grants where proname = 'my_func3' order by 1;

my_func3    my_schema   public  X   my_user
my_func3    my_schema   my_user X   my_user
my_func3    my_schema   my_role X   my_user

现在它按预期工作了。

好的,可能是通过授予的角色继承默认权限吗?

set role my_schema_owner;
alter default privileges in schema my_schema grant execute on functions to my_role;
set role my_user;
alter default privileges in schema my_schema revoke execute on functions from my_role;

让我们验证一下:

select * from pg_namespaces_default_grants where nspname = 'my_schema';

my_schema   my_schema_owner f   my_role X   my_schema_owner
my_schema   my_schema_owner f   my_role X   <me>

正确。现在:

set role my_user;
create function my_schema.my_func7() returns int as
  $$ begin return 3; end; $$ language plpgsql;

select * from pg_functions_grants where proname = 'my_func7' order by 1;

my_func7    my_schema   my_user arwdDxt my_user

该死的,它没有!

总结:默认权限仅在用户(显式)设置默认权限的用户下创建对象时有效,在被授予角色 who 的用户下工作设置默认权限。

现在的问题:

  1. 上述事实是否在我未能找到的文档中的某个地方提到?

  2. 为什么这么不方便?可能是我滥用它吗?有没有办法在模式中设置默认权限,该权限适用于每个具有某些授予角色的用户?对于所有(现有和未来)用户?

  3. PUBLIC 的情况完全不清楚。为什么它没有在 d) 中将 EXECUTE 授予 PUBLIC?我又进行了几次实验,发现如果用户为架构设置了任何默认授权,他们会通过 EXECUTE for PUBLIC 获得增强。但是,如果没有默认权限,则不会授予 PUBLIC 函数上的 EXECUTE。在我看来,这完全不合逻辑。有对此的解释吗?

【问题讨论】:

    标签: postgresql permissions database-administration postgresql-10


    【解决方案1】:

    我会尽量回答最后提出的问题:

    1. The documentation 说:

      ALTER DEFAULT PRIVILEGES
          [ FOR { ROLE | USER } target_role [, ...] ]
          [ IN SCHEMA schema_name [, ...] ]
          abbreviated_grant_or_revoke
      

      <em>target_role</em>

      当前角色所属的现有角色的名称。如果省略FOR ROLE,则假定当前角色。

      您总是为某个角色定义默认权限,也就是说,权限仅在该角色创建对象时适用。

    2. 就是这样。最好的办法是只允许一个角色在架构中创建对象。

    3. 任何授予的权限都会添加到现有权限中。

      所有函数都是使用PUBLICEXECUTE 权限创建的,我不相信你在 d) 中的结果。为此,您必须想出一个简单的可重现测试用例。

      改变这一点的唯一方法是拥有一个默认权限(不限于架构!)撤销EXECUTE 权限。

    【讨论】:

    • 感谢#1,我误解了这个概念。在 #2 中,只有一个角色非常不方便,因为这是典型的情况,即有多个开发人员在一个项目上工作,并且他们中的任何一个都应该能够添加列、更改结构等。
    • 至于#3,简单的可重现测试用例如下:create schema s; create function s.f() returns int as $$ begin return 1; end; $$ language plpgsql;。我的 Postgres version() 是 x86_64-pc-linux-gnu 上的 PostgreSQL 10.3 (Ubuntu 10.3-1.pgdg14.04+1),由 gcc (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4, 64- 编译位
    • 如果多个用户应该能够在一个模式中创建对象,请将他们全部置于对模式具有写入权限的角色中,并让他们在创建对象之前使用SET ROLE。我用s.f() 尝试了你的示例,PUBLIC 按预期具有EXECUTE 权限。
    • 我没有办法强迫他们这样做,他们是人,第二天就会忘记它。从他们的角色中撤销 INHERIT 将迫使他们使用 SET ROLE,但会带来很多其他的不便。关于 PUBLIC:may 数据库有什么问题?可能缺少一些配置参数?一些全局设置?
    • NOINHERIT 是正确的。关于权限问题:我想不出会导致这种情况的设置。也许您应该使用 complete 测试用例打开一个不同的问题,包括所有 CREATE ROLE 和其他命令。
    猜你喜欢
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2021-10-18
    • 2021-04-07
    相关资源
    最近更新 更多