[PATCH] Add reloption for views to enable RLS

Поиск
Список
Период
Сортировка
От Christoph Heiss
Тема [PATCH] Add reloption for views to enable RLS
Дата
Msg-id b66dd6d6-ad3e-c6f2-8b90-47be773da240@cybertec.at
обсуждение исходный текст
Список pgsql-hackers
Hi all!

As part of a customer project we are looking to implement an reloption 
for views which when set, runs the subquery as invoked by the user 
rather than the view owner, as is currently the case.
The rewrite rule's table references are then checked as if the user were 
referencing the table(s) directly.

This feature is similar to so-called 'SECURITY INVOKER' views in other DBMS.
Although such permission checking could be implemented using views which 
SELECT from a table function and further using triggers, that approach 
has obvious performance downsides.

Our initial thought on implementing this was to simply add another 
reloption for views, just like the already existing `security_barrier`. 
With this in place, we then can conditionally evaluate in 
RelationBuildRuleLock() if we need to call setRuleCheckAsUser() or not.
The new reloption has been named `security`, which is an enum currently 
only supporting a single value: `relation_permissions`.

The code for fetching the rules and triggers in RelationBuildDesc() had 
to be moved after the parsing of the reloptions, since with this change 
RelationBuildRuleLock()now depends upon having relation->rd_options 
available.

The current behavior of views without that new reloption set is unaltered.
This is implemented as such in patch 0001.

Regression tests are included for both the new reloption of CREATE VIEW 
and the row level security side of this too, contained in patch 0002.
All regression tests are passing without errors.

Finally, patch 0003 updates the documentation for this new reloption.

An simplified example on how this feature can be used could look like this:

   CREATE TABLE people (id int, name text, company text);
   ALTER TABLE people ENABLE ROW LEVEL SECURITY;
   INSERT INTO people VALUES (1, 'alice', 'foo'), (2, 'bob', 'bar');

   CREATE VIEW customers_no_security
       AS SELECT * FROM people;

   CREATE VIEW customers
       WITH (security=relation_permissions)
       AS SELECT * FROM people;

   -- We want carol to only see people from company 'foo'
   CREATE ROLE carol;
   CREATE POLICY company_foo_only
       ON people FOR ALL TO carol USING (company = 'foo');

   GRANT SELECT ON people TO carol;
   GRANT SELECT ON customers_no_security TO carol;
   GRANT SELECT ON customers TO carol;

Now using these tables as carol:

     postgres=# SET ROLE carol;
     SET

For the `people` table, the policy is applied as expected:

     postgres=> SELECT * FROM people;
      id | name  | company
     ----+-------+---------
       1 | alice | foo
     (1 row)

If we now use the view with the new relopt set, the policy is applied too:

     postgres=> SELECT * FROM customers;
      id | name  | company
     ----+-------+---------
       1 | alice | foo
     (1 row)

But without the `security=relation_permissions` relopt, carol gets to 
see data they should not be able to due to the policy not being applied, 
since the rules are checked against the view owner:

     postgres=> SELECT * FROM customers_no_security;
      id | name  | company
     ----+-------+---------
       1 | alice | foo
       2 | bob   | bar
     (2 rows)


Excluding regression tests and documentation, the changes boil down to this:
  src/backend/access/common/reloptions.c    | 20
  src/backend/nodes/copyfuncs.c             |  1
  src/backend/nodes/equalfuncs.c            |  1
  src/backend/nodes/outfuncs.c              |  1
  src/backend/nodes/readfuncs.c             |  1
  src/backend/optimizer/plan/subselect.c    |  1
  src/backend/optimizer/prep/prepjointree.c |  1
  src/backend/rewrite/rewriteHandler.c      |  1
  src/backend/utils/cache/relcache.c        | 62
  src/include/nodes/parsenodes.h            |  3
  src/include/utils/rel.h                   | 21
  11 files changed, 84 insertions(+), 29 deletions(-)

All patches are against current master.

Thanks,
Christoph Heiss
Вложения

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Alvaro Herrera
Дата:
Сообщение: Re: Column Filtering in Logical Replication
Следующее
От: Greg Stark
Дата:
Сообщение: Re: WIP: WAL prefetch (another approach)