postgres user restrict schema changes - postgresql

I need a postgres user who cannot alter tables, views, triggers etc. Only select & insert into tables, so I created new role and granted SELECT, INSERT, USE SCHEMA(something like that), SEQUENCE and even EXECUTE ON ALL FUNCTIONS privileges. But when I run function, I get following error: ERROR: permission denied for relation #table_name.

Related

Grant privileges on tables in other database

Context
I want to grant privileges to a specific user, on the public schema in database mydb.
Currently, I connect as user postgres on database mydb, and run :
GRANT insert, update, delete, truncate ON ALL TABLES IN SCHEMA public TO myuser
My Issue
I would feel more comfortable naming the target database in the query, rather than relying on the connection being on the correct database.
For example, I wouldn't want to accidentally give accesses on the postgres database, rather than on mydb.
Question
Is there a way to target tables in another database in a GRANT query ?
I couldn't find a way to do so in the doc (perhaps I overlooked a paragraph ?) and the following do not work :
# grant insert on all tables in schema mydb.public to myuser;
ERROR: syntax error at or near "."
LINE 1: grant insert on all tables in schema mydb.public to...
^
# grant insert on mydb.public.mytable1 to myuser;
ERROR: cross-database references are not implemented: "mydb.public.mytable1"
No, as the error message says, cross-database references are not implemented.
This is a security feature: There is no way to affect another database than the one you are connected to with an SQL statement (unless you are using something like dblink or foreign data wrappers).

Permission denied for relation <table_name>

So I'm making this app and I'm using Postgres and I've already created a database, a user and a password and granted all privileges on the database to the user I've created.
The thing is, when I switch the database in psql using \c <database_name> I get in just fine and can use queries on it.
But when I run psql using postgres://user_name:password#localhost:5432/databasename on terminal and try to select * from the <table_name> it gives me this message
permission denied for relation <table_name>
Can you please tell me what to do, I've had this problem before and I had to create another database or change the user but I want a better solution please.
PS: I've tried to use this :
GRANT ALL PRIVILEGES ON TABLE <table_name> to <user_name>
This is how I created and accessed my database:
rawan95=# create database food ;
CREATE DATABASE
rawan95=# create user meal with password '123';
CREATE ROLE
rawan95=# grant all privileges on database food to meal;
GRANT
rawan95=# \c food
You are now connected to database "food" as user "rawan95".
After that, I've built it using
food=# \i src/database/db_build.sql
BEGIN
DROP TABLE
CREATE TABLE
INSERT 0 1
COMMIT
Then I selected data from the table just fine, but when I try to access it using this, I get an error: psql postgres://meal:123#localhost:5432/food
food=> select * from foods;
ERROR: permission denied for relation foods
You are granting the privileges before you create the tables.
As there are no tables at that moment nothing is granted. The tables you created are not owned by the user meal but the user rawan95 (which the \c command told you).
Plus: granting "all privileges" on a database, does not grant any select privilege. As documented in the manual "all privileges" are: CREATE, CONNECT, TEMPORARY, TEMP. The CREATE privilege would allow the user meal to create tables in that database.
If you want all those tables to be owned by the user meal you need to run your setup script after you connected as the user meal (the \c command did not change the current user)
If you do want rawan95 to be the owner of the tables, you need to either grant the select privilege after creating all tables:
grant select on all tables in schema public to meal;
Or, you can change the default privilege before creating the tables (before running db_build.sql), so that they are applied to all tables in the future:
alter default privileges in schema public
grant select on all tables to meal;
The alter default privileges only has an effect for tables that are created after that. So to fix your current setup, you need to first grant select on the existing tables, and the change the default privileges for all tables that are created in the future.
Have you granted usage on the schema? Without that the table permissions are useless.
GRANT USAGE ON SCHEMA schema_name TO username
EDIT: Based on comment thread below we have established.
The table is in public schema.
The table belongs to rawan95 but the schema does not (public schema belongs to root postgres user).
The OP is attempting to connect and access the table as user 'meal' they have granted table permissions using the rawan95 user but are unable to grant schema permissions.
From the above, the problem could still be that the user 'meal' does not have usage on the public schema. If you are on Linux the quickest way to sort this is to switch to the super user to make this change from terminal:
sudo -u postgres psql -c "GRANT USAGE ON SCHEMA public TO meal"
FURTHER EDIT - having read your new clarification this is not correct (or at least not useful). The issue is as pointed out by the other answerer that you didn't have a table at the time you did the grant.

Have access to table and function, but not the table within the function

I ran into a peculiar problem with my database that I haven't been able to solve since yesterday.
So I created a user that has access to the function "write_match_history()" and access to the table "match_history," and I can use this user to query match history as well as write to it directly using sql. However, when I try to run "write_match_history," I get the following error:
error: error: permission denied for relation match_history
Here are the accesses I've granted to this user:
drop OWNED by d_write;
drop user if exists d_write;
create user d_write with encrypted password 'supersecret';
grant execute on function write_match_history(a,b,c,d,e,f) to d_write;
grant usage on schema d to d_write;
grant insert on table d.match_history to d_write;
grant select on table d.match_history to d_write;
grant select on all SEQUENCES in SCHEME d to d_write;
grant insert on all tables in schema d to d_write;
grant select on all talbes in schema d to d_write;
These permissions are everything I've tried so far. Let me know if you need more information.
Thanks!
Well, what is the owner of the function write_match_history(a,b,c,d,e,f). Do it allow to insert/update on table match_history. If not, please try it. I think the problem is here.

Granting SELECT on all tables to a user in Firebird 2.1

I've added a user to a Firebird 2.1 instance using gsec, but now I wanted to grant SELECT on all tables to this new user. I could find how to grant this permission on specific tables, but not to them all:
GRANT SELECT ON TABLE table TO USER user;
If I try to use the new user I get the following error on isql:
no permission for read/select access to TABLE table
Is there a way to do that on Firebird 2.1?
Something like this:
EXECUTE BLOCK
AS
DECLARE VARIABLE tablename VARCHAR(32);
BEGIN
FOR SELECT rdb$relation_name
FROM rdb$relations
WHERE rdb$view_blr IS NULL
AND (rdb$system_flag IS NULL OR rdb$system_flag = 0)
INTO :tablename DO
BEGIN
EXECUTE STATEMENT ('GRANT SELECT ON TABLE ' || :tablename || ' TO USER TEST');
END
END
I could find how to grant this permission on specific tables, but not to them all
You can grant specific privileges to all users, already existing and yet to be created. That is made by granting privilege to "PUBLIC" pseudo-user. Or you could grant privileges to some ROLE, then grant this ROLE to given users, then during database connection specify the option, that the user impersonate this ROLE in this session.
However there is no syntax to grant privileges to all generators or all procedures or all views or all tables, etc.
See the GRANT statement syntax in documentation.
What you can do though, is creating a simple script (anonymous and volatile aka EXECUTE BLOCK or persistent and named as STORED PROCEDURE) and that script of yours would be querying system tables to list all non-system ( COALESCE(RDB$SYSTEM_FLAG,0)=0 ) tables (together with views, or tables but not views: check if RDB$RELATION_TYPE is 0 or is 0 or 1) and then form a sequence of GRANT statements and execute them one by one.
See documentation about EXECUTE BLOCK and FOR SELECT ... INTO ... DO ... and EXECUTE STATEMENT ( or maybe FOR EXECUTE STATEMENT also, but I do not think it already was there in FB 2.1. There is unofficial wiki tracking which statements were available since which FB versions, but it is not thorough and may contain errors: http://firebirdsql.su/doku.php ).
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-security-privs.html#fblangref25-security-privs-grant
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-relations.html
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-psql-coding.html#fblangref25-psql-execstmt
https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-dml-execblock.html

Postgres role with usage privilige but not DELETE

I have a postgres instance with a user root that has full admin privileges.
I have two databases db1 and db2.
For every database, I would like to have two users dbN_user and dbN_admin. dbN_user will be the used by my application, and dbN_admin will be used for migrations that change the table structure.
No rows are ever deleted by the application, and I would like to enforce that with user privileges.
db1_user should be able to connect to db1, and be able to SELECT, INSERT and UPDATE, but not DELETE.
db1_admin should have additional privileges to DELETE, CREATE TABLE, ALTER TABLE.
What are the SQL statements to set this up?
dbN_admin would be the owner of the objects, so that user would have all privileges automatically.
You need to GRANT the privileges for dbN_user on the tables and other objects themselves, not on the database.
Just add the correct GRANT statements after the CREATE TABLE statements in the SQL script that populates the database.
You need to GRANT the USAGE privilege on the schema that contains the objects to dbN_user as well.
There is the possibility to define default privileges in a database:
ALTER DEFAULT PRIVILEGES FOR dbN_admin
GRANT SELECT, INSERT, UPDATE ON TABLES
TO dbN_user;
This will grant the privileges automatically whenever dbN_admin creates a new table (but it does not affect tables created before the ALTER DEFAULT PRIVILEGES command).
admin:
create user db1_admin;
create schema app_relations;
alter schema app_relations owner to db1_admin;
app:
create user db1_user;
grant CONNECT ON DATABASE db1 to db1_user; --only if you have restricted connections on db previously
grant usage on schema app_relations to db1_user;
grant select,insert,update on all tables in schema app_relations to db1_user;