Problem

How do i create a read-only user ? The user ( non-superuser ) with connect permission on the database is able to create / drop object on the database , how do we restrict them from doing so ?

Solution

By default any user that is allowed to connect to the database can create object in the public schema , you can use the below query to check who can connect under the column "rolcanlogin"

SELECT * FROM pg_roles;

So if you wish users to avoid creating a table , you will need to revoke first permission from public through this command below after connecting to the database.

REVOKE ALL ON schema public FROM public;

This will make only gpadmin ( superuser ) create objects under the database in question , but if you wish other user to create object in it as well , you would have to grant them separatly / manually like

GRANT ALL ON schema public TO ;

Example

Now lets take a example to understand the scenario better.

First lets check who can create object under a database in the public schema .

gpadmin=# select * from pg_namespace where nspname='public';
 nspname | nspowner |                     nspacl
---------+----------+------------------------------------------------
 public  |       10 | {gpadmin=UC/gpadmin,a2=UC/gpadmin,=UC/gpadmin}
(1 row)

from the above example the column "nspacl" shows a entry of "=UC/gpadmin" , note there is no value before the last "="" sign , which means any one can create objects under this public schema.

Revoke the grant and verifying it , shows now no one can create object under it

gpadmin=# REVOKE ALL ON schema public FROM public;
REVOKE
Time: 299.719 ms
gpadmin=# select * from pg_namespace where nspname='public';
 nspname | nspowner |               nspacl
---------+----------+------------------------------------
 public  |       10 | {gpadmin=UC/gpadmin,a2=UC/gpadmin}
(1 row)

Time: 23.899 ms
gpadmin=#

Connecting as non-superuser a1 and attempting to create a table , throws out error like below.

gpadmin:Fullrack@mdw $ psql -U a1
Password for user a1:
Timing is on.
Pager usage is off.
psql (8.2.15)
Type "help" for help.

gpadmin=> create table test1111 as select * from pg_class;
NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'relname' as the Greenplum Database data distribution key for this table.
HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR:  no schema has been selected to create in
gpadmin=>

As gpadmin ( superuser ) , grant specfic users/role to create object under the schema

gpadmin=# GRANT ALL ON schema public TO a1;
GRANT
Time: 125.443 ms
gpadmin=# select * from pg_namespace where nspname='public';
 nspname | nspowner |                      nspacl
---------+----------+--------------------------------------------------
 public  |       10 | {gpadmin=UC/gpadmin,a2=UC/gpadmin,a1=UC/gpadmin}
(1 row)

Time: 22.500 ms
gpadmin=# \q
gpadmin:Fullrack@mdw $ psql -U a1
Password for user a1:
Timing is on.
Pager usage is off.
psql (8.2.15)
Type "help" for help.

gpadmin=> create table test1111 as select * from pg_class;
NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'relname' as the Greenplum Database data distribution key for this table.
HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
SELECT 508
Time: 3921.078 ms