Allow postgres user to only list his own database

匿名 (未验证) 提交于 2019-12-03 02:59:02

问题:

I'm using a postgresql server and I want to forbid my users to see what other databases are on the same server.

Essentially a \l should only list his own database.

I'm pretty sure that there is a right which I need to revoke from the user but I can't find it in the docs.

回答1:

This seems to work but might have unforeseen consequences. It requires tinkering with system catalogues, which isn't really a good idea!

First off, you have to permit superusers to update system catalogues by adding this to your postgresql config:

allow_system_table_mods = on 

and restart.

Now, you can use DDL statements to modify system catalogues (you should be afraid). Connect to one of the user databases (a test one would be a good idea) and:

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; 

You should now find that if you connect to that database as a low-priv user, the \l command will just list the databases that that user can connect to.

The problem is you now need to guess which database the users connect to initially to fetch their database list from. If they connect to their own database initially, then you're probably done at this point. If they connect to postgres or template1 first, then you need to make this change on that database instead.

It seems to me that this should work, since the pg_database catalog is referred to by postgres backends directly by oid, rather than by name, so moving it out of the way and changing which rows are shown in it should be invisible to them. In particular, you can't stop the server distinguishing to the user between a database not existing and them not having connection privilege.

I'm not going to make any promises that this sort of change doesn't screw something else up down the line. If it breaks, you get to keep the pieces.

You probably want to make this change in a template database, and create user databases from that in future, and deactivate the allow_system_table_mods setting when you're done (which requires a server restart, remember).

Also, I tested this on 9.0: it seems to me it should work on some earlier versions too, caveat emptor.



回答2:

There's no such setting in pgsql. There are settings to prevent users from connecting to databases that they shouldn't (grant / revoke connect). Being able to see there's a database is no big deal. Being able to connect / have edit rights etc. is.



回答3:

I would imagine this might have negative repercussions for the user, such as not being able to connect to the database since the system does not have access to the sytem tables, not sure though. But as far as figuring out what table to revoke - this a good general way to see what the psql meta commands are doing:

To see what \l is doing you can also use the -E flag from the command line with psql.

~$ 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; ************************** 

So if the user does not have access to pg_database they will not be able to use the \l command.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!