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.
Related
I need to create 3 users with different DML, DDL, DQL on newly created clean Database in PostgreSQL.
DML should have SELECT, UPDATE, DELETE
DDL should have CREATE, DROP, ALTER, TRUNCATE, INSERT
DQL should have SELECT
all of this in standard scheme public.
Important is that user inherit right on newly created tables by DDL user.
users ref: https://www.geeksforgeeks.org/sql-ddl-dql-dml-dcl-tcl-commands/
I did some coding but I'm pretty new in PostgreSQL and it didn't work :(
The main problem was that I cannot perform GRANT or REVOKE on CREATE, DROP, ALTER, TRUNCATE :(
Can someone help please?
Maybe you have something similar already prepared?
The setup you want, can be done to some extent. However these privileges are controlled on schema level, not on database level.
Assuming you have a schema app_schema for which this should be defined, you can do the following:
First create the users:
create user ddl with password '***';
create user dml with password '***';
create user dql with password '***';
Then create the schema:
create schema app_schema;
Then allow the ddl user to create objects:
grant create,usage on schema app_schema to ddl;
Then change the default privileges on the schema, so that every table (or view, or sequence ...) created by the ddl user is accessible by the dml and dql users:
alter default privileges
for role ddl
grant select,update,delete on tables
to dml;
alter default privileges
for role ddl
grant select on tables
to dql;
This will affect all future tables created in the schema by the user ddl.
The owner of the tables automatically has the privileges to INSERT,UPDATE,DELETE or TRUNCATE the tables.
I have never tried this, but it seems possible to revoke the UPDATE and SELECT privileges:
alter default privileges
for role ddl
in schema app_schema
revoke update,select,delete on tables
from ddl;
If there are already tables in the schema, you need to grant the desired privileges for them:
grant select,insert,update,delete on all tables
in schema app_schema
to dml;
grant select on all tables
in schema app_schema
to dql;
Currently I am using this to grant permissions:
grant select on all tables in schema public to <user_name>;
alter default privileges in schema public grant select on tables to <user_name>;
According to the documentation, the second statement should have resolved the problem. It does not however auto grant permissions to user_name when a new table is added to the public schema.
I am using this user (user_name) to copy data over to another database.
Found the answer. It is in this line in the ALTER DEFAULT PRIVILEGES documentation.
You can change default privileges only for objects that will be created by yourself or by roles that you are a member of.
I was using alter default privileges from a different user than the one creating the tables.
Make sure to set the role to the user creating the table before the alter default privilege statement:
SET ROLE <user_that_creates_new_tables>;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO <user_name>;
To grant default privileges, you need to grant to the user you are creating the table with.
You are creating the tables as SA_user, but reading the tables as READ_user. Your code needs to look like:
ALTER DEFAULT PRIVILEGES
FOR USER SA_user
IN SCHEMA schema_name
GRANT SELECT ON TABLES TO READ_user;
So whenever the SA_user creates a table, it will grant select rights for the READ_user.
I was looking for same thing, I found other way to solve this. Based on postgresql documentation we can create event trigger, so when new table is created, grant query will execute automatically. So no matter who created new table, other user allowed to use it.
CREATE OR REPLACE FUNCTION auto_grant_func()
RETURNS event_trigger AS $$
BEGIN
grant all on all tables in schema public to <username>;
grant all on all sequences in schema public to <username>;
grant select on all tables in schema public to <username>;
grant select on all sequences in schema public to <username>;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER auto_grant_trigger
ON ddl_command_end
WHEN TAG IN ('CREATE TABLE', 'CREATE TABLE AS')
EXECUTE PROCEDURE auto_grant_func();
I had a schema in one oracle DB as ui_prod. I asked my DBA team guys to create exactly same schema like ui_prod but as read only and name it ui_prod_readonly. Usually I will use Oracle SQL developer to connect a DB and query directly with table name like below.
--Connect to ui_prod
select * from table
but why I requested to put owner name infront when query for readonly schema they created for me, as without putting it, I get error table not exist.
--Connect to ui_prod_readonly
select * from ui_prod.table
I have project files which hardcode the sql query with only table names and adding owner name in front will cause many changes and effort. Can anyone explain me on this? or provide me any document/link to read. Thanks
You should look into synonyms, apparently the user you are connecting to the database as is not the owner of the objects. So to view the object you have to prepend the names with the schema name (the owner of the object themselves).
http://www.techonthenet.com/oracle/synonyms.php
CREATE OR REPLACE SYNONYM ui_prod_readonly.synonym_name
FOR ui_prod.object_name
It seems to me that your dbas have not created another set of tables but just granted the existing tables to the user ui_prod_readonly.
When you log in to Oracle, the current schema is the name of the user you used to log in. So if you log in with ui_prod_readonly Oracle checks that schema for the table if you do not qualify it with the owner (=schema).
If you want to change the current schema so that you don't need to fully qualify the tables, you can do that with ALTER SESSION
alter session set current_schema = ui_prod;
Once you have done that, you don't need to fully qualify the table with the owner (=schema).
if you need a user to read the data only
its simple to create new user and grant it only select privilege
you can create user and grant select privilege using
CREATE USER [user] IDENTIFIED BY [your_password];
grant select on table to [user]
I have a production database, where the user can create a set of tables that inherits a master table X. The matter is when i want to apply an automatic grant for all the tables;
Naturally with this command : GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only ; this will only be applied to tables that have already been created.
The aim, is to applied the command for all the newest tables.
NB : I already tried to make a trigger on tables pg_class,
pg_namespace but it's impossible and it's the same for the pg_tables
view;
You can set the default grants for newly created objects with the ALTER DEFAULT PRIVILEGES command, e.g.:
ALTER DEFAULT PRIVILEGES
FOR USER creator_role IN SCHEMA public
GRANT SELECT ON TABLES TO read_only;
As an aside, while you can't install triggers on the system catalogs, you can achieve the same thing (in Postgres 9.3+) with event triggers, which fire on any CREATE/DROP/ALTER statement.
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.)