postgres:如何允许同一用户创建索引但不允许表更改或表删除?

orm*_*orm 9 postgresql permissions role

我正在设置一个 postgres 服务器,它将是一个(主要是)只读工作负载。

我想允许我自己和同事按照我们认为合适的方式创建/删除索引,而不允许我们删除表或改变表。

我花了一些时间阅读授权/撤销文档以及角色文档页面,但似乎表所有者角色获得了这两种权力。

我发现的一件事是,据说,在表空间上授予创建允许创建索引,但它不起作用(注意,我没有创建任何其他表空间)。

具体来说,我试过:

mydb=# grant create on tablespace pg_default to bob;
GRANT
Run Code Online (Sandbox Code Playgroud)

...然后切换到鲍勃:

mydb=> create index on foo(a);
ERROR:  must be owner of relation foo
Run Code Online (Sandbox Code Playgroud)

我也尝试让 bob 成为所有者,但是 bob 获得了删除表的权利,而且似乎无法撤销该特权。所以我要么两者兼而有之,要么什么都不做。

有任何想法吗?

Cra*_*ger 9

在 SQL 级别你不能,因为所有这些任务都由表所有权管理。

CREATE上表空间是必需的,但没有足够的创建一个表的索引和存储在该表的索引。如果您没有CREATE要放置索引的表空间的权限,那么您就不能使用CREATE INDEX该索引。然而,拥有这项权利还不够。否则,任何人都可以在任何表上创建索引,前提是他们有权在任何表空间中创建任何内容,而我们不希望那样。索引具有性能成本,在创建过程中需要大量锁定,而且最重要的是,表达式索引可能会通过恶意函数或运算符泄漏有关表的数据。因此,您必须拥有要在其上创建索引的表。

INDEX对表的单独权限的支持可以添加到 PostgreSQL,但尚未添加,如果提交可能不会被接受。现在,你不得不拥有这张桌子。

您可以编写一个 C 扩展来安装ProcessUtility_hook检查正在执行的操作和当前用户身份,然后根据情况拒绝或允许它们。您可以在 BDR 项目源代码的文件中找到ProcessUtility_hook在内部contrib/sepgsql和外部使用的示例bdr_commandfilter.c。您必须编译扩展,将其安装到文件系统中,然后将其添加到文件系统中以shared_preload_libraries进行安装,因此您需要对服务器具有完整的文件系统级别访问权限,并且通常是 root 访问权限。

更实用的方法是使用SECURITY DEFINER函数作为包装器。编写一个 PL/PgSQL 函数,该函数作为表所有者运行,并接受要索引的表、要索引的列等作为参数。让它创建CREATE INDEX表达式,format(...)然后将其传递给EXECUTE. 难道不是允许用户通过任意的SQL表达式作为参数,或者你基本上让他们通过SQL注入的完全访问权限。想要多列?你必须接受colname text[]一个论点和quote_ident每个论点。等等。搜索“动态 SQL plpgsql”以了解有关此方法的更多信息。

  • 让我补充一点,对于大/繁忙的表,使用 `CONCURRENTLY` 创建索引通常是避免阻塞的方法。不幸的是,这在函数中是不可能的。 (2认同)