I installed PostgreSQL 9 database (migration from Oracle10g) and I am realy confused by user/role management. When I create new user using SQL command like CREATE USER or CREATE ROLE, or by Navicat tool, created user can see all databases! He realy can connect them! Although he can't select any data from table, he can see table objects and sequences and so on. I was trying revoke connect privilegia but no effect. I was expected the new user has no privilegia and cant see anything. I really don't know why he can.
From http://www.postgresql.org/docs/9.2/static/sql-grant.html#SQL-GRANT-DESCRIPTION-OBJECTS (emphasis mine):
PostgreSQL grants default privileges on some types of objects to PUBLIC. No privileges are granted to PUBLIC by default on tables, columns, schemas or tablespaces. For other types, the default privileges granted to PUBLIC are as follows: CONNECT and CREATE TEMP TABLE for databases; EXECUTE privilege for functions; and USAGE privilege for languages. The object owner can, of course, REVOKE both default and expressly granted privileges. (For maximum security, issue the REVOKE in the same transaction that creates the object; then there is no window in which another user can use the object.) Also, these initial default privilege settings can be changed using the ALTER DEFAULT PRIVILEGES command.
In order to remove all privileges (including CONNECT) for all unspecified users on a database, use:
REVOKE ALL PRIVILEGES ON DATABASE <database> FROM public;
See also:
PostgreSQL: View database connect permissions
http://wiki.postgresql.org/wiki/Shared_Database_Hosting
You probably also need to modify the pg_hba.conf file. By default, a local installation doesn't do authorization checks.
Related
I have multiple databases and each of them have multiple schemas.
I have a set of apps that connect to these databases. Each app has it own user and, depending on their function, the apps can:
read / write all schemas and tables of a specific db, set functions/notifications
read only all schemas and tables of a specific db
The schemas and tables can be created at any time, so the permissions need to be set with ALTER DEFAULT.
My understanding is that the ALTER DEFAULT has to be done by the user that will create the future tables. Is that correct?
Since I can have scenarios where User 1 can RO db A, but RW db B, while User 2 can only RO db B, etc.. using roles doesn't seem to be of any help here.
So I'm a bit confused how to set that up.
Then comes the next complication:
I can assign permissions as either SELECT (RO), or SELECT, INSERT, UPDATE, DELETE (RW), but:
what about sequences? I don't want a RW user to be able to alter the sequences, but they need to be able to use them
then how does it work with functions? the RW users need to be able to set/update their own functions
Any example of this setup would be greatly appreciated because going through the doc didn't help me much and most of the questions / answers on SO seems to be very similar yet never exactly the same, so it's quite confusing :)
Edit, following 'a_horse_with_no_name''s suggestion in the comments, I did this:
here is my init.sql:
CREATE DATABASE accounts;
CREATE DATABASE analysis;
CREATE DATABASE exchange;
GRANT CONNECT ON DATABASE exchange TO capture, analyzer, sunny, viewer;
GRANT CONNECT ON DATABASE analysis TO analyzer, sunny, viewer;
GRANT CONNECT ON DATABASE accounts TO sunny;
then I log in as admin to db exchange and do:
GRANT pg_write_all_data TO capture;
GRANT pg_read_all_data TO analyzer, sunny, viewer;
and I create a table called instruments there
then I log in as capture to to db exchange and do an insert, and I get:
42501: permission denied for table instruments
so using the capture user on the exchange db, I should have the pg_write_all_data property; why do I get the error?
It looks like I have to grant usage of instruments to capture.. which defeats the purpose of the pg_write_all_data. If I do the grant, then it works. So it looks like adding the role doesn't work.
Since your users shall have different permissions in different databases, define read-only and read-write roles for each database.
For example, db1_ro has read-only permissions in db1, and db2_rw has read-write permissions in db2. Then you can grant them both to a user, and the user will have different permissions in different databases.
Using a sequence typically means to call nextval(). So you should give that user the USAGE privilege. To use setval(), the user would need UPDATE. Nobody except the owner can ALTER an object anyway.
Functions cannot be set or updated, only executed, for which there is the EXECUTE privilege, which is granted to PUBLIC by default.
I have a database called funnycode. I also have a user called funnycode_user.
How do I grant default privileges to funnycode_user so that the user can:
Create a database under the name funnycode.
User can connect to any future database with the name funnycode, but not other databases.
User can select from all tables and has access to all sequences on any future database under the name funnycode but not other databases.
Is this possible in Postgres? If so, how? I read the documentation here, but I don't see how this:
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT INSERT ON TABLES TO funnycode_user;
Is tied to a specific database, in my case that would be the funnycode database?
The user that creates a database automatically owns that database (unless a different owner is specified) and thus automatically has all privileges on the database. You don't need any additional grants to enable that user creating and using tables in the database.
So if you give funnycode_user the create database privilege, he can create any database he wants, not just funnycode. There is no way to prevent that.
Every new database that is created automatically grants the connect privilege to the role public. If you don't want funnycode_user to connect to other database, you need to revoke that privilege from the public role for every database.
Another way of limiting access to a specific database for a specific user, is through pg_hba.conf
You would need an entry like that:
# TYPE DATABASE USER ADDRESS METHOD
host funnycode funnycode_user 0.0.0.0/0 md5
The entry 0.0.0.0/0 means that funnycode_user can connect from any IP address. Even if funnycode_user created other databases, he wouldn't be able to connect to them.
I think the better (cleaner) way is to not give that user the privilege to create database. Just create that database once, make funnycode_user the owner and that's it.
E.g. as the superuser run:
create user funnycode_user password 'VerySecret';
create database funnycode owner = funnycode_user;
You only need to do that once (or after funnycode_user decides to drop the database) and you don't need to give funnycode_user the privilege to create databases.
In postgres, you can GRANT or REVOKE privileges like:
REVOKE ALL ON SCHEMA public FROM PUBLIC;
GRANT USAGE ON SCHEMA public TO <myuser>;
My question; If each database has a schema PUBLIC, then are you revoking or granting for this all databases? If so, what if you only want to alter the schema permissions of one database?
The context: I want to GRANT SELECT, INSERT, DELETE to one user for only one scheme in one database. I want to do this without being connected to the DB. Or is the way to do this simply by also handling CONNECT permissions to actual databases. So if they can only connect to one database, it doesn't matter if you say "all" PUBLIC schemas?
There are a lot of questions here; I'll try to restore order.
It is a good idea to revoke CREATE from the public schema in all databases.
But you absolutely have to connect to each database in turn to do that.
A beautiful solution might be that you do it on database template1. Then every new database will automatically be set up correctly, since CREATE DATABASE copies the template database.
To give users permission to a schema in all databases, you again have to connect to all databases in turn.
It is also a good idea to REVOKE ALL on all databases from PUBLIC and grant the CONNECT privilege selectively.
This time, you can do it without connecting to each database, because databases are shared objects — the pg_database catalog is accessible from each database.
I want create users that only can execute functions from one database. Not view source functions, procedures, select, etc of any database.
Thanks.
This should do it:
Allow the user to connect to only the correct database, either with permissions on the database object (you have to REVOKE the CONNECT privilege granted to PUBLIC by default first) or with suitable entries in pg_hba.conf.
In the one database where the user can connect, it should have USAGE privilege on the schemas that contain the functions.
Create functions with SECURITY INVOKER that belong to a user that has the rights to access the required objects.
REVOKE EXECUTE on all functions from PUBLIC and GRANT it to the user as required.
There is no supported way in PostgreSQL to keep a user that can log on from seeing the source code of functions. You can try to REVOKE SELECT ON pg_proc FROM PUBLIC, but don't be surprised if you get problems with client programs like pgAdmin or psql.
I want to create a postgres user that can access only one database on the postgres server at all.
Currently my flow is:
create database database1;
create user user1 with password 'pass';
grant all privileges on database database1 to user1;
but user1 can still see a list of dbs, users, tables etc. Is there a way to prevent that user from seeing that info? The user needs to be able to write to and read from that db.
Thanks a lot.
Each user can see other databases and roles listed, but should not be able to see tables in other databases, ever.
If you revoke CONNECT privilege on all databases except the allotted one, the user will not be able to access the contents of other databases.
Roles and database names are global, and not readily blockable. You can try Frank Heikens suggestion of selective revocations on the system tables, but you take risks to do that. PostgreSQL developers on the usenet mailing lists have discouraged tampering with access to the system catalogs.
Psql, among other tools, assumes they will be available and functions poorly without them.
Why is knowing the names of other databases and roles so bad?
REVOKE the SELECT permissions on the information_schema and some sections in the system catalog.
By default any objects you create are created in the public schema. Also, any users that you create have CREATE and USAGE privileges on the public schema. You should revoke CREATE and USAGE to the public schema for this user, or you should change the default access level. You'll also need to move the database to which this user has access into the user's schema, or a schema accessible to the user. See DDL Schemas in the Postgres manual.