0

I host the databases of several clients. For each database dbname, I currently have a dbnameusers role that I grant to the users of that client.

I would now like to have read only "sub roles".

I created a test database, a role usersro and a user ro (in role usersro).

Then I granted all privileges on the DB to usersro and revoked the CREATE privilege :

# grant all on database test to usersro;
GRANT
# revoke create on database test from usersro;
REVOKE

\l shows something that looks correct :

# \l
                            List of databases
    Name    |    Owner    | Encoding |   Collate   |    Ctype    |   Access privileges   
------------+-------------+----------+-------------+-------------+-----------------------
 test       | cat         | UTF8     | fr_FR.UTF-8 | fr_FR.UTF-8 | =Tc/cat              +
            |             |          |             |             | cat=CTc/cat          +
            |             |          |             |             | usersro=Tc/cat

But connecting as user ro, I can still create a table. I guess this comes from the PUBLIC role but I haven't found a way to see those default privileges.

My guess is that I should revoke all privileges from the PUBLIC role and recreate them in the usersrw role and only part of them in usersro (hence the need to know which are the default ones).

Is this the correct approach ? I have the feeling that PostgreSQL is quite permissive out of the box and that you have to break everything in order to build a multilevel access architecture.

2

3 Answers 3

3

To answer your direct question "if I revoke the CREATE privilege from the PUBLIC role, how do I see that ? "...

Use the following SQL (from this stackoverflow question) to get database-specific privileges for PUBLIC role:

   SELECT nspname,
       coalesce(nullif(role.name,''), 'PUBLIC') AS name,
       substring(
          CASE WHEN position('U' in split_part(split_part((','||array_to_string(nspacl,',')), ','||role.name||'=',2 ) ,'/',1)) > 0 THEN ', USAGE' ELSE '' END 
          || CASE WHEN position('C' in split_part(split_part((','||array_to_string(nspacl,',')), ','||role.name||'=',2 ) ,'/',1)) > 0 THEN ', CREATE' ELSE '' END 
       , 3,10000) AS privileges
FROM pg_namespace pn, (SELECT pg_roles.rolname AS name
   FROM pg_roles UNION ALL SELECT '' AS name) AS role
 WHERE (','||array_to_string(nspacl,',')) LIKE '%,'||role.name||'=%'
 AND nspowner > 1;

Result:

      nspname       |   name   |  privileges   
--------------------+----------+---------------
 pg_catalog         | postgres | USAGE, CREATE
 pg_catalog         | PUBLIC   | USAGE
 information_schema | postgres | USAGE, CREATE
 information_schema | PUBLIC   | USAGE
 test               | postgres | USAGE, CREATE
 public             | postgres | USAGE, CREATE
 **public             | PUBLIC   | USAGE, CREATE**

Now, run the following:

REVOKE CREATE ON SCHEMA public FROM PUBLIC;

Re-run the first SQL, and we get the following result-set:

   nspname       |   name   |  privileges   
--------------------+----------+---------------
 pg_catalog         | postgres | USAGE, CREATE
 pg_catalog         | PUBLIC   | USAGE
 information_schema | postgres | USAGE, CREATE
 information_schema | PUBLIC   | USAGE
 test               | postgres | USAGE, CREATE
 public             | postgres | USAGE, CREATE
 **public             | PUBLIC   | USAGE**

Compare the last lines from the 2 result-sets. You will see the missing CREATE privilege.

Don't forget to add the following back:

GRANT  CREATE ON SCHEMA public TO  PUBLIC;

To answer your other direct question : "Does that mean that the public role has all privileges granted (by default) ? "

'PUBLIC' is not an explicit role. This is what tripped me when I started Postgres.

Run the following command to confirm this - PUBLIC is absent from this result set:

select * from pg_roles;

Erwin Brandstetter has given a great explanation of PUBLIC role and another even more detailed explanation of PUBLIC role here .

My own notes - just paraphrasing the Postgres documentation on GRANT...

Any particular role will have the sum of following privileges:

  1. privileges granted directly to it +
  2. privileges granted to any role it is presently a member of +
  3. privileges granted to PUBLIC.

This official Postgres post does a great job of explaining how to setup rights: Managing Rights in Postgres

1
  • Perfect, thank you for the provided links.
    – JC Boggio
    Commented Jan 31, 2018 at 23:36
2

Just to clarify,

I guess this comes from the PUBLIC role but I haven't found a way to see those default privileges.

You are right, and you can see PUBLIC privileges in your \l output, where your first item of aclitem[] is =Tc/cat and actually it is your PUBLIC privileges according to documentation (on the bottom):

=xxxx/username -- privileges granted to PUBLIC by username

And one more moment, do not confuse, PUBLIC privileges and default privileges is something different. Where the first one is privileges that actually granted to all users (yes, it could be done by default if you just created your database) which can be found using different queries for different object types (such as @Sanora provided). And second one is privileges that will be applied to objects created in the future which you can find in pg_default_acl.

1

The CREATE privilege on a database controls the ability to create schemas. To control the ability to create tables, you need to control the CREATE privilege on that SCHEMA, not on the DATABASE containing the schema.

REVOKE CREATE on SCHEMA public FROM usersro ;
3
  • Thanks, I overlooked this. But after revoking that privilege (and reconnecting), user ro is still able to create tables. Should I see this revocation in \dn (because I don't) ?
    – JC Boggio
    Commented Jan 29, 2018 at 16:24
  • You probably have to revoke it from the role public as well, since the public schema defaults to having public access. Or drop the public schema and explicitly create what you want instead. Use \dn+ to see schema privileges.
    – jjanes
    Commented Jan 29, 2018 at 20:15
  • Does that mean that the public role has all privileges granted (by default) ? And if I revoke the CREATE privilege from the PUBLIC role, how do I see that ? This is my question.
    – JC Boggio
    Commented Jan 30, 2018 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.