sraoss / pgsql-ivm

IVM (Incremental View Maintenance) development for PostgreSQL
Other
127 stars 12 forks source link

Support for RLS in base tables #64

Closed thoshiai closed 4 years ago

thoshiai commented 4 years ago

When IVM execute calculation of incremental difference, it use Ephemeral Named Relation(ENR) for store of base table diff. VIM was not supported RLS, because ENR could not have RLS info.

It meant that data which owner don't have permission was seen on matview. So this patch add that give RLS info of base table to RTE of ENR.

yugo-n commented 4 years ago

Thanks! BTW, could you also add the test for confirming if it works as you intended?

thoshiai commented 4 years ago

Thanks! BTW, could you also add the test for confirming if it works as you intended?

Thank you for your comment. I added test case.

yugo-n commented 4 years ago

@thoshiai Could you please resolve the conflicts?

thoshiai commented 4 years ago

@thoshiai Could you please resolve the conflicts?

I resolved conflict

yugo-n commented 4 years ago

I found this works wrong when multiple tables are simultaneously updated.

CREATE TABLE rls_tbl(id int, data text, owner name);
CREATE TABLE
INSERT INTO rls_tbl VALUES
  (1,'foo','rls_user'),
  (2,'bar','postgres');
INSERT 0 2
CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user);
CREATE POLICY
ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY;
ALTER TABLE
GRANT ALL on rls_tbl TO PUBLIC;
GRANT
CREATE TABLE num_tbl(i int, num text);
CREATE TABLE
INSERT INTO num_tbl VALUES 
 (1,'one'),(2,'two'),(3,'three'),(4,'four');
INSERT 0 4
GRANT ALL on num_tbl TO PUBLIC;
GRANT
SET SESSION AUTHORIZATION rls_user;
SET
CREATE INCREMENTAL MATERIALIZED VIEW  immv_rls AS SELECT * FROM rls_tbl JOIN num_tbl ON i=id;
SELECT 1
RESET SESSION AUTHORIZATION;
RESET
SELECT * FROM immv_rls;
 id | data |  owner   | i | num 
----+------+----------+---+-----
  1 | foo  | rls_user | 1 | one
(1 row)

INSERT INTO rls_tbl VALUES
  (3,'baz','rls_user'),
  (4,'qux','postgres');
INSERT 0 2
SELECT * FROM immv_rls;
 id | data |  owner   | i |  num  
----+------+----------+---+-------
  1 | foo  | rls_user | 1 | one
  3 | baz  | rls_user | 3 | three
(2 rows)

WITH 
 x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)),
 y AS (UPDATE num_tbl SET num = num || '_2' where i in (3,4))
SELECT;
--
(1 row)

SELECT * FROM immv_rls;
 id | data  |  owner   | i |   num   
----+-------+----------+---+---------
  1 | foo   | rls_user | 1 | one
  4 | qux   | postgres | 4 | four_2
  3 | baz_2 | rls_user | 3 | three_2
(3 rows)

Note that the last result contains a tuple whose owner is not rls_user although this must not be invisible for the matview owner. I think this is due to ENRs in a subquery to calculate the pre-state, so we need to set securtyQuals for them in get_prestate_rte.

Attached is the test SQL script.

test_rls.sql.txt

thoshiai commented 4 years ago

I found this works wrong when multiple tables are simultaneously updated.

Thank you for your comment and sharing test code. I will confirm and fix it.

thoshiai commented 4 years ago

I found this works wrong when multiple tables are simultaneously updated.

I check replaying this problem. And I add a commit that it is resolved and add regrresion test.

yugo-n commented 4 years ago

Thanks! It seems good.