I created a read-only user in PostgreSQL and it is still able to create tables:
I created a test DB and then created a readonly2 user. Gave it only select privileges on 2 tables. When I log into this DB as readonly2 user I am still able to create tables:
create database test1
create user readonly2 with password 'readonly';
grant select on test1 to readonly2
grant select on test2 to readonly2
where test1 and test2 are 2 tables in test DB.
Now when I log into the test DB as readonly2 user, I am able to create tables:
test=> create table test55 (id int);
CREATE TABLE
I just want to create a read-only user with select permissions. I do not want to grant create table permissions.
Every table is created in a schema in Postgres. To create a table, a role must have the CREATE privilege for the schema. Per documentation:
CREATE
... For schemas, allows new objects to be created within the schema.
The default schema for a table to be created in is the first schema of the current search_path.
The first schema in the search_path is typically the schema with the same name as the user or the schema public.
And the public schema comes with default privileges:
A user can also be allowed to create objects in someone else's schema.
To allow that, the CREATE privilege on the schema needs to be granted.
Note that by default, everyone has CREATE and USAGE privileges on the
schema public.
Bold emphasis mine.
You can change that:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
Be sure to think about consequences first ...
(Either that, or the role is a superuser.)
Related
Using SYSTEM user I create a new user. After that I try to give this user access to specific columns only in 1 table, but get the error that this table does not exist. Meaning that SYSTEM user does not have access to this table. Unfortunately, the user that has access to the normal production tables cannot manage user privileges and access. What are my options?
CREATE USER test1 IDENTIFIED BY 123456;
GRANT UPDATE (extinvno, invoiceno) ON invoice TO test1;
Edit: Solution
Created 3 views that I needed. GRANT-ed the new user SELECT and UPDATE on 2 of the views and SELET on the 3rd. For the new user I had to use the chema to refer to the views: chema.view
If SYSTEM doesn't own the table then you need to specify who does; for example if the table was in the HR schema you would do:
GRANT UPDATE (extinvno, invoiceno) ON HR.invoice TO test1;
... using the real owning schema name, of course.
It isn't that SYSTEM doesn't have access to the table; it's that by default it's looking for SYSTEM.invoice, which doesn't exist.
The table owner could also grant the update privilege to test1.
I have an application schema U32_C5 and another schema MIG_SRC which has some tables and then we have a ROLE RO_ROLE on which we have some grants of tables from Schema U32_C5.
The RO_ROLE is assigned to another Schema MRGO_RO which is Read Only.
Here I need to grant select on tables from MIG_SRC to MRGO_RO catch here is that the process which and from where I can include these grants is run from application schema U32_C5 in production so when I tried to to something like below it says table or view does not exists (which seems to be obvious)
execute Grant from U32_C5
grant select on MIG_SRC.MOBILE_CELLPHONE_PAIRINGS to MRGO_RO;
Another way which I think of is creating DB link on MRGO_RO for MIG_SRC Schema but it enables read/write operation as well on MIG_SRC tables which is not allowed on production.
DB Links is present on U32_C5 Schema for MIG_SRC Schema
So looking for a way to accomplish above task without creating DB Link any suggestion is welcome.
Sample Script of requirement what I want to achieve Please Remember I cannot and do not want Login to MIG_SRC and only way I am looking for is to do it by using U32_C5 and without DBA HELP
A RO ROLE Created by DBA's
Create role RO_ROLE;
/* Create application schema, table inside it and grant select on it to RO_ROLE*/
CREATE USER U32_C5 IDENTIFIED BY U32_C5 DEFAULT TABLESPACE;
GRANT ALTER SESSION TO U32_C5;
GRANT CREATE SESSION TO U32_C5;
GRANT CREATE database link TO U32_C5;
GRANT CREATE table TO U32_C5;
create table U32_C5_test_tab (id number);
grant select on U32_c5.U32_C5_Test_tab to RO_ROLE;
/* Create Read Only schema, grant RO_ROLE to it */
CREATE USER mrgo_ro IDENTIFIED BY mrgo_ro DEFAULT TABLESPACE;
GRANT ALTER SESSION TO mrgo_ro;
GRANT CREATE SESSION TO mrgo_ro;
grant ro_role to mrgo_ro;
/* Create SRC schema, table inside it */
CREATE USER MIG_SRC IDENTIFIED BY MIG_SRC DEFAULT TABLESPACE;
GRANT ALTER SESSION TO MIG_SRC;
GRANT CREATE SESSION TO MIG_SRC;
GRANT CREATE database link TO MIG_SRC;
GRANT CREATE table TO MIG_SRC;
create table mig_src_test_tab (id number);
/* login to Apllication Schema U32_C5 */
sqlplus U32_C5/U32_C5#SID
grant select on mig_src.mig_src_test_tab to mrgo_ro; -- for me it gives error here at this step table or does not exist
/* login to Read Only Schema mrgo_ro */
sqlplus mrgo_ro/mrgo_ro#SID
select * from mig_src.mig_src_test_tab;
or
select * from mig_src_test_tab;
If I understood you correctly, then WITH GRANT OPTION is what you're missing.
Once someone (A) grants privileges on their own objects to someone else (B), and that (B) has to "forward" those privileges to (C), then it is the WITH GRANT OPTION that helps.
Documentation says:
Specify WITH GRANT OPTION to enable the grantee to grant the object privileges to other users and roles.
Restriction on Granting WITH GRANT OPTION You can specify WITH GRANT OPTION only when granting to a user or to PUBLIC, not when granting to a role.
It means that you should grant privileges directly, not via role. That fact doesn't have to be a drawback because of named PL/SQL procedures, where privileges acquired via roles won't work anyway, so you might end up in direct grants anyway.
Other option - which you might consider - is related to what you said:
when I tried to to something like below it says table or view does not exists
If you created a synonym for those tables, then you wouldn't get such an error.
Database link isn't an option, as you said - by using it, you have full access (as you have to know username/password to create the DB link, and that isn't really read only access).
I want to create new schemas and transfer the table in public schema to these schemas, but whenever I'm moving a table from the public schema to another schema, the user/role which has usage access on the new schema, as well as on its tables (including future tables), isn't able to access the newly moved table.
The table (in public schema):
CREATE TABLE atable(ID INT);
INSERT INTO atable VALUES(1);
INSERT INTO atable VALUES(2);
New user:
create user x_user with login password 'x_user';
New schema:
create schema dw;
Then I grant it all the access to the new schema and its tables:
GRANT USAGE ON SCHEMA dw TO x_user;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA dw to x_user;
GRANT SELECT ON ALL TABLES IN SCHEMA dw TO x_user;
For tables added to the schema in the future
ALTER DEFAULT PRIVILEGES IN SCHEMA dw GRANT SELECT ON TABLES TO x_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA dw GRANT USAGE ON SEQUENCES TO x_user;
Now I change the schema of the atable to dw:
ALTER TABLE atable SET SCHEMA dw;
Also, I create another table in the dw schema:
CREATE TABLE dw.btable(id int);
INSERT INTO dw.btable VALUES(3);
INSERT INTO dw.btable VALUES(4);
Now when I connect to the database, using the new user credentials, and run:
SELECT * FROM dw.atable;
I get: ERROR: permission denied for relation atable 1 statement failed.
Whereas if I run the same query for btable , which was created in the dw schema, it works.
SELECT * FROM dw.btable;
id
---
3
4
It also works when I move a table from one schema to another, but when I'm moving a table from the public schema to another schema, it is not working.
What am I doing wrong here?
GRANT ... ON ALL TABLES IN SCHEMA affects only the current contents of the schema.
ALTER DEFAULT PRIVILEGES IN SCHEMA affects tables created in the schema.
Neither of these have any effect when moving tables from one schema to another, and I'm not aware of anything which does.
It should be possible to do this by creating an event trigger which fires on any ALTER TABLE command and applies the appropriate GRANT. Unfortunately, while you can write these trigger functions in PL/pgSQL, I don't think it (currently) provides any way to find out what the actual command was; you'd need to either:
Write a C function to inspect the pg_ddl_command structure returned by pg_event_trigger_ddl_commands(), or
Blindly run a GRANT after every ALTER TABLE, regardless of whether or not it was a SET SCHEMA command.
A far simpler option - provided that it fits your use case - would be to write a move_table() function which combines the ALTER and GRANT commands.
I am running PostgreSQL 9.3.1. I have test database and backup user which is used to backup the database. I have no problems with granting privileges to all current tables, but I have to grant privileges each time the new table is added to schema.
createdb test
psql test
test=# create table foo();
CREATE TABLE
test=# grant all on all tables in schema public to backup;
GRANT
test=# create table bar();
CREATE TABLE
psql -U backup test
test=> select * from foo;
test=> select * from bar;
ERROR: permission denied for relation bar
Is it possible to grant access to tables which will be created in future without making user owner of the table?
It looks like the solution is to alter default privileges for backup user:
alter default privileges in schema public grant all on tables to backup;
alter default privileges in schema public grant all on sequences to backup;
From the comment by Matt Schaffer:
As caveat, the default only applies to the user that executed the
alter statement. This confused me since I was driving most of my
permissions statements from the postgres user but creating tables from
an app user. In short, you might need something like this depending on
your setup:
ALTER DEFAULT PRIVILEGES FOR USER webapp IN SCHEMA public GRANT SELECT ON SEQUENCES TO backup;
ALTER DEFAULT PRIVILEGES FOR USER webapp IN SCHEMA public GRANT SELECT ON TABLES TO backup;
Where webapp is the user that will be creating new tables in the futrue and backup is the user that will be able to read from new tables created by webapp.
If you want the backup user to have access to the future tables of userN,
you must run the code below under each userN who creates new tables,
because ALTER DEFAULT PRIVILEGES...
works only for objects by that user under whom you run ALTER DEFAULT PRIVILEGES...
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO backup;
I am trying to create a role, grant connect access to the role and then alter default privileges to keep access for future objects. However, it seems that the below command doesn't work at role level.
alter default privileges in schema public grant all on tables to backup;
I followed the below documentation but seems that there are two command do not work for roles.
DOC: https://aws.amazon.com/blogs/database/managing-postgresql-users-and-roles/
First command:
GRANT CONNECT ON DATABASE mydatabase TO readonly;
Second command:
GRANT USAGE ON SCHEMA myschema TO readonly;
(For ROLES usually it needs TO ROLE, I also tried TO ROLE but still doesn't work.
I am trying to setup a new role for making the access rights granting easier. I was wondering if there is an easier way to give select on all tables (newly created tables should be accessible automatically) under a schema to selected users. I ran following queries for the same. But still my user is not able to access the specific table.
CREATE ROLE myrole;
GRANT SELECT ON myschema.mytable TO myrole;
GRANT usage ON schema myschema TO myrole;
CREATE USER mytest1 identified BY '***';
GRANT myrole TO mytest1;
After this, when I login with mytest1 user and trying to run select on myschema.mytable it is asking me to grant usage on schema to user. After I grant usage on schema to user directly it is failing with permission denied for that table.
Please help with the same. I am running on vertica 5.0
Update:
I find that u also have to make that role default or explicitely set that role as default for user session for making the role's effect take place.
ALTER USER mytest1 DEFAULT ROLE myrole;
But still, my another question of how to make all tables under a schema accessible to specific users remains.
As per the Vertica SQL Reference Manual.pdf (page 725) (doc version 5.0 - for page numbers)
GRANT (Schema)
...
USAGE
Allows the user access to the objects contained within the
schema. This allows the user to look up objects within the
schema. Note that the user must also be granted access to the
individual objects. See the GRANT TABLE (page 727) ... .
The the user must also be granted access to the individual objects means that you need to also GRANT table.
The two I use is GRANT SELECT and GRANT REFERENCES which allows the user to run queries and join (reference) tables in the query.
Example:
GRANT SELECT ON TABLE [schema].[Table1] TO myUser;
GRANT SELECT ON TABLE [schema].[Table2] TO myUser;
GRANT REFERENCES ON TABLE [schema].[Table1] TO myUser;
GRANT REFERENCES ON TABLE [schema].[Table2] TO myUser;
...
6.0 doc reference GRANT SCHEMA (page 808) and GRANT TABLE (page 813).