How can I insert records into Postgres with RLS when user has `grant all` perms and a loose policy - sql

I'm new to Postgres' RLS feature. I believe I'm following the documentation appropriately, but am getting unexpected behavior. Consider the following case:
i have a table named report_files
this table has a simple policy, policy <name> for all using (true)
the user has grant all permissions on the table (grant all on all tables in schema testing to testuser;, along with grant execute on all functions ... and grant usage for the schema as well)
the user can now read all fields in the table, but cannot insert records, against expectation
Here's a really short snippet from psql demonstrating the aforementioned: https://gist.github.com/cdaringe/85dd9a7b1278afe4770869dc494216f3
I have set a permissive policy, which clearly evaluates OK as evidenced by the successful select command.
What can I troubleshoot to get the insert to work?
Thanks!

ERROR: permission denied for sequence report_files_id_seq
It looks to me like you need to grant your user permission to use the id sequence: report_files_id_seq
You should be able to do this with the following
GRANT USAGE, SELECT ON SEQUENCE report_files_id_seq TO testuser;
Or to bulk add all tables:
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA <insert schema name here>
ALL is equivalent to USAGE, SELECT, UPDATE

As I cannot comment yet, I will add some input as an answer if anyone arrives on this thread like me today.
Yes, you have to grant permissions on sequence(s) separately, in addition to the privileges already granted on the table(s). In fact it is what you have to do.
Even if your table is dependant on the sequence object, they are both different objects from the RDBMS point of view, so they require distinct privileges.
As for your indices example, index in a sub-object of a table, and no additional privilege is required to be able to make use of indices so no further action than the index creation is needed.
Moreover, be careful to prefix the sequence name in case it is stored in a schema which is not the default one (public) and which is not in your search_path.
If that is not the case, you may encounter a permission denied error even though you have all necessary privilege on the sequence you aim to work with.

Related

Can't select rows from table with user

I created a user and granted him all permissions, i used: GRANT ALL PRIVILEGES TO user1;
but then i tried to select rows from a table that i created with the admin user like this:
select * from sys.table it gives me an error message table or view doesn't exist
then i did: Grant select on table to user1 and it worked.
so does all privileges not include select?
As is often the case, Oracle uses words "approximately".
In this case, ALL doesn't mean "all". From the documentation:
ALL PRIVILEGES
Specify ALL PRIVILEGES to grant all of the system privileges listed in
Table 18-1, except the SELECT ANY DICTIONARY, ALTER DATABASE LINK, and
ALTER PUBLIC DATABASE LINK privileges.
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/GRANT.html#GUID-20B4E2C0-A7F8-4BC8-A5E8-BE61BDC41AC3
Notice the "except" part. "All" should mean "all", that is, "no exception"; yet........
Relevant to your question: ALL PRIVILEGES does not include SELECT ANY DICTIONARY. Most likely, whatever table or view you were trying to select from is a dictionary table (or view); which explains why granting ALL PRIVILEGES didn't work, but granting access directly on the table/view did.
If you want to grant access to all dictionary objects, you can grant SELECT ANY DICTIONARY to the user.
After you are done playing with these explicit grants, you may want to consider granting system roles to the users who need them (and only to those users), instead of hunting down all such exceptions.

Simple select query returns no result in postgres database depending on user

I am trying to create a read all user for my database, but it seems the most simplest of queries isn't working properly.
When I try running the query select * from public.reports limit 5; it works fine when using the postgres user (db owner), returning 5 lines of results. However, it returns no results when using this new user. It throws no errors, it says nothing. It simply returns no results, as if the table was empty.
I created the new user using the following queries:
CREATE USER "new_user" WITH PASSWORD 'strong_password';
GRANT CONNECT ON DATABASE my_database TO "new_user";
GRANT USAGE ON SCHEMA public TO "new_user";
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO "new_user";
GRANT SELECT ON ALL TABLES IN SCHEMA public to "new_user";
ALTER USER "new_user" WITH LOGIN;
What am I missing?
So you have row-level security enabled? The manual:
If row-level security is enabled for a table, but no applicable
policies exist, a “default deny” policy is assumed, so that no rows
will be visible or updatable.
This would explain that your user cannot see any rows.
The simplest way to bypass RLS generally for the new user is with BYPASSRLS.
CREATE USER new_user WITH BYPASSRLS PASSWORD 'strong_password';
Else, you need CREATE POLICY to allow things. To allow all read and write operations on table reports for our new role:
CREATE POLICY foo ON public.reports TO new_user USING (true) WITH CHECK (true);

How SELECT ANY TABLE privilege work in Oracle?

I would like to know how the privilege SELECT ANY TABLE works internally in Oracle.
Is it treated as a single privilege? Or is it equivalent to make a GRANT SELECT ON MyTable TO MyUser for each table?
As example, I would like to know if this work :
GRANT SELECT ANY TABLE TO PUBLIC;
REVOKE ALL ON MY_TABLE FROM PUBLIC;
Would I still have access to MY_TABLE from any user after those queries?
Yes, all users would still be able to query MY_TABLE.
You are looking at different privilege types:
The main types of user privileges are as follows:
System privileges—A system privilege gives a user the ability to perform a particular action, or to perform an action on any schema objects of a particular type. For example, the system privilege CREATE TABLE permits a user to create tables in the schema associated with that user, and the system privilege CREATE USER permits a user to create database users.
Object privileges—An objectprivilege gives a user the ability to perform a particular action on a specific schema object. Different object privileges are available for different types of schema objects. The privilege to select rows from the EMPLOYEES table or to delete rows from the DEPARTMENTS table are examples of object privileges.
SELECT ANY TABLE is a system privilege that allows the grantee to:
Query tables, views, or materialized views in any schema except SYS. Obtain row locks using a SELECT ... FOR UPDATE.
When you grant that it is a standalone single privilege, visible in dba_sys_privs. When Oracle decides if the user is allowed to access a table it can look first at system privleges, and only goes on to look for specific object privileges (visible in dba_tab_privs) if there isn't a system privilege that allows the action being performed.
System privileges are not translated into individual privileges on each object in the database - maintaining that would be horrible, as creating a new object would have to automatically figure out who should be granted privileges on it based on the system privilege; and it would mean that you couldn't tell the difference between that and individually granted privileges. So, for instance, if you explicitly granted select privs on a specific table, then the user was granted SELECT ANY TABLE, and then they had SELECT ANY TABLE revoked - what happens to the previous explicit grant?
Your scenario is basically the same, except you've specifed all privileges on the object to be revoked. If those are the only two commands involved then PUBLIC has no explicit privileges on MY_TABLE so revoking doesn't really do anything; but if any explicit privileges on that table had been granted then they would be revoked. That has no impact on the higher-level SELECT ANY TABLE system privileg though.
Privileges are cummulative; revoking a privilege on a specific object doesn't block access to that object, it just removes one possible access route.
Incidentally, hopefully you've used a contrived example, as such powerful system privileges should be granted sparingly and only when really needed. Letting any user query any table in your database potentially blows a big hole in the security model. Again from the docs:
Oracle recommends that you only grant the ANY privileges to trusted users
and
Oracle recommends against granting system privileges to PUBLIC.
and read more in the database security guide.

ORA-01031 after creating table (But only for a while)

I'm having some problems with oracle after creating a table. I have the proper permissions to create the table, but if I try to query immediately after creating it I get error ORA-01031 "Insufficient privileges".
However, if I wait a couple of hours then I have no problems querying it.
Any ideas what would cause this?
I think that you need give privilege for selection data from created table for user that contains it. Use follow script:
grant select on <user>.created_table to <user>;
this script must run from user with admin grant.
Also you can give several options:
grant select, update, delete, insert on <user>.created_table to <user>;

Grant privileges for a particular database in PostgreSQL

I'm moving from MySQL to PostgreSQL and have hit a wall with user privileges. I am used to assigning a user all privileges to all tables of a database with the following command:
# MySQL
grant all privileges on mydatabase.* to 'myuser'#'localhost' identified by 'mypassword';
It appears to me that the PostgreSQL 9.x solution involves assigning privileges to a "schema", but the effort required of me to figure out exactly what SQL to issue is proving excessive. I know that a few more hours of research will yield an answer, but I think everyone moving from MySQL to PostgreSQL could benefit from having at least one page on the web that provides a simple and complete recipe. This is the only command I have ever needed to issue for users. I'd rather not have to issue a command for every new table.
I don't know what scenarios have to be handled differently in PostgreSQL, so I'll list some of the scenarios that I have typically had to handle in the past. Assume that we only mean to modify privileges to a single database that has already been created.
(1a) Not all of the tables have been created yet, or (1b) the tables have already been created.
(2a) The user has not yet been created, or (2b) the user has already been created.
(3a) Privileges have not yet been assigned to the user, or (3b) privileges were previously assigned to the user.
(4a) The user only needs to insert, update, select, and delete rows, or (4b) the user also needs to be able to create and delete tables.
I have seen answers that grant all privileges to all databases, but that's not what I want here. Please, I am looking for a simple recipe, although I wouldn't mind an explanation as well.
I don't want to grant rights to all users and all databases, as seems to be the conventional shortcut, because that approach compromises all databases when any one user is compromised. I host multiple database clients and assign each client a different login.
It looks like I also need the USAGE privilege to get the increasing values of a serial column, but I have to grant it on some sort of sequence. My problem got more complex.
Basic concept in Postgres
Roles are global objects that can access all databases in a db cluster - given the required privileges.
A cluster holds many databases, which hold many schemas. Schemas (even with the same name) in different DBs are unrelated. Granting privileges for a schema only applies to this particular schema in the current DB (the current DB at the time of granting).
Every database starts with a schema public by default. That's a convention, and many settings start with it. Other than that, the schema public is just a schema like any other.
Coming from MySQL, you may want to start with a single schema public, effectively ignoring the schema layer completely. I am using dozens of schema per database regularly.
Schemas are a bit (but not completely) like directories in the file system.
Once you make use of multiple schemas, be sure to understand search_path setting:
How does the search_path influence identifier resolution and the "current schema"
Default privileges
Per documentation on GRANT:
PostgreSQL grants default privileges on some types of objects to
PUBLIC. No privileges are granted to PUBLIC by default on tables,
columns, schemas or tablespaces. For other types, the default
privileges granted to PUBLIC are as follows: CONNECT and CREATE TEMP TABLE
for databases; EXECUTE privilege for functions; and USAGE privilege for languages.
All of these defaults can be changed with ALTER DEFAULT PRIVILEGES:
Grant all on a specific schema in the db to a group role in PostgreSQL
Group role
Like #Craig commented, it's best to GRANT privileges to a group role and then make a specific user member of that role (GRANT the group role to the user role). This way it is simpler to deal out and revoke bundles of privileges needed for certain tasks.
A group role is just another role without login. Add a login to transform it into a user role. More:
Why did PostgreSQL merge users and groups into roles?
Predefined roles
Update: Postgres 14 or later adds the new predefined roles (formally "default roles") pg_read_all_data and pg_write_all_data to simplify some of the below. See:
Grant access to all tables of a database
Recipe
Say, we have a new database mydb, a group mygrp, and a user myusr ...
While connected to the database in question as superuser (postgres for instance):
REVOKE ALL ON DATABASE mydb FROM public; -- shut out the general public
GRANT CONNECT ON DATABASE mydb TO mygrp; -- since we revoked from public
GRANT USAGE ON SCHEMA public TO mygrp;
To assign "a user all privileges to all tables" like you wrote (I might be more restrictive):
GRANT ALL ON ALL TABLES IN SCHEMA public TO mygrp;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO mygrp; -- don't forget those
To set default privileges for future objects, run for every role that creates objects in this schema:
ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON TABLES TO mygrp;
ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON SEQUENCES TO mygrp;
-- more roles?
Now, grant the group to the user:
GRANT mygrp TO myusr;
Related answer:
PostgreSQL - DB user should only be allowed to call functions
Alternative (non-standard) setting
Coming from MySQL, and since you want to keep privileges on databases separated, you might like this non-standard setting db_user_namespace. Per documentation:
This parameter enables per-database user names. It is off by default.
Read the manual carefully. I don't use this setting. It does not void the above.
Maybe you could give me an example that grants a specific user
select/insert/update/delete on all tables -- those existing and not
yet created -- of a specific database?
What you call a database in MySQL more closely resembles a PostgreSQL schema than a PostgreSQL database.
Connect to database "test" as a superuser. Here that's
$ psql -U postgres test
Change the default privileges for the existing user "tester".
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT INSERT, SELECT, UPDATE, DELETE ON TABLES
TO tester;
Changing default privileges has no effect on existing tables. That's by design. For existing tables, use standard GRANT and REVOKE syntax.
You can't assign privileges for a user that doesn't exist.
You can forget about the schema if you only use PUBLIC.
Then you do something like this: (see doc here)
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
I don't want to grant rights to all users and all databases, as seems to be the conventional shortcut, because that approach compromises all databases when any one user is compromised. I host multiple database clients and assign each client a different login.
OK. When you assign tables to the correct role, the privileges granted will be role-specific and not to all users! Then you can decide who to give roles to.
Create a role for each database. A role can hold many users.
Then assign a client-username to the correct role.
Also assign your-username to each role if needed.
(1a) Not all of the tables have been created yet, or (1b) the tables have already been created.
OK. You can create tables later.
When you are ready, assign tables to the correct client role.
CREATE TABLE tablename();
CREATE ROLE rolename;
ALTER TABLE tablename OWNER TO rolename;
(2a) The user has not yet been created, or (2b) the user has already been created.
OK. Create usernames when you are ready. If your client needs more than one username simply create a second client-username.
CREATE USER username1;
CREATE USER username2;
(3a) Privileges have not yet been assigned to the user, or (3b) privileges were previously assigned to the user.
OK. When you are ready to give privileges, create the user and assign the correct role to her.
Use GRANT-TO command to assign roles to users.
GRANT rolename TO username1;
GRANT rolename TO username2;
(4a) The user only needs to insert, update, select, and delete rows, or (4b) the user also needs to be able to create and delete tables.
OK. You run these commands to add permissions to your users.
GRANT SELECT, UPDATE, INSERT, DELETE ON dbname TO role-or-user-name;
ALTER USER username1 CREATEDB;