Limiting the scope of schemas when GRANT/REVOKE'ing in Postgres - postgresql

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.

Related

very confused about permissions in postgres

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.

Posgtresql pgadmin how to prevent access to schema

I'm new on PostgreSQL. I created a user for to use a specific schema. I have done a table but I can't prevent on schema. I don't want to show all schema to the user. How can I prevent to access the schema?
Grant and Revoke to grant access and privileges on your database, including schema.

How to do one user postgresql with privileges only execute functions

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.

Why new user in PostgreSQL can connect to all databases?

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.

How to prevent a user from being able to see other databases and the tables from other databases?

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.