Revoke privilege "create table" from public schema but not from custom made schema - postgresql-9.4

I am trying to create an account that is only able to use "SELECT" within the mydb_schema.
I am able to revoke the creation of a tables in public schema in my database (mydb) from a specific role but I am not able to revoke the creation of tables within the schema (mydb_schema) the role (user_role) is assigned to.
Can someone assist? What am I missing?
Below are the commands I used as user postgres and as the owner of the schema. At the end I also altered the postgres account by using the noinherit just as a desperate test. No result.
\c mydb
mydb=# create role user_account
mydb=# alter role user_account login noinherit;
mydb=# alter role user_account set search_path = 'mydb_schema';
##Up until this point I don't have SELECT pivileges but I can create a table within mydb_schema only and not in public.
mydb=# grant select on all tables in schema mydb_schema to user_account;
mydb=# revoke CREATE on SCHEMA public from public;
These are my databases:
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description
--------------------------------------------------------------------------
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 6820 kB | pg_default | default administrative connection database
mydb | seeker | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/seeker +| 3465 MB | pg_default |
seeker=CTc/seeker
These are my schemas:
List of schemas
Name | Owner | Access privileges | Description
----------------+----------+----------------------+------------------------
public | postgres | postgres=UC/postgres | standard public schema
mydb_schema | seeker | seeker=UC/seeker +|
| | =UC/seeker |

Found the solution here in dba.stackexchange
alter role servers_admin set default_transaction_read_only = 'ON';

Related

Postgresql: why can't you drop a role with privileges that does not own any ressource?

I'm confused by the nomenclature around roles and privileges with postgresql.
Given a stock postgresql install, if I do this:
postgres=# create database foo;
CREATE DATABASE
Now, there is a database.
postgres=# create role bar;
CREATE ROLE
Now, there is a user. I can delete it:
postgres=# drop role bar;
DROP ROLE
And it's gone, and I can recreate it again.
postgres=# create role bar;
CREATE ROLE
postgres=# grant all privileges on database foo to bar;
GRANT
So this role does not own anything. (Since there is nothing to own.)
The database existed before the role. The way I understand it, it's an independent entity.
And you've just "GRANT"-ed the role "bar" to do some things with this database.
Plain english. Pretty logical.
Then you changed your mind, and remove the role:
postgres=# drop role bar;
ERROR: role "bar" cannot be dropped because some objects depend on it
DETAIL: privileges for database foo
"What the what ? What do you mean 'some objects depend on it' ? THERE IS NO OBJECT YET !!!", you ask.
As I understand it, the answer lies here:
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
--------------+----------+----------+-------------+-------------+---------------------------
foo | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres +
| | | | | postgres=CTc/postgres +
| | | | | bar=CTc/postgres
So the "ressource" that depends on you is the "privilege" itself.
So you can remove the privilege, and after that, drop the role:
postgres=# revoke all on database foo from bar;
REVOKE
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
--------------+----------+----------+-------------+-------------+---------------------------
foo | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres +
| | | | | postgres=CTc/postgres
postgres=# drop user bar;
DROP ROLE
So my question is: why ? In this situation, something is preventing postgresql from doing the (obvious / expected / arguably less confusing) thing, and "cascading" the dropping of "privileges", too.
What could it be ?
It might simply be a confusing error message over a n00b issue, but I suspect something more fundamental...

Postgres - Can not 'SELECT' from tables even though my role/user has been granted 'READ'

I have an admin role/user and a developers role on postgres. The developers role enherits attributes from a 'readaccess' role which I created for convenience in the future. If I run \du I get:
Role name | Attributes | Member of
-----------------+------------------------------------------------------------+-------------------
developers | | {readaccess}
rds_replication | Cannot login | {}
rds_superuser | Cannot login | {rds_replication}
rdsadmin | Superuser, Create role, Create DB, Replication, Bypass RLS+| {}
| Password valid until infinity |
rdsrepladmin | No inheritance, Cannot login, Replication | {}
readaccess | Cannot login +| {}
| Password valid until infinity |
admin | Create role, Create DB +| {rds_superuser}
| Password valid until infinity |
I have granted read access to my developers account and my readaccess account via the following
GRANT SELECT ON ALL TABLES IN SCHEMA mySchema TO developers;
ALTER DEFAULT PRIVILEGES IN SCHEMA mySchema GRANT SELECT ON TABLES TO developers;
GRANT SELECT ON ALL TABLES IN SCHEMA mySchema TO readaccess;
ALTER DEFAULT PRIVILEGES IN SCHEMA mySchema GRANT SELECT ON TABLES TO readaccess;
If I run the command \z on one of my tables in mySchema
myDb=> \z mySchema.myTable;
Access privileges
Schema | Name | Type | Access privileges | Column privileges | Policies
---------+------------------------+-------+-------------------------+-------------------+----------
mySchema| myTable | table | admin=arwdDxt/admin+ | |
| | | developers=r/admin | |
(1 row)
However I can not run selects -- it says I have no permissions
myDB=> select * from mySchema.myTable;
ERROR: permission denied for schema mySchema
LINE 1: select * from mySchema.myTable;
Can anyone help out?
In addition to granting access to the tables, you must also grant access to the schema that contains them:
GRANT USAGE ON SCHEMA myschema TO readaccess, developers;

Restrict user to one schema in PostgreSQL?

Is it possible in PostgreSQL to create a user that can only access a single schema?
Here is what I tried:
REVOKE ALL ON DATABASE testdb FROM public;
GRANT CONNECT ON DATABASE testdb TO testuser;
When I connect as testuser indeed I cannot access the actual data:
> SELECT * FROM some_table;
ERROR: permission denied for relation some_table
However, I can still list all the tables, etc. in all the other schemas:
SELECT * FROM pg_tables;
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
--------------------+-------------------------------------------+------------+------------+------------+----------+-------------+-------------
test2 | foo | postgres | | t | f | f | f
test2 | bar | postgres | | t | f | f | f
...
It is impossible to configure PostgreSQL so that a user can only see those objects in the system catalogs for which he or she has permissions.
If you need such a setup, you should create a database per user.
I was able to do this like so:
GRANT USAGE ON SCHEMA schema_name TO user_name;
ALTER USER user_name SET search_path = schema_name;
The ALTER USER statement like this is a way of permanently setting the search path for schemas the way you would set the schema search path of an individual sessions with
SET SEARCH_PATH= schema_name_1, schema_name_2;

Why aren't these commands creating a read-only user in PostgreSQL?

I've carefully reviewed similar questions on this site and I can't get it to work.
I'm using PostgreSQL 9.3.9 (installed from package) on Ubuntu 14.04 (Vagrant box).
I'm creating a new database called site owned by postgres.
I want to create a read-only user called readonly with access to this database.
I've tried to lock them out of SCHEMA public but whatever I try to do, they can still create tables.
Can anybody help me understand why this user can still write to the database, despite being locked out completely? Here's the steps I'm taking; first, set up the entities and explicitly lock out all the permissions:
postgres=# CREATE DATABASE site;
CREATE DATABASE
postgres=# CREATE ROLE readonly UNENCRYPTED PASSWORD 'password' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1;
CREATE ROLE
postgres=# REVOKE ALL ON SCHEMA public FROM public;
REVOKE
postgres=# REVOKE ALL ON SCHEMA public FROM readonly;
REVOKE
postgres=# REVOKE ALL ON DATABASE site FROM public;
REVOKE
Let's check that readonly can't connect:
vagrant#vagrant-web1:~$ PGHOST=127.0.0.1 PGPASSWORD=password psql -U readonly site
psql: FATAL: permission denied for database "site"
DETAIL: User does not have CONNECT privilege.
Everything correct up to this point. Now the superuser grants a single permission:
postgres=# GRANT CONNECT ON DATABASE site TO readonly;
GRANT
This is where the system breaks. The readonly user can log in and can create tables:
vagrant#vagrant-web1:~$ PGHOST=127.0.0.1 PGPASSWORD=password psql -U readonly site
psql (9.3.9)
SSL connection (cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.
site=> CREATE TABLE orders(id int);
CREATE TABLE
site=> \dt
List of relations
Schema | Name | Type | Owner
--------+--------+-------+----------
public | orders | table | readonly
(1 row)
This has had me stuck for a couple of hours. Any help would be greatly appreciated.
Extra information: There's only a single schema in the database. Here's what the output of \du is:
postgres=# \du
List of roles
Role name | Attributes | Member of
---------------------+------------------------------------------------+-----------------------------------------------
postgres | Superuser, Create role, Create DB, Replication | {}
readonly | | {}
Here's the output of \list:
postgres=# \list
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------------+---------------------+----------+-------------+-------------+---------------------------------------------
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
site | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | postgres=CTc/postgres +
| | | | | readonly=c/postgres
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
You issued commands REVOKE ALL ON SCHEMA public ... in database postgres, not site. Check it:
site=> \dn+
List of schemas
Name | Owner | Access privileges | Description
--------+----------+----------------------+------------------------
public | postgres | postgres=UC/postgres+| standard public schema
| | =UC/postgres |
(1 row)
Line =UC/postgres means that public has Usage and Create privileges for schema public.
So do the following:
site=> \c site postgres
You are now connected to database "site" as user "postgres".
site=# REVOKE ALL ON SCHEMA public FROM public;
REVOKE
And now it works:
site=# \c site readonly
You are now connected to database "site" as user "readonly".
site=> create table t(n numeric);
ERROR: no schema has been selected to create in
site=> create table public.t(n numeric);
ERROR: permission denied for schema public

postgres read only user not working

I have Postgresql 9.2 with database running and now try to create a read only user. I followed these descriptions:
ERROR: permission denied for relation tablename on Postgres while trying a SELECT as a readonly user
How do you create a read-only user in PostgreSQL?
BasicallyI have done the following:
jbossmanager=# CREATE USER jbcust WITH ENCRYPTED PASSWORD '#######';
CREATE ROLE
jbossmanager=# GRANT USAGE ON SCHEMA jbossmanager to jbcust;
GRANT
jbossmanager=# ALTER DEFAULT PRIVILEGES IN SCHEMA jbossmanager GRANT SELECT ON TABLES TO jbcust;
ALTER DEFAULT PRIVILEGES
jbossmanager=# GRANT CONNECT ON DATABASE jbossmanager to jbcust;
GRANT
jbossmanager=# GRANT SELECT ON ALL SEQUENCES IN SCHEMA jbossmanager TO jbcust;
GRANT
jbossmanager=# GRANT SELECT ON ALL TABLES IN SCHEMA jbossmanager TO jbcust;
GRANT
After this a "\l" shows the following:
jbossmanager=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
--------------+--------------+----------+-------------+-------------+-------------------------------
jbossmanager | jbossmanager | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/jbossmanager +
| | | | | jbossmanager=CTc/jbossmanager+
| | | | | jbcust=c/jbossmanager
which looks good to me, also a list of tables in that db / schema lokks fine:
jbossmanager=# \dp+
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------------+-------------------------------+----------+-----------------------------------+--------------------------
jbossmanager | env_server_standalone_info | table | jbossmanager=arwdDxt/jbossmanager+|
| | | jbcust=r/jbossmanager |
But now when I connect as this jbcust user to database and try:
#psql -d jbossmanager -U jbcust -h 127.0.0.1
Password for user jbcust:
psql (9.2.4)
Type "help" for help.
jbossmanager=> \dp+
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+------+------+-------------------+--------------------------
(0 rows)
I have no idea what is wrong or what is missing.
Thanks a lot for your help!
The reason why I did not see any schema when connecting with read only user is that the default schema for this user was not set.
After this:
ALTER USER jbcust SET search_path = jbossmanager;
it works perfect.