19

目前我正在为我的应用程序使用 PostgreSQL。由于我试图将每个包含事务(即插入、更新、删除)的 SQL 都放在一个函数中,所以我偶然发现了这个问题:

是否可能只允许数据库用户调用函数和选择语句,而他不能调用包含事务的 SQL 语句?“调用函数”是指任何函数。不管它是否包含交易。

我已经尝试创建一个只能调用函数和 Select-Statements 的用户。但是在调用包含事务的函数时,我总是会出错。据我了解,如果 dbuser 调用使用插入、更新或删除语句的函数,则他需要写权限。

我错过了什么吗?这种情况真的不可能吗?安全方面,这真的很棒,因为您几乎可以从一开始就阻止 SQL 注入。

4

1 回答 1

33

没有“特权SELECT”。您所需要的只是EXECUTE功能的特权。相关函数可以运行SECURITY DEFINER以继承所有者的所有权限。要将可能的特权升级限制在最低限度,请让守护程序角色拥有相关功能,仅具有必要的特权 - 而不是超级用户!

食谱

作为超级用户...

创建一个非超级用户角色myuser

CREATE ROLE myuser PASSWORD ...;

创建一个组角色mygroup并使其成为myuser成员。

CREATE ROLE mygroup;
GRANT mygroup TO myuser;

您可能想像myuser以后一样添加更多用户。

根本不授予myuser.
仅将这些授予mygroup

  • GRANT CONNECT ON DATABASE mydb TO mygroup;
  • GRANT USAGE ON SCHEMA public TO mygroup;
  • GRANT EXECUTE ON FUNCTION foo() TO mygroup;

删除不应该拥有的所有特权。publicmyuser

REVOKE ALL ON ALL TABLES IN SCHEMA myschema FROM public;

可能还有更多。我引用手册:

PostgreSQL 将某些类型的对象的默认权限授予 PUBLIC. 默认情况下,PUBLIC 不会对表、列、模式或表空间授予任何权限。CONNECT对于其他类型,授予CREATE TEMP TABLEPUBLIC的默认权限如下:EXECUTE功能特权;和USAGE 语言的特权。当然,对象所有者REVOKE既可以默认也可以明确授予权限。(为了获得最大的安全性,请REVOKE在创建对象的同一事务中发出 ;然后没有其他用户可以使用该对象的窗口。)此外,可以使用ALTER DEFAULT PRIVILEGES命令更改这些初始默认权限设置。

创建守护程序角色拥有相关功能。

CREATE ROLE mydaemon;

仅授予执行这些函数所需的权限mydaemon,(包括EXECUTE ON FUNCTION允许调用另一个函数)。同样,您可以使用组角色来捆绑权限并将它们授予mydaemon

GRANT bundle1 TO mydaemon;

此外,您可以使用DEFAULT PRIVILEGES自动将未来对象的某些特权直接授予捆绑包或守护程序:

ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT ON TABLES    TO bundle1;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT USAGE  ON SEQUENCES TO bundle1;

这仅适用于执行它的角色。根据文档:

如果FOR ROLE省略,则假定当前角色。

还要涵盖架构中预先存在的对象(请参阅rob 的评论):

GRANT SELECT ON ALL TABLES    IN SCHEMA public TO bundle1;
GRANT USAGE  ON ALL SEQUENCES IN SCHEMA public TO bundle1;

制作mydaemon自己的相关功能。可能看起来像这样:

CREATE OR REPLACE FUNCTION foo()
  ...
SECURITY DEFINER SET search_path = myschema, pg_temp;

ALTER FUNCTION foo() OWNER TO mydaemon;
REVOKE EXECUTE ON FUNCTION foo() FROM public;
GRANT  EXECUTE ON FUNCTION foo() TO mydaemon;
GRANT  EXECUTE ON FUNCTION foo() TO mygroup;
-- possibly others ..

###Note
由于pgAdmin的当前版本 1.16.1 中的这个错误,必要的命令

REVOKE EXECUTE ON FUNCTION foo() FROM public;

is missing in the reverse engineered DDL script. Remember to add it, when recreating.
This bug is fixed in the current version pgAdmin 1.18.1.

于 2013-04-07T21:50:42.477 回答