Skip to content

Commit 8be7342

Browse files
ashutosh-bapatCommitfest Bot
authored andcommitted
Access permissions on property graph
Access to the property graph referenced in GRAPH_TABLE clause and the base relations underlying the graph pattern specified in that clause are governed by the following rules. 1. A user needs SELECT privilege to access a property graph in the query. 2. The property graph itself acts similar to a security invoker view in the sense that the current_user should have privileges to access the tables and columns, underlying the graph pattern. For example, a property graph g1 contains graph element tables e1 and e2. Assume two users u1 and u2 with privileges to access e1 and e2 respectively. Let's also assume that they have privileges to access the property graph g1. u1, as the current user, would be able to run query involving g1 successfully as long as it does *not* require access to e2. Similarly u2 would be able to run query involving g1 successfully as long as it does *not* require access to e1. 3. If a property graph is referenced in a security definer view, access to the property graph is governed by the privileges of the owner of the view but the access to the base relations underlying the graph pattern are governed by the privileges of the user executing the query. This is similar to how access to the base relations underlying a security invoker view referenced from a security definer view is handled. access 4. We have not implemented security definer property graphs since SQL/PGQ standard does not mention those. Note: The privileges tests defined views which are owned by users other than the table owners. Right now, property graph can not contain relations which are not owned by its owner. Hence I have not added tests for testing view access through property graphs. Per SQL/PGQ standard, a property graph can contain any relation as long as it has SELECT privilege on that relation. Once we implement what standard says, we can add the tests with views and preferrably add the views as edge tables. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/a855795d-e697-4fa5-8698-d20122126567@eisentraut.org
1 parent 2c7acde commit 8be7342

File tree

5 files changed

+176
-1
lines changed

5 files changed

+176
-1
lines changed

doc/src/sgml/ref/create_property_graph.sgml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,14 @@ CREATE PROPERTY GRAPH g1
276276
Property graphs are queried using the <literal>GRAPH_TABLE</literal> clause
277277
of <xref linkend="sql-select"/>.
278278
</para>
279+
280+
<para>
281+
Access to the base relations underlying the <literal>GRAPH_TABLE</literal>
282+
clause is determined by the permissions of the user executing the query,
283+
rather than the property graph owner. Thus, the user of a property graph must
284+
have the relevant permissions on the property graph and base relations
285+
underlying the <literal>GRAPH_TABLE</literal> clause.
286+
</para>
279287
</refsect1>
280288

281289
<refsect1>

src/backend/executor/execMain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ ExecCheckPermissions(List *rangeTable, List *rteperminfos,
600600

601601
/*
602602
* Only relation RTEs and subquery RTEs that were once relation
603-
* RTEs (views) have their perminfoindex set.
603+
* RTEs (views, property graph tables) have their perminfoindex set.
604604
*/
605605
Assert(rte->rtekind == RTE_RELATION ||
606606
(rte->rtekind == RTE_SUBQUERY &&

src/backend/rewrite/rewriteGraphTable.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "catalog/pg_propgraph_property.h"
2222
#include "nodes/makefuncs.h"
2323
#include "nodes/nodeFuncs.h"
24+
#include "optimizer/optimizer.h"
2425
#include "parser/analyze.h"
2526
#include "parser/parse_node.h"
2627
#include "parser/parse_relation.h"
@@ -383,6 +384,7 @@ generate_query_for_graph_path(RangeTblEntry *rte, List *graph_path)
383384
Query *path_query = makeNode(Query);
384385
List *fromlist = NIL;
385386
List *qual_exprs = NIL;
387+
List *vars;
386388

387389
path_query->commandType = CMD_SELECT;
388390

@@ -496,6 +498,22 @@ generate_query_for_graph_path(RangeTblEntry *rte, List *graph_path)
496498
replace_property_refs(rte->relid,
497499
(Node *) rte->graph_table_columns,
498500
graph_path));
501+
502+
/*
503+
* Mark the columns being accessed in the path query as requiring SELECT
504+
* privilege. Any lateral columns should have been handled when the
505+
* corresponding ColumnRefs were transformed. Ignore those here.
506+
*/
507+
vars = pull_vars_of_level((Node *) list_make2(qual_exprs, path_query->targetList), 0);
508+
foreach_node(Var, var, vars)
509+
{
510+
RTEPermissionInfo *perminfo = getRTEPermissionInfo(path_query->rteperminfos,
511+
rt_fetch(var->varno, path_query->rtable));
512+
513+
/* Must offset the attnum to fit in a bitmapset */
514+
perminfo->selectedCols = bms_add_member(perminfo->selectedCols,
515+
var->varattno - FirstLowInvalidHeapAttributeNumber);
516+
}
499517
return path_query;
500518
}
501519

src/test/regress/expected/privileges.out

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3077,9 +3077,100 @@ revoke select on dep_priv_test from regress_priv_user4 cascade;
30773077

30783078
set session role regress_priv_user1;
30793079
drop table dep_priv_test;
3080+
--
3081+
-- Property graphs
3082+
--
3083+
set session role regress_priv_user1;
3084+
create property graph ptg1
3085+
vertex tables (
3086+
atest5 key (four)
3087+
default label properties (four)
3088+
label lttc properties (three as lttck),
3089+
atest1 key (a)
3090+
default label
3091+
label lttc properties (a as lttck),
3092+
atest2 key (col1)
3093+
default label
3094+
label ltv properties (col1 as ltvk));
3095+
-- select privileges on property graph as well as table
3096+
select * from graph_table (ptg1 match ( : atest5) COLUMNS (1 as value)) limit 0; -- ok
3097+
value
3098+
-------
3099+
(0 rows)
3100+
3101+
grant select on ptg1 to regress_priv_user2;
3102+
set session role regress_priv_user2;
3103+
select * from graph_table (ptg1 match ( : atest1) COLUMNS (1 as value)) limit 0; -- ok
3104+
value
3105+
-------
3106+
(0 rows)
3107+
3108+
-- select privileges on property graph but not table
3109+
select * from graph_table (ptg1 match ( : atest5) COLUMNS (1 as value)) limit 0; -- fails
3110+
ERROR: permission denied for table atest5
3111+
select * from graph_table (ptg1 match ( : lttc) COLUMNS (1 as value)) limit 0; -- fails
3112+
ERROR: permission denied for table atest5
3113+
set session role regress_priv_user3;
3114+
-- select privileges on table but not property graph
3115+
select * from graph_table (ptg1 match ( : atest1) COLUMNS (1 as value)) limit 0; -- fails
3116+
ERROR: permission denied for property graph ptg1
3117+
-- select privileges on neither
3118+
select * from graph_table (ptg1 match ( : atest5) COLUMNS (1 as value)) limit 0; -- fails
3119+
ERROR: permission denied for property graph ptg1
3120+
-- column privileges
3121+
set session role regress_priv_user1;
3122+
select * from graph_table (ptg1 match (v : lttc) COLUMNS (v.lttck)) limit 0; -- ok
3123+
lttck
3124+
-------
3125+
(0 rows)
3126+
3127+
grant select on ptg1 to regress_priv_user4;
3128+
set session role regress_priv_user4;
3129+
select * from graph_table (ptg1 match (a : atest5) COLUMNS (a.four)) limit 0; -- ok
3130+
four
3131+
------
3132+
(0 rows)
3133+
3134+
select * from graph_table (ptg1 match (v : lttc) COLUMNS (v.lttck)) limit 0; -- fail
3135+
ERROR: permission denied for table atest5
3136+
-- access property graph through security definer view
3137+
set session role regress_priv_user4;
3138+
create view atpgv1 as select * from graph_table (ptg1 match ( : atest1) COLUMNS (1 as value)) limit 0;
3139+
grant select on atpgv1 to regress_priv_user3;
3140+
select * from atpgv1; -- ok
3141+
value
3142+
-------
3143+
(0 rows)
3144+
3145+
set session role regress_priv_user3;
3146+
select * from atpgv1; -- ok
3147+
value
3148+
-------
3149+
(0 rows)
3150+
3151+
set session role regress_priv_user4;
3152+
create view atpgv2 as select * from graph_table (ptg1 match (v : ltv) COLUMNS (v.ltvk)) limit 0;
3153+
-- though the session user is the owner of the view and also has access to the
3154+
-- property graph, it does not have access to a table referenced in the graph
3155+
-- pattern
3156+
select * from atpgv2; -- fail
3157+
ERROR: permission denied for table atest2
3158+
grant select on atpgv2 to regress_priv_user2;
3159+
-- The user who otherwise does not have access to the property graph, gets
3160+
-- access to it through a security definer view and uses it successfully since
3161+
-- it has access to the tables referenced in the graph pattern.
3162+
set session role regress_priv_user2;
3163+
select * from atpgv2; -- ok
3164+
ltvk
3165+
------
3166+
(0 rows)
3167+
30803168
-- clean up
30813169
\c
30823170
drop sequence x_seq;
3171+
drop view atpgv1;
3172+
drop view atpgv2;
3173+
drop property graph ptg1;
30833174
DROP AGGREGATE priv_testagg1(int);
30843175
DROP FUNCTION priv_testfunc2(int);
30853176
DROP FUNCTION priv_testfunc4(boolean);

src/test/regress/sql/privileges.sql

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,13 +1800,71 @@ revoke select on dep_priv_test from regress_priv_user4 cascade;
18001800
set session role regress_priv_user1;
18011801
drop table dep_priv_test;
18021802

1803+
--
1804+
-- Property graphs
1805+
--
1806+
set session role regress_priv_user1;
1807+
create property graph ptg1
1808+
vertex tables (
1809+
atest5 key (four)
1810+
default label properties (four)
1811+
label lttc properties (three as lttck),
1812+
atest1 key (a)
1813+
default label
1814+
label lttc properties (a as lttck),
1815+
atest2 key (col1)
1816+
default label
1817+
label ltv properties (col1 as ltvk));
1818+
-- select privileges on property graph as well as table
1819+
select * from graph_table (ptg1 match ( : atest5) COLUMNS (1 as value)) limit 0; -- ok
1820+
grant select on ptg1 to regress_priv_user2;
1821+
set session role regress_priv_user2;
1822+
select * from graph_table (ptg1 match ( : atest1) COLUMNS (1 as value)) limit 0; -- ok
1823+
-- select privileges on property graph but not table
1824+
select * from graph_table (ptg1 match ( : atest5) COLUMNS (1 as value)) limit 0; -- fails
1825+
select * from graph_table (ptg1 match ( : lttc) COLUMNS (1 as value)) limit 0; -- fails
1826+
set session role regress_priv_user3;
1827+
-- select privileges on table but not property graph
1828+
select * from graph_table (ptg1 match ( : atest1) COLUMNS (1 as value)) limit 0; -- fails
1829+
-- select privileges on neither
1830+
select * from graph_table (ptg1 match ( : atest5) COLUMNS (1 as value)) limit 0; -- fails
1831+
-- column privileges
1832+
set session role regress_priv_user1;
1833+
select * from graph_table (ptg1 match (v : lttc) COLUMNS (v.lttck)) limit 0; -- ok
1834+
grant select on ptg1 to regress_priv_user4;
1835+
set session role regress_priv_user4;
1836+
select * from graph_table (ptg1 match (a : atest5) COLUMNS (a.four)) limit 0; -- ok
1837+
select * from graph_table (ptg1 match (v : lttc) COLUMNS (v.lttck)) limit 0; -- fail
1838+
-- access property graph through security definer view
1839+
set session role regress_priv_user4;
1840+
create view atpgv1 as select * from graph_table (ptg1 match ( : atest1) COLUMNS (1 as value)) limit 0;
1841+
grant select on atpgv1 to regress_priv_user3;
1842+
select * from atpgv1; -- ok
1843+
set session role regress_priv_user3;
1844+
select * from atpgv1; -- ok
1845+
set session role regress_priv_user4;
1846+
create view atpgv2 as select * from graph_table (ptg1 match (v : ltv) COLUMNS (v.ltvk)) limit 0;
1847+
-- though the session user is the owner of the view and also has access to the
1848+
-- property graph, it does not have access to a table referenced in the graph
1849+
-- pattern
1850+
select * from atpgv2; -- fail
1851+
grant select on atpgv2 to regress_priv_user2;
1852+
-- The user who otherwise does not have access to the property graph, gets
1853+
-- access to it through a security definer view and uses it successfully since
1854+
-- it has access to the tables referenced in the graph pattern.
1855+
set session role regress_priv_user2;
1856+
select * from atpgv2; -- ok
18031857

18041858
-- clean up
18051859

18061860
\c
18071861

18081862
drop sequence x_seq;
18091863

1864+
drop view atpgv1;
1865+
drop view atpgv2;
1866+
drop property graph ptg1;
1867+
18101868
DROP AGGREGATE priv_testagg1(int);
18111869
DROP FUNCTION priv_testfunc2(int);
18121870
DROP FUNCTION priv_testfunc4(boolean);

0 commit comments

Comments
 (0)