create/remove row permission in IBM i (as400) SQL - db2

In Db2 for IBM i, I can create row permission like this.
-- enable row access control
ALTER TABLE QIWS.QCUSTCDT ACTIVATE ROW ACCESS CONTROL;
-- create permission MYPERMISSION999
CREATE PERMISSION MYPERMISSION999 ON SALES.ORDHED
FOR ROWS WHERE VERIFY_GROUP_FOR_USER(SESSION_USER,'MYGROUP') = 1
AND SCODE = SESSION_USER
ENFORCED FOR ALL ACCESS
ENABLE;
COMMIT;
ALTER TABLE SALES.ORDHED ACTIVATE ROW ACCESS CONTROL;
COMMIT;
If I Deactivate row access control, rules seem to go away, but if I ACTIVATE old rules come back.
ALTER TABLE SALES.ORDHED
DEACTIVATE ROW ACCESS CONTROL

DROP PERMISSION MYPERMISSION999;
Should do it

Related

Why is the policy's "using"-clause used for the new row while a "with check"-clause is provided for an update statement?

From the Postgres CREATE POLICY documentation:
UPDATE policies accept both a USING expression and a WITH CHECK expression. The USING expression determines which records the UPDATE command will see to operate against, while the WITH CHECK expression defines which modified rows are allowed to be stored back into the relation.
See the following queries to reproduce an error.
-- model + data
create schema sandbox;
create table sandbox.person (
name text primary key,
deleted_at timestamp without time zone
);
insert into sandbox.person (name) values ('Bob'),('Alice');
-- user and permissions
create role tester;
grant usage on schema sandbox to tester;
grant select, insert, update, delete on table sandbox.person to tester;
-- RLS
alter table sandbox.person enable row level security;
create policy test_policy on sandbox.person
for all
to tester
using (deleted_at is null)
with check (true);
-- testing the policy
set role tester;
update sandbox.person set deleted_at = now()
where name = 'Alice';
--> ERROR: new row violates row-level security policy for table "person"
-- cleanup
reset role;
drop schema if exists sandbox cascade;
drop role if exists tester;
The error seems to be caused by the "using"-clause that is checked against the NEW row, but the documentation says that when a "with check"-clause is provided, the NEW row will be checked against the "with check"-clause instead of the "using"-clause. But according to the error I must be misinterpreting or overlooked a condition that invalidates the statement in the docs in this scenario.
Can you explain what I am missing and how the policy should look like? The end goal is to hide the records marked as deleted, and allow a user to mark them as such.
I reproduced my problem in Postgres 11 and 15.
Update
I've tried separating the policies into 1 for select and 1 for the update.
create policy test_policy_for_update on sandbox.person
for update
to tester
with check (true);
create policy test_policy_for_select on sandbox.person
for select
to tester
using (deleted_at is null);
This prevents the error in the update-statement but results in zero records updated.
Update 2
I now believe that the next best way to solves this is to create a separate update function with security definer to bypass RLS as proposed in this answer:
Postgres Row Level Security doesn't allow update on restrictive select policy
That proposal is due to the returning * added by postgraphile, but even without that, the separate update function solution is still needed.
You made your policy applying to all operations, including SELECT operations. The documentation states that even for an UPDATE statement there are cases where the USING clause of the SELECT policy is checked for the new row. This seems to be happening here.

Redshift: Truncating Table Created by another user

I'm trying to truncate a table in redshift but it's throwing the following error -
SQL Error [500310] [42501]: Amazon Invalid operation: must
be owner of relation table;
I have already granted all the privileges on the table to the user. As checked through the online documentation for redshift, I can't grant the truncate table access explicitly like the way it's enabled now in PostgreSQL. Is there a way or a best practice to handle this scenario?
As you say only the table owner or a superuser can truncate a table. There are several options.
Change the table to be owned by the user that needs to truncate but this may not meet other constraints
Alter table to current user, truncate, and alter it back to the previous user (requires DROP permission)
Drop and recreate the table but this may break dependencies
Make a table LIKE the original, perform an ALTER TABLE APPEND to this new table, and then drop the new table (some restrictions like no identity columns)

Postgresql role with no drop table permision

Is it possible to set role with access to one database, with all privileges except to drop tables?
Not really. If a user can issue CREATE TABLE, it can issue a DROP for that table as well. From the docs:
The right to drop an object, or to alter its definition in any way, is not treated as a grantable privilege; it is inherent in the owner, and cannot be granted or revoked.
And as noted by the CREATE TABLE docs:
The table will be owned by the user issuing the command.
There is no mechanism to allow a user to create tables that they do not own and therefore cannot drop.

postgresql table updated only by trigger

Is it possible, to configure a Postgres database such, that a specific table may only be updated by a trigger. I have history table, updated by trigger, so I want to prevent this table from un unauthorised access. I want history table to be updated only from trigger.
Sure. Both the history table and the table with the trigger belong to a user that has no login rights. Then you grant privileges on the latter table to the application user.
To prevent unauthorized access to a table you can change the owner of the table to the user who should be accessing with the following query:
alter table yourschema.yourtable owner to youruser;
Now you can disable the trigger for all other users using the query:
alter table yourschema.yourtable disable trigger triggername all;
here all means that the trigger is disabled for all the users. Now only the owner will be able to use the trigger to update the table.
A trigger always fires on the event on it is defined. Thus, if an update trigger is defined for updates, no one can bypass the trigger during an update if the trigger is enabled.
If you have different user groups with different privileges accessing your database, then you should map this about users in the database. For instance you can disallow that a user can disable triggers on a table.

how to grant update or select on some specified row in postgresql table?

I want to create some roles in my Postgresql DB and grant some access.
I have student role and i want to grant this user type : can edit only record a bout him/her in student table and can not edit other rows
how can i do it?
thanks
Create a view on the table with an appropriate where clause, then grant access to that:
create view students_view as
select col1, col2, col3 -- limit column access here
from mytable
where <whatever>; -- limit row access here
-- limit what he can do here
grant update, select to student_role;
BTW It is a commonly held misconception that you can't update a view, but that is only true if the view is a join or similarly complicated query.
PostgreSQL doesn't have row-level declarative security (yet, there's ongoing work into it) so if you can't just create a view - say, if you have many different people who need this access - you will probably need a SECURITY DEFINER helper function or trigger.
You've got a couple of options:
Write a SECURITY DEFINER function that lets them make only the permitted changes and limit their access to the table to SELECT, revoking UPDATE, DELETE, TRUNCATE and INSERT rights; or
write a trigger that tries to restrict them from making changes you don't want them to make and GRANT them write access to the table.
Of the two, the function and restricted rights approach is by far the safest option so long as you follow the SECURITY DEFINER secure coding guidelines set above - setting search_path for the function, avoiding dynamic SQL (EXECUTE) with string substitutions, etc.
The view approach given above can work quite nicely if it's a view that filters by current_user. You may also want to look at the new SECURITY BARRIER views; see this post for a useful discussion of them.
GRANT UPDATE(column) on tabela to user_name;