如何以正确的方式对 Postgres 中的函数使用默认模式权限?
How to use default schema privileges on functions in Postgres in right way?
我很难理解默认模式权限在 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) 我们看到它授予 PUBLIC 在 func1 上执行的权限。没关系,文档说这是默认的。
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
妈的,没有!
总而言之:默认权限仅在用户下创建对象时有效(显式)设置默认权限并且不有效在被授予角色并设置默认权限的用户下。
现在提问:
上面的事实是否在文档中的某个地方提到但我没有找到?
为什么这么不方便?可能是我误用了吗?有没有办法在模式中设置默认权限,该权限适用于具有某些授予角色的每个用户?对于所有(现有和未来)用户?
PUBLIC完全不清楚情况。为什么不在 d) 中将 EXECUTE 授予 PUBLIC?我进行了更多的实验,发现如果用户为模式设置了 any 默认授权,他们会通过 EXECUTE for [=79= augmented ].但是,如果没有默认权限,则不会在函数上授予 PUBLIC EXECUTE。在我看来这完全不合逻辑。对此有解释吗?
我会尽量回答最后提出的问题:
-
ALTER DEFAULT PRIVILEGES
[ FOR { ROLE | USER } target_role [, ...] ]
[ IN SCHEMA schema_name [, ...] ]
abbreviated_grant_or_revoke
<em>target_role</em>
The name of an existing role of which the current role is a member. If FOR ROLE
is omitted, the current role is assumed.
您始终为特定角色定义默认权限,也就是说,权限仅在该角色创建对象时适用。
就是这样。最好的办法是只允许一个角色在模式中创建对象。
任何授予的权限都会添加到现有权限中。
所有函数都是使用 PUBLIC
的 EXECUTE
权限创建的,我不相信你在 d) 中的结果。您必须为此提出一个简单的可重现测试用例。
更改它的唯一方法是拥有默认权限(不限于架构!),撤销 EXECUTE
权限。
我很难理解默认模式权限在 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) 我们看到它授予 PUBLIC 在 func1 上执行的权限。没关系,文档说这是默认的。 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
妈的,没有!
总而言之:默认权限仅在用户下创建对象时有效(显式)设置默认权限并且不有效在被授予角色并设置默认权限的用户下。
现在提问:
上面的事实是否在文档中的某个地方提到但我没有找到?
为什么这么不方便?可能是我误用了吗?有没有办法在模式中设置默认权限,该权限适用于具有某些授予角色的每个用户?对于所有(现有和未来)用户?
PUBLIC完全不清楚情况。为什么不在 d) 中将 EXECUTE 授予 PUBLIC?我进行了更多的实验,发现如果用户为模式设置了 any 默认授权,他们会通过 EXECUTE for [=79= augmented ].但是,如果没有默认权限,则不会在函数上授予 PUBLIC EXECUTE。在我看来这完全不合逻辑。对此有解释吗?
我会尽量回答最后提出的问题:
-
ALTER DEFAULT PRIVILEGES [ FOR { ROLE | USER } target_role [, ...] ] [ IN SCHEMA schema_name [, ...] ] abbreviated_grant_or_revoke
<em>target_role</em>
The name of an existing role of which the current role is a member. If
FOR ROLE
is omitted, the current role is assumed.您始终为特定角色定义默认权限,也就是说,权限仅在该角色创建对象时适用。
就是这样。最好的办法是只允许一个角色在模式中创建对象。
任何授予的权限都会添加到现有权限中。
所有函数都是使用
PUBLIC
的EXECUTE
权限创建的,我不相信你在 d) 中的结果。您必须为此提出一个简单的可重现测试用例。更改它的唯一方法是拥有默认权限(不限于架构!),撤销
EXECUTE
权限。