即使在运行 GRANT ALL to role 之后,使用 SECURITY DEFINER 调用函数时权限被拒绝

Posted

技术标签:

【中文标题】即使在运行 GRANT ALL to role 之后,使用 SECURITY DEFINER 调用函数时权限被拒绝【英文标题】:Permission denied when calling a function when using SECURITY DEFINER even after GRANT ALL to role has been run 【发布时间】:2019-09-07 22:12:07 【问题描述】:

运行下面的 SQL 我遇到了权限问题。

[42501] 错误:模式 myschema 的权限被拒绝其中:PL/pgSQL 函数 >myschema.test_func() SQL 语句的第 8 行

我需要授予什么权限才能允许 SECURITY DEFINER 选择/执行功能。所有权限似乎都不起作用。

看着https://www.postgresql.org/docs/current/sql-grant.html,我看不出还有什么可以让我完成这项工作的。

我正在使用 Postgresql 11。显然,如果我让 myrole 成为超级用户,它就可以正常工作。即使将赠款放在最后也会产生相同的错误。


编辑:

我没有很好地解释。问题不是创建函数我在调用以下行时遇到问题: SELECT myschema.test_func_2('foo', 'bar') INTO l_table_result;

函数的创建工作正常,只有当我运行select myschema.test_func(); 时才会得到SQL 错误。

我看不到 myrole 需要什么其他权限才能调用另一个函数。

CREATE ROLE myrole WITH NOLOGIN;

CREATE SCHEMA IF NOT EXISTS myschema;

GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA myschema TO myrole ;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA myschema TO myrole ;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA myschema TO myrole ;


CREATE OR REPLACE
FUNCTION myschema.test_func()
RETURNS BOOLEAN
    SECURITY DEFINER
    LANGUAGE plpgsql
AS $$
DECLARE
    l_table_result BOOLEAN;
BEGIN

    RAISE LOG 'Will Get This Far ... ';

    SELECT myschema.test_func_2('foo', 'bar') INTO l_table_result;

    RAISE LOG 'But Not This Far';

    RETURN TRUE;

END;
$$;

/* OWNERSHIP AND PERMISSIONS*/
ALTER FUNCTION myschema.test_func OWNER to myrole;



CREATE OR REPLACE
FUNCTION myschema.test_func_2(
                                p_foo VARCHAR(10),
                                p_bar VARCHAR(10)
)
RETURNS BOOLEAN
    SECURITY DEFINER
    LANGUAGE plpgsql
AS $$
BEGIN

    RETURN TRUE;

END;
$$;

/* OWNERSHIP AND PERMISSIONS*/
ALTER FUNCTION myschema.test_func_2(VARCHAR, VARCHAR) OWNER to myrole;




select myschema.test_func();

【问题讨论】:

【参考方案1】:

您需要架构上的CREATE 权限,才能在该架构中创建新对象。 因此GRANT ALL ON SCHEMA myschema to myrole; 授予myrole 创建此功能的权利。此GRANT 的文档也在您链接的页面上。

不管怎样,你刚刚在你的脚本中创建了这个用户,我猜你当时没有和这个用户连接到数据库,所以你可以在创建函数之前添加SET ROLE myrole;。你可以在之后杀死ALTER FUNCTION,尽管有时你可能想保留它,这是你的决定。

最后一句话:如果您尝试使用 SECURITY DEFINERALTER FUNCTION 的组合来获得一个以真正发出 CREATE FUNCTION 的用户身份执行的函数(如果您故意不这样做,可能会发生什么) SET ROLE),这是行不通的。如here 所述,权限检查是针对拥有该功能的用户,而不是创建它的用户。

编辑:从评论中回答,确实解决了(编辑的)问题

尽管创建是可能的(也许只是您通过ALTER FUNCTION 选择的方式,而不是通过CREATE FUNCTION 和用户myrole)并且您可以调用该函数,在您作为用户myrole 和函数myschema.test_func_2的查找由他执行,因此myrole至少需要架构上的USAGE权限。

【讨论】:

感谢问题不是创建函数问题是当函数运行时(即使通过超级用户帐户),SQL 错误显示与此行 SELECT myschema.test_func_2('foo', 'bar') INTO l_table_result; 运行。函数创建得很好,这是我遇到问题的执行。 由于指定了SECURITY DEFINER,因此通过超级用户调用该函数应该没有什么不同,因此预计您在两种设置中都会出现错误(或没有错误)。尽管创建是可能的(也许只是您通过ALTER FUNCTION 而不是通过CREATE FUNCTION 和用户myrole 选择的方式)并且您可以调用该函数,在函数内部您作为用户myrole 和查找函数myschema.test_func_2 由他执行,因此myrole 至少需要架构上的USAGE 权限。您是否尝试过授予它? GRANT USAGE 已对其进行排序。我在想这是一个功能级别的问题,但它是一个模式级别。非常感谢。

以上是关于即使在运行 GRANT ALL to role 之后,使用 SECURITY DEFINER 调用函数时权限被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

Security10:Grant object Permission to DB Role or User

MySQL 用户管理之 GRANT 授权

grant all privileges on *.* to 'root'@'%' identified by '123456' with grant

停止 mySQL GRANT ALL,而不仅仅是擦除

Mysql grant all privileges on ...不生效解决方案

grant all privileges on *.* to root@"%" identified by ".";报错问题