Thread: security invoker review need full select (all columns) to do DML?

hi.

the following setup is extract from src/test/regress/sql/updatable_views.sql
you can search keywords: "-- ordinary view on top of security invoker
view permissions"

------------------------------------------------------------------------------------
CREATE USER regress_view_user1;
CREATE USER regress_view_user2;
CREATE USER regress_view_user3;
drop table if exists base_tbl cascade;
-- ordinary view on top of security invoker view permissions
CREATE TABLE base_tbl(a int, b text, c float);
INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0);

SET SESSION AUTHORIZATION regress_view_user1;
CREATE VIEW rw_view1 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl;
ALTER VIEW rw_view1 SET (security_invoker = true);
SELECT * FROM rw_view1;  -- not allowed
UPDATE rw_view1 SET aa=aa;  -- not allowed
MERGE INTO rw_view1 t USING (VALUES (2, 'Row 2', 2.0)) AS v(a,b,c) ON t.aa = v.a
  WHEN NOT MATCHED THEN INSERT VALUES (v.b, v.c, v.a); -- not allowed

SET SESSION AUTHORIZATION regress_view_user2;
CREATE VIEW rw_view2 AS SELECT cc AS ccc, aa AS aaa, bb AS bbb FROM rw_view1;
GRANT SELECT, UPDATE ON rw_view2 TO regress_view_user3;
SELECT * FROM rw_view2;  -- not allowed
UPDATE rw_view2 SET aaa=aaa;  -- not allowed
MERGE INTO rw_view2 t USING (VALUES (2, 'Row 2', 2.0)) AS v(a,b,c) ON
t.aaa = v.a
  WHEN NOT MATCHED THEN INSERT VALUES (v.c, v.a, v.b); -- not allowed

RESET SESSION AUTHORIZATION;
GRANT SELECT(a,b) ON base_tbl TO regress_view_user1;
GRANT UPDATE (a, b) ON base_tbl TO regress_view_user1;
------------------------------------------------------------------------------------
SET SESSION AUTHORIZATION regress_view_user1;
SELECT a, b FROM base_tbl; -- ok
SELECT aa, bb FROM rw_view1; -- ok
UPDATE rw_view1 SET aa=11, bb=22; --ok
UPDATE rw_view1 SET aa=11, bb=22 returning aa,bb; --not ok.

Should the last query be allowed?
The (Updatable Views section in create_view.sgml) didn't explain it or
I didn't fully understand it.

<<QUOTE from manual [1]
Note that the user performing the insert, update or delete on the view
must have the corresponding insert, update or delete privilege on the
view. In addition, by default, the view's owner must have the relevant
privileges on the underlying base relations, whereas the user
performing the update does not need any permissions on the underlying
base relations (see Section 41.5). However, if the view has
security_invoker set to true, the user performing the update, rather
than the view owner, must have the relevant privileges on the
underlying base relations.
<<end of the QUOTE

[1] https://www.postgresql.org/docs/current/sql-createview.html



Re: security invoker review need full select (all columns) to do DML?

From
Dean Rasheed
Date:
On Wed, 21 Aug 2024 at 10:08, jian he <jian.universality@gmail.com> wrote:
>
> the following setup is extract from src/test/regress/sql/updatable_views.sql
> you can search keywords: "-- ordinary view on top of security invoker
> view permissions"
>
> CREATE TABLE base_tbl(a int, b text, c float);
> INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0);
>
> SET SESSION AUTHORIZATION regress_view_user1;
> CREATE VIEW rw_view1 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl;
> ALTER VIEW rw_view1 SET (security_invoker = true);
>
> RESET SESSION AUTHORIZATION;
> GRANT SELECT(a,b) ON base_tbl TO regress_view_user1;

In updatable_views.sql that GRANT is actually

GRANT SELECT ON base_tbl TO regress_view_user1;

Without that, the view is effectively unusable by regress_view_user1
because it selects from column c of base_tbl, and regress_view_user1
lacks permissions on that column.

This is consistent with simple subqueries:

select a, b from (select a,b from base_tbl); -- ok
 a |   b
---+-------
 1 | Row 1
(1 row)

select a, b from (select a,b,c from base_tbl); -- not allowed
ERROR:  permission denied for table base_tbl

The user must have select permissions on all columns selected by the
subquery/view, because we don't go through the outer query to check
which columns are actually referred to. Now maybe we could, but I
suspect that would be quite a lot of effort because you'd need to be
sure that the column wasn't referred to anywhere in either the outer
query or the subquery itself (e.g., in WHERE clauses, etc.).

Regards,
Dean



Dean Rasheed <dean.a.rasheed@gmail.com> writes:
> The user must have select permissions on all columns selected by the
> subquery/view, because we don't go through the outer query to check
> which columns are actually referred to. Now maybe we could, but I
> suspect that would be quite a lot of effort because you'd need to be
> sure that the column wasn't referred to anywhere in either the outer
> query or the subquery itself (e.g., in WHERE clauses, etc.).

I'd argue that we should check that permission regardless, and are
probably required to by the SQL spec.  You don't normally get to
escape permission checks when bits of the query are optimized away.
(This is why permission checks are done on the range table not the
plan tree.)

            regards, tom lane