Re: WIP patch (v2) for updatable security barrier views - Mailing list pgsql-hackers
From | Craig Ringer |
---|---|
Subject | Re: WIP patch (v2) for updatable security barrier views |
Date | |
Msg-id | 52AB112B.6020403@2ndquadrant.com Whole thread Raw |
In response to | Re: WIP patch for updatable security barrier views (Craig Ringer <craig@2ndquadrant.com>) |
Responses |
Re: varattno remapping
Re: WIP patch (v2) for updatable security barrier views |
List | pgsql-hackers |
Hi all Here's an updated version of the updatable security barrier views patch that's proposed as the next stage of progressing row-security toward useful and maintainable inclusion in core. If updatable security barrier views are available then the row-security code won't have to play around with remapping vars and attrs during query planning when it injects its subquery late. We'll simply stop the planner flattening an updatable security barrier view, and for row-security we'll dynamically inject one during rewriting when we see a relation that has a row-security attribute. This patch just implements updatable security barrier views. It is a work in progress with at least two known crash bugs and limited testing. I'd greatly appreciate comments (and advice) from those who are interested in the problem domain as we proceed further into work on 9.4. The patch is attached; it's on top of 46328916eefc5f9eaf249518e96f68afcd35923b, current head. It doens't yet touch the documentation, but the only change needed should be to remove the restriction on security_barrier views from the definition of what a "simply updatable" view is. There are couple of known issues: a crash with INSERT ... RETURNING; DEFAULT handling through views isn't implemented yet; and a crash I just found on UPDATE of a view that re-orders the original table columns. As a result it doesn't survive "make check" yet. I'm still working on fixing these issues and on finding more. Suggestions/comments would be appreciated. I'll post specifics of the INSERT ... RETURNING one soon, as I'm increasingly stuck on it. Simple demo: -- The 'id' is 'integer' not 'serial' because of the limitation with -- DEFAULT mentioned below. CREATE TABLE t (id integer primary key, secret text); INSERT INTO t(id, secret) SELECT x, 'secret'||x FROM generate_series(1,100) x; CREATE VIEW t_even AS SELECT id, secret FROM t WHERE id % 2 = 0; CREATE VIEW t_even_sb WITH (security_barrier) AS SELECT id, secret FROM t WHERE id % 2 = 0; CREATE VIEW t_even_check WITH (check_option = 'cascaded') AS SELECT id, secret FROM t WHERE id % 2 = 0; CREATE VIEW t_even_check_sb WITH (check_option = 'cascaded', security_barrier) AS SELECT id, secret FROM t WHERE id % 2 = 0; You'll find that the same f_leak tests used in the original read security barrier views work here, too. -- Subsets of cols work: CREATE VIEW just_id AS SELECT id FROM t; INSERT INTO just_id(id) VALUES (101); CREATE VIEW just_id_sb WITH (security_barrier) AS SELECT id FROM t; INSERT INTO just_id_sb(id) VALUES (101); -- Reversed column-lists work: CREATE VIEW reversed AS SELECT secret, id FROM t; INSERT INTO reversed(id, secret) VALUES (102, 'fred'); CREATE VIEW reversed_sb WITH (security_barrier) AS SELECT secret, id FROM t; INSERT INTO reversed_sb(id, secret) VALUES (102, 'fred'); -- WITH CHECK OPTION is working postgres=# INSERT INTO t_even_check(id, secret) values (296, 'blah'); INSERT 0 1 postgres=# INSERT INTO t_even_check(id, secret) values (297, 'blah'); ERROR: new row violates WITH CHECK OPTION for view "t_even_check" DETAIL: Failing row contains (297, blah). postgres=# INSERT INTO t_even_check_sb(id, secret) values (298, 'blah'); INSERT 0 1 postgres=# INSERT INTO t_even_check_sb(id, secret) values (299, 'blah'); ERROR: new row violates WITH CHECK OPTION for view "t_even_check_sb" DETAIL: Failing row contains (299, blah). -- 3-col views are OK with various permutations CREATE TABLE t3 ( id integer primary key, aa text, bb text ); CREATE VIEW t3_bai AS SELECT bb, aa, id FROM t3; INSERT INTO t3_bai VALUES ('bb','aa',3); UPDATE t3_bai SET bb = 'whatever' WHERE id = 3 RETURNING *; DELETE FROM t3_bai RETURNING *; CREATE VIEW t3_bai_sb WITH (security_barrier) AS SELECT bb, aa, id FROM t3; INSERT INTO t3_bai_sb VALUES ('bb','aa',3); -- This crashes, with or without RETURNING. Bug in re-ord -- UPDATE t3_bai_sb SET bb = 'whatever' WHERE id = 3 RETURNING *; -- This is OK: DELETE FROM t3_bai_sb RETURNING *; -- Known issues: DEFAULT injection doesn't occur correctly through the view. Needs some changes in the rewriter where expand_target_list is called. Haven't investigated in detail yet. Causes inserts through views to fail if there's a default not null constraint, among other issues. Any INSERT with a RETURNING clause through a view causes a crash (simple VALUES clauses) or fails with "no relation entry for relid 1" (INSERT ... SELECT). UPDATE and DELETE is fine. Seems to be doing subquery pull-up, producing a simple result sub-plan that incorrectly has a Var reference but doesn't perform any scan. Issue traced to plan_subquery, but no deeper yet. Privilege enforcement has not yet been through a thorough test matrix. UPDATE of a subset of columns fails. E.g.: CREATE VIEW just_secret AS SELECT secret FROM t; UPDATE just_secret SET secret = 'fred'; Known failing queries. Note that it doesn't matter what you choose from RETURNING, any reference to a result relation will fail; constant expressions succeed. INSERT INTO t_even(id, secret) VALUES (218, 'fred') RETURNING *; -- **crash** INSERT INTO t_even_sb(id, secret) VALUES (218, 'fred') RETURNING *; -- **crash** INSERT INTO t_even_sb SELECT x, 'secret'||x from generate_series(220,225) x RETURNING *; -- ERROR: no relation entry for relid 1 INSERT INTO t_even SELECT x, 'secret'||x from generate_series(226,230) x RETURNING *; -- ERROR: no relation entry for relid 1 -- Craig Ringer http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
Attachment
pgsql-hackers by date: