允许postgres用户只列出自己的数据库

时间:2011-02-07 01:33:45

标签: postgresql

我正在使用postgresql服务器,我想禁止我的用户查看同一服务器上的其他数据库。

基本上\l应该只列出他自己的数据库。

我很确定我需要撤消用户的权利,但我无法在文档中找到它。

4 个答案:

答案 0 :(得分:4)

这似乎有效但可能会产生无法预料的后果。它需要修改系统目录,这不是一个好主意!

首先,您必须允许超级用户通过将其添加到您的postgresql配置来更新系统目录:

allow_system_table_mods = on

然后重新启动。

现在,您可以使用DDL语句来修改系统目录(您应该害怕)。连接到其中一个用户数据库(测试一个是个好主意)和:

alter table pg_catalog.pg_database rename to pg_database_catalog;
create view pg_catalog.pg_database as
  select oid, 1262::oid as tableoid, pg_database_catalog.*
  from pg_catalog.pg_database_catalog
  where has_database_privilege(pg_database_catalog.oid, 'connect');    
grant select on pg_catalog.pg_database to public;

您现在应该发现,如果您以低权限用户身份连接到那个数据库,\l命令将只列出该用户可以连接的数据库。

问题是你现在需要猜测用户最初连接哪个数据库来从中获取数据库列表。如果他们最初连接到他们自己的数据库,那么你可能已经完成了这一点。如果他们首先连接到postgrestemplate1,那么您需要在该数据库上进行此更改。

在我看来,这应该有效,因为pg_database目录由postgres后端直接由oid引用,而不是名称,因此将其移开并更改其中显示的行对他们来说应该是看不见的。特别是,您无法阻止服务器在不存在的数据库与没有连接权限的数据库之间区分用户。

我不会做出任何承诺,这种改变不会阻碍其他事情。如果它坏了,你就可以保留它们。

您可能希望在模板数据库中进行此更改,并在将来创建用户数据库,并在完成后停用allow_system_table_mods设置(需要重新启动服务器,请记住)。

另外,我在9.0上对此进行了测试:在我看来它也应该适用于某些早期版本,但需要注意。

答案 1 :(得分:1)

pgsql中没有这样的设置。有一些设置可以防止用户连接到他们不应该访问的数据库(授予/撤消连接)。能够看到有一个数据库没什么大不了的。能够连接/拥有编辑权等是。

答案 2 :(得分:1)

我认为这可能会对用户产生负面影响,例如无法连接到数据库,因为系统无法访问系统表,但不确定。但是要找出要撤销的表 - 这是查看psql元命令正在做什么的一般方法:

要查看\l正在做什么,您还可以使用psql命令行中的-E标志。

~$ psql -E -c '\l'
********* QUERY **********
SELECT d.datname as "Name",
       pg_catalog.pg_get_userbyid(d.datdba) as "Owner",
       pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding",
       d.datcollate as "Collation",
       d.datctype as "Ctype",
       pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges"
FROM pg_catalog.pg_database d
ORDER BY 1;
**************************

因此,如果用户无权访问pg_database,他们将无法使用\ l命令。

答案 3 :(得分:0)

@araqnid的answer above似乎是一个解决方法,除了一个问题:select oid, 1262::oid as tableoid, pg_database_catalog.*将在结果中将oid列定义为两次 ,一次是通过select oid明确给出的,一次是从pg_database_catalog.*中提取的。至少在Postgresql 12上,create view pg_catalog.pg_database会抱怨列oid被定义了两次,并将中止。

因此,更正后的代码为:

alter table pg_catalog.pg_database rename to pg_database_catalog;
create view pg_catalog.pg_database as
  select 1262::oid as tableoid, pg_database_catalog.*
  from pg_catalog.pg_database_catalog
  where has_database_privilege(pg_database_catalog.oid, 'connect');    
grant select on pg_catalog.pg_database to public;

有关其他所有信息,请参考original answer

如果有人可以确认我在这里的发现是正确的(或反驳他们),我将感到非常高兴。

相关问题