-- Suppress NOTICE messages when users/groups don't exist SET client_min_messages TO'warning';
DROP ROLE IFEXISTS regress_priv_group1; DROP ROLE IFEXISTS regress_priv_group2;
DROP ROLE IFEXISTS regress_priv_user1; DROP ROLE IFEXISTS regress_priv_user2; DROP ROLE IFEXISTS regress_priv_user3; DROP ROLE IFEXISTS regress_priv_user4; DROP ROLE IFEXISTS regress_priv_user5; DROP ROLE IFEXISTS regress_priv_user6; DROP ROLE IFEXISTS regress_priv_user7;
SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000AND oid < 3000ORDERBY oid;
RESET client_min_messages;
-- test proper begins here
CREATE USER regress_priv_user1; CREATE USER regress_priv_user2; CREATE USER regress_priv_user3; CREATE USER regress_priv_user4; CREATE USER regress_priv_user5; CREATE USER regress_priv_user5; -- duplicate CREATE USER regress_priv_user6; CREATE USER regress_priv_user7; CREATE USER regress_priv_user8; CREATE USER regress_priv_user9; CREATE USER regress_priv_user10; CREATE ROLE regress_priv_role;
-- circular ADMIN OPTION grants should be disallowed GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; GRANT regress_priv_user1 TO regress_priv_user3 WITH ADMIN OPTION GRANTED BY regress_priv_user2; GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION GRANTED BY regress_priv_user3;
-- need CASCADE to revoke grant or admin option if dependent grants exist REVOKE ADMIN OPTIONFOR regress_priv_user1 FROM regress_priv_user2; -- fail REVOKE regress_priv_user1 FROM regress_priv_user2; -- fail SELECT member::regrole, admin_option FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole;
BEGIN; REVOKE ADMIN OPTIONFOR regress_priv_user1 FROM regress_priv_user2 CASCADE; SELECT member::regrole, admin_option FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole;
ROLLBACK; REVOKE regress_priv_user1 FROM regress_priv_user2 CASCADE; SELECT member::regrole, admin_option FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole;
-- inferred grantor must be a role with ADMIN OPTION GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; GRANT regress_priv_user2 TO regress_priv_user3; SET ROLE regress_priv_user3; GRANT regress_priv_user1 TO regress_priv_user4; SELECT grantor::regrole FROM pg_auth_members WHERE roleid = 'regress_priv_user1'::regrole and member = 'regress_priv_user4'::regrole;
RESET ROLE; REVOKE regress_priv_user2 FROM regress_priv_user3; REVOKE regress_priv_user1 FROM regress_priv_user2 CASCADE;
-- test GRANTED BY with DROP OWNED and REASSIGN OWNED GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; GRANT regress_priv_user1 TO regress_priv_user3 GRANTED BY regress_priv_user2; DROP ROLE regress_priv_user2; -- fail, dependency
REASSIGN OWNED BY regress_priv_user2 TO regress_priv_user4; DROP ROLE regress_priv_user2; -- still fail, REASSIGN OWNED doesn't help DROP OWNED BY regress_priv_user2; DROP ROLE regress_priv_user2; -- ok now, DROP OWNED does the job
-- test that removing granted role or grantee role removes dependency GRANT regress_priv_user1 TO regress_priv_user3 WITH ADMIN OPTION; GRANT regress_priv_user1 TO regress_priv_user4 GRANTED BY regress_priv_user3; DROP ROLE regress_priv_user3; -- should fail, dependency DROP ROLE regress_priv_user4; -- ok DROP ROLE regress_priv_user3; -- ok now GRANT regress_priv_user1 TO regress_priv_user5 WITH ADMIN OPTION; GRANT regress_priv_user1 TO regress_priv_user6 GRANTED BY regress_priv_user5; DROP ROLE regress_priv_user5; -- should fail, dependency DROP ROLE regress_priv_user1, regress_priv_user5; -- ok, despite order
-- recreate the roles we just dropped CREATE USER regress_priv_user1; CREATE USER regress_priv_user2; CREATE USER regress_priv_user3; CREATE USER regress_priv_user4; CREATE USER regress_priv_user5;
GRANT pg_read_all_data TO regress_priv_user6; GRANT pg_write_all_data TO regress_priv_user7; GRANT pg_read_all_settings TO regress_priv_user8 WITH ADMIN OPTION; GRANT regress_priv_user9 TO regress_priv_user8;
SET SESSION AUTHORIZATION regress_priv_user8; GRANT pg_read_all_settings TO regress_priv_user9 WITH ADMIN OPTION;
SET SESSION AUTHORIZATION regress_priv_user9; GRANT pg_read_all_settings TO regress_priv_user10;
SET SESSION AUTHORIZATION regress_priv_user8; REVOKE pg_read_all_settings FROM regress_priv_user10 GRANTED BY regress_priv_user9; REVOKE ADMIN OPTIONFOR pg_read_all_settings FROM regress_priv_user9; REVOKE pg_read_all_settings FROM regress_priv_user9;
RESET SESSION AUTHORIZATION; REVOKE regress_priv_user9 FROM regress_priv_user8; REVOKE ADMIN OPTIONFOR pg_read_all_settings FROM regress_priv_user8;
SET SESSION AUTHORIZATION regress_priv_user8; SET ROLE pg_read_all_settings;
RESET ROLE;
RESET SESSION AUTHORIZATION; REVOKESETOPTIONFOR pg_read_all_settings FROM regress_priv_user8; GRANT pg_read_all_stats TO regress_priv_user8 WITHSETFALSE;
SET SESSION AUTHORIZATION regress_priv_user8; SET ROLE pg_read_all_settings; -- fail, no SET option any more SET ROLE pg_read_all_stats; -- fail, granted without SET option
RESET ROLE;
RESET SESSION AUTHORIZATION;
-- test interaction of SET SESSION AUTHORIZATION and SET ROLE, -- as well as propagation of these settings to parallel workers GRANT regress_priv_user9 TO regress_priv_user8;
SET SESSION AUTHORIZATION regress_priv_user8; SET ROLE regress_priv_user9; SET debug_parallel_query = 0; SELECT session_user, current_role, current_user, current_setting('role') as role; SET debug_parallel_query = 1; SELECT session_user, current_role, current_user, current_setting('role') as role;
BEGIN; SET SESSION AUTHORIZATION regress_priv_user10; SET debug_parallel_query = 0; SELECT session_user, current_role, current_user, current_setting('role') as role; SET debug_parallel_query = 1; SELECT session_user, current_role, current_user, current_setting('role') as role;
ROLLBACK; SET debug_parallel_query = 0; SELECT session_user, current_role, current_user, current_setting('role') as role; SET debug_parallel_query = 1; SELECT session_user, current_role, current_user, current_setting('role') as role;
RESET SESSION AUTHORIZATION; -- session_user at this point is installation-dependent SET debug_parallel_query = 0; SELECT session_user = current_role as c_r_ok, session_user = current_useras c_u_ok, current_setting('role') as role; SET debug_parallel_query = 1; SELECT session_user = current_role as c_r_ok, session_user = current_useras c_u_ok, current_setting('role') as role;
RESET debug_parallel_query;
REVOKE pg_read_all_settings FROM regress_priv_user8;
DROP USER regress_priv_user10; DROP USER regress_priv_user9; DROP USER regress_priv_user8;
CREATEGROUP regress_priv_group1; CREATEGROUP regress_priv_group2 WITH ADMIN regress_priv_user1 USER regress_priv_user2;
ALTERGROUP regress_priv_group1 ADD USER regress_priv_user4;
GRANT regress_priv_group2 TO regress_priv_user2 GRANTED BY regress_priv_user1; SET SESSION AUTHORIZATION regress_priv_user3; ALTERGROUP regress_priv_group2 ADD USER regress_priv_user2; -- fail ALTERGROUP regress_priv_group2 DROP USER regress_priv_user2; -- fail SET SESSION AUTHORIZATION regress_priv_user1; ALTERGROUP regress_priv_group2 ADD USER regress_priv_user2; ALTERGROUP regress_priv_group2 ADD USER regress_priv_user2; -- duplicate ALTERGROUP regress_priv_group2 DROP USER regress_priv_user2; ALTER USER regress_priv_user2 PASSWORD 'verysecret'; -- not permitted
RESET SESSION AUTHORIZATION; ALTERGROUP regress_priv_group2 DROP USER regress_priv_user2; REVOKE ADMIN OPTIONFOR regress_priv_group2 FROM regress_priv_user1; GRANT regress_priv_group2 TO regress_priv_user4 WITH ADMIN OPTION;
-- prepare non-leakproof function for later CREATE FUNCTION leak(integer,integer) RETURNS boolean AS'int4lt'
LANGUAGE internal IMMUTABLE STRICT; -- but deliberately not LEAKPROOF ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1;
-- test owner privileges
GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY regress_priv_role; -- error, doesn't have ADMIN OPTION GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE; REVOKE ADMIN OPTIONFOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error REVOKE ADMIN OPTIONFOR regress_priv_role FROM regress_priv_user1 GRANTED BY regress_priv_user2; -- warning, noop REVOKE ADMIN OPTIONFOR regress_priv_role FROM regress_priv_user1 GRANTED BYCURRENT_USER; REVOKE regress_priv_role FROM regress_priv_user1 GRANTED BY CURRENT_ROLE; DROP ROLE regress_priv_role;
SET SESSION AUTHORIZATION regress_priv_user1; SELECT session_user, current_user;
CREATETABLE atest1 ( a int, b text ); SELECT * FROM atest1; INSERTINTO atest1 VALUES (1, 'one'); DELETEFROM atest1; UPDATE atest1 SET a = 1WHERE b = 'blech';
TRUNCATE atest1;
BEGIN; LOCK atest1 IN ACCESS EXCLUSIVE MODE; COMMIT;
REVOKEALLON atest1 FROM PUBLIC; SELECT * FROM atest1;
GRANTALLON atest1 TO regress_priv_user2; GRANTSELECTON atest1 TO regress_priv_user3, regress_priv_user4; SELECT * FROM atest1;
CREATETABLE atest2 (col1 varchar(10), col2 boolean); SELECT pg_get_acl('pg_class'::regclass, 'atest2'::regclass::oid, 0); GRANTSELECTON atest2 TO regress_priv_user2; GRANTUPDATEON atest2 TO regress_priv_user3; GRANTINSERTON atest2 TO regress_priv_user4 GRANTED BYCURRENT_USER; GRANT TRUNCATE ON atest2 TO regress_priv_user5 GRANTED BY CURRENT_ROLE; SELECT unnest(pg_get_acl('pg_class'::regclass, 'atest2'::regclass::oid, 0));
GRANT TRUNCATE ON atest2 TO regress_priv_user4 GRANTED BY regress_priv_user5; -- error
SET SESSION AUTHORIZATION regress_priv_user2; SELECT session_user, current_user;
-- try various combinations of queries on atest1 and atest2
SELECT * FROM atest1; -- ok SELECT * FROM atest2; -- ok INSERTINTO atest1 VALUES (2, 'two'); -- ok INSERTINTO atest2 VALUES ('foo', true); -- fail INSERTINTO atest1 SELECT1, b FROM atest1; -- ok UPDATE atest1 SET a = 1WHERE a = 2; -- ok UPDATE atest2 SET col2 = NOT col2; -- fail SELECT * FROM atest1 FORUPDATE; -- ok SELECT * FROM atest2 FORUPDATE; -- fail DELETEFROM atest2; -- fail
TRUNCATE atest2; -- fail
BEGIN; LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail COMMIT;
COPY atest2 FROM stdin; -- fail GRANTALLON atest1 TO PUBLIC; -- fail
-- checks in subquery, both ok SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) );
SET SESSION AUTHORIZATION regress_priv_user6; SELECT * FROM atest1; -- ok SELECT * FROM atest2; -- ok INSERTINTO atest2 VALUES ('foo', true); -- fail
SET SESSION AUTHORIZATION regress_priv_user7; SELECT * FROM atest1; -- fail SELECT * FROM atest2; -- fail INSERTINTO atest2 VALUES ('foo', true); -- ok UPDATE atest2 SET col2 = true; -- ok DELETEFROM atest2; -- ok
-- Make sure we are not able to modify system catalogs UPDATE pg_catalog.pg_class SET relname = '123'; -- fail DELETEFROM pg_catalog.pg_class; -- fail UPDATE pg_toast.pg_toast_1213 SET chunk_id = 1; -- fail
SET SESSION AUTHORIZATION regress_priv_user3; SELECT session_user, current_user;
SELECT * FROM atest1; -- ok SELECT * FROM atest2; -- fail INSERTINTO atest1 VALUES (2, 'two'); -- fail INSERTINTO atest2 VALUES ('foo', true); -- fail INSERTINTO atest1 SELECT1, b FROM atest1; -- fail UPDATE atest1 SET a = 1WHERE a = 2; -- fail UPDATE atest2 SET col2 = NULL; -- ok UPDATE atest2 SET col2 = NOT col2; -- fails; requires SELECT on atest2 UPDATE atest2 SET col2 = trueFROM atest1 WHERE atest1.a = 5; -- ok SELECT * FROM atest1 FORUPDATE; -- fail SELECT * FROM atest2 FORUPDATE; -- fail DELETEFROM atest2; -- fail
TRUNCATE atest2; -- fail
BEGIN; LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok COMMIT;
COPY atest2 FROM stdin; -- fail
-- checks in subquery, both fail SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) );
SET SESSION AUTHORIZATION regress_priv_user4;
COPY atest2 FROM stdin; -- ok
bar true
\. SELECT * FROM atest1; -- ok
-- test leaky-function protections in selfuncs
-- regress_priv_user1 will own a table and provide views for it. SET SESSION AUTHORIZATION regress_priv_user1;
CREATETABLE atest12 as SELECT x AS a, 10001 - x AS b FROM generate_series(1,10000) x; CREATEINDEXON atest12 (a); CREATEINDEXON atest12 (abs(a)); -- results below depend on having quite accurate stats for atest12, so... ALTERTABLE atest12 SET (autovacuum_enabled = off); SET default_statistics_target = 10000;
VACUUM ANALYZE atest12;
RESET default_statistics_target;
-- views with leaky operator CREATE VIEW atest12v AS SELECT * FROM atest12 WHERE b <<< 5; CREATE VIEW atest12sbv WITH (security_barrier=true) AS SELECT * FROM atest12 WHERE b <<< 5;
-- This plan should use nestloop, knowing that few rows will be selected. EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b;
-- And this one. EXPLAIN (COSTS OFF) SELECT * FROM atest12 x, atest12 y WHERE x.a = y.b and abs(y.a) <<< 5;
-- This should also be a nestloop, but the security barrier forces the inner -- scan to be materialized EXPLAIN (COSTS OFF) SELECT * FROM atest12sbv x, atest12sbv y WHERE x.a = y.b;
-- Check if regress_priv_user2 can break security. SET SESSION AUTHORIZATION regress_priv_user2;
-- These should not show any "leak" notices before failing. EXPLAIN (COSTS OFF) SELECT * FROM atest12 WHERE a >>> 0; EXPLAIN (COSTS OFF) SELECT * FROM atest12v WHERE a >>> 0; EXPLAIN (COSTS OFF) SELECT * FROM atest12sbv WHERE a >>> 0;
-- Now regress_priv_user1 grants access to regress_priv_user2 via the views. SET SESSION AUTHORIZATION regress_priv_user1; GRANTSELECTON atest12v TO PUBLIC; GRANTSELECTON atest12sbv TO PUBLIC; SET SESSION AUTHORIZATION regress_priv_user2;
-- These plans should continue to use a nestloop, since they execute with the -- privileges of the view owner. EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b; EXPLAIN (COSTS OFF) SELECT * FROM atest12sbv x, atest12sbv y WHERE x.a = y.b;
-- A non-security barrier view does not guard against information leakage. EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b and abs(y.a) <<< 5;
-- But a security barrier view isolates the leaky operator. EXPLAIN (COSTS OFF) SELECT * FROM atest12sbv x, atest12sbv y WHERE x.a = y.b and abs(y.a) <<< 5;
-- Now regress_priv_user1 grants sufficient access to regress_priv_user2. SET SESSION AUTHORIZATION regress_priv_user1; GRANTSELECT (a, b) ON atest12 TO PUBLIC; SET SESSION AUTHORIZATION regress_priv_user2;
-- regress_priv_user2 should continue to get a good row estimate. EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b;
-- But not for this, due to lack of table-wide permissions needed -- to make use of the expression index's statistics. EXPLAIN (COSTS OFF) SELECT * FROM atest12 x, atest12 y WHERE x.a = y.b and abs(y.a) <<< 5;
-- clean up (regress_priv_user1's objects are all dropped later) DROP FUNCTION leak2(integer, integer) CASCADE;
-- groups
SET SESSION AUTHORIZATION regress_priv_user3; CREATETABLE atest3 (one int, two int, three int); GRANTDELETEON atest3 TOGROUP regress_priv_group2;
SET SESSION AUTHORIZATION regress_priv_user1;
SELECT * FROM atest3; -- fail DELETEFROM atest3; -- ok
BEGIN;
RESET SESSION AUTHORIZATION; ALTER ROLE regress_priv_user1 NOINHERIT; SET SESSION AUTHORIZATION regress_priv_user1;
SAVEPOINT s1; DELETEFROM atest3; -- ok because grant-level option is unchanged
ROLLBACK TO s1;
RESET SESSION AUTHORIZATION; GRANT regress_priv_group2 TO regress_priv_user1 WITH INHERIT FALSE; SET SESSION AUTHORIZATION regress_priv_user1; DELETEFROM atest3; -- fail
ROLLBACK TO s1;
RESET SESSION AUTHORIZATION; REVOKE INHERIT OPTIONFOR regress_priv_group2 FROM regress_priv_user1; SET SESSION AUTHORIZATION regress_priv_user1; DELETEFROM atest3; -- also fail
ROLLBACK;
-- views
SET SESSION AUTHORIZATION regress_priv_user3;
CREATE VIEW atestv1 ASSELECT * FROM atest1; -- ok /* The next *should* fail, but it's not implemented that way yet. */ CREATE VIEW atestv2 ASSELECT * FROM atest2; CREATE VIEW atestv3 ASSELECT * FROM atest3; -- ok /* Empty view is a corner case that failed in 9.2. */ CREATE VIEW atestv0 ASSELECT0as x WHEREfalse; -- ok
SELECT * FROM atestv1; -- ok SELECT * FROM atestv2; -- fail GRANTSELECTON atestv1, atestv3 TO regress_priv_user4; GRANTSELECTON atestv2 TO regress_priv_user2;
SET SESSION AUTHORIZATION regress_priv_user4;
SELECT * FROM atestv1; -- ok SELECT * FROM atestv2; -- fail SELECT * FROM atestv3; -- ok SELECT * FROM atestv0; -- fail
-- Appendrels excluded by constraints failed to check permissions in 8.4-9.2. select * from
((select a.q1 as x from int8_tbl a offset 0) unionall
(select b.q2 as x from int8_tbl b offset 0)) ss wherefalse;
set constraint_exclusion = on; select * from
((select a.q1 as x, random() from int8_tbl a where q1 > 0) unionall
(select b.q2 as x, random() from int8_tbl b where q2 > 0)) ss where x < 0;
reset constraint_exclusion;
CREATE VIEW atestv4 ASSELECT * FROM atestv3; -- nested view SELECT * FROM atestv4; -- ok GRANTSELECTON atestv4 TO regress_priv_user2;
SET SESSION AUTHORIZATION regress_priv_user2;
-- Two complex cases:
SELECT * FROM atestv3; -- fail SELECT * FROM atestv4; -- ok (even though regress_priv_user2 cannot access underlying atestv3)
SELECT * FROM atest2; -- ok SELECT * FROM atestv2; -- fail (even though regress_priv_user2 can access underlying atest2)
-- Test column level permissions
SET SESSION AUTHORIZATION regress_priv_user1; CREATETABLE atest5 (one int, two intunique, three int, four intunique); CREATETABLE atest6 (one int, two int, blue int); GRANTSELECT (one), INSERT (two), UPDATE (three) ON atest5 TO regress_priv_user4; GRANTALL (one) ON atest5 TO regress_priv_user3; SELECT unnest(pg_get_acl('pg_class'::regclass, 'atest5'::regclass::oid, 1)); SELECT unnest(pg_get_acl('pg_class'::regclass, 'atest5'::regclass::oid, 2)); SELECT unnest(pg_get_acl('pg_class'::regclass, 'atest5'::regclass::oid, 3)); SELECT unnest(pg_get_acl('pg_class'::regclass, 'atest5'::regclass::oid, 4));
INSERTINTO atest5 VALUES (1,2,3);
SET SESSION AUTHORIZATION regress_priv_user4; SELECT * FROM atest5; -- fail SELECT one FROM atest5; -- ok
COPY atest5 (one) TO stdout; -- ok SELECT two FROM atest5; -- fail
COPY atest5 (two) TO stdout; -- fail SELECT atest5 FROM atest5; -- fail
COPY atest5 (one,two) TO stdout; -- fail SELECT1FROM atest5; -- ok SELECT1FROM atest5 a JOIN atest5 b USING (one); -- ok SELECT1FROM atest5 a JOIN atest5 b USING (two); -- fail SELECT1FROM atest5 a NATURALJOIN atest5 b; -- fail SELECT * FROM (atest5 a JOIN atest5 b USING (one)) j; -- fail SELECT j.* FROM (atest5 a JOIN atest5 b USING (one)) j; -- fail SELECT (j.*) ISNULLFROM (atest5 a JOIN atest5 b USING (one)) j; -- fail SELECT one FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)) j; -- ok SELECT j.one FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)) j; -- ok SELECT two FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)) j; -- fail SELECT j.two FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)) j; -- fail SELECT y FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)) j; -- fail SELECT j.y FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)) j; -- fail SELECT * FROM (atest5 a JOIN atest5 b USING (one)); -- fail SELECT a.* FROM (atest5 a JOIN atest5 b USING (one)); -- fail SELECT (a.*) ISNULLFROM (atest5 a JOIN atest5 b USING (one)); -- fail SELECT two FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT a.two FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT y FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT b.y FROM (atest5 a JOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT y FROM (atest5 a LEFTJOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT b.y FROM (atest5 a LEFTJOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT y FROM (atest5 a FULL JOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT b.y FROM (atest5 a FULL JOIN atest5 b(one,x,y,z) USING (one)); -- fail SELECT1FROM atest5 WHERE two = 2; -- fail SELECT * FROM atest1, atest5; -- fail SELECT atest1.* FROM atest1, atest5; -- ok SELECT atest1.*,atest5.one FROM atest1, atest5; -- ok SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.two); -- fail SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.one); -- ok SELECT one, two FROM atest5; -- fail
SET SESSION AUTHORIZATION regress_priv_user1; GRANTSELECT (one,two) ON atest6 TO regress_priv_user4;
SET SESSION AUTHORIZATION regress_priv_user4; SELECT one, two FROM atest5 NATURALJOIN atest6; -- fail still
SET SESSION AUTHORIZATION regress_priv_user1; GRANTSELECT (two) ON atest5 TO regress_priv_user4;
SET SESSION AUTHORIZATION regress_priv_user4; SELECT one, two FROM atest5 NATURALJOIN atest6; -- ok now
-- test column-level privileges for INSERT and UPDATE INSERTINTO atest5 (two) VALUES (3); -- ok
COPY atest5 FROM stdin; -- fail
COPY atest5 (two) FROM stdin; -- ok 1
\. INSERTINTO atest5 (three) VALUES (4); -- fail INSERTINTO atest5 VALUES (5,5,5); -- fail UPDATE atest5 SET three = 10; -- ok UPDATE atest5 SET one = 8; -- fail UPDATE atest5 SET three = 5, one = 2; -- fail -- Check that column level privs are enforced in RETURNING -- Ok. INSERTINTO atest5(two) VALUES (6) ON CONFLICT (two) DO UPDATEset three = 10; -- Error. No SELECT on column three. INSERTINTO atest5(two) VALUES (6) ON CONFLICT (two) DO UPDATEset three = 10 RETURNING atest5.three; -- Ok. May SELECT on column "one": INSERTINTO atest5(two) VALUES (6) ON CONFLICT (two) DO UPDATEset three = 10 RETURNING atest5.one; -- Check that column level privileges are enforced for EXCLUDED -- Ok. we may select one INSERTINTO atest5(two) VALUES (6) ON CONFLICT (two) DO UPDATEset three = EXCLUDED.one; -- Error. No select rights on three INSERTINTO atest5(two) VALUES (6) ON CONFLICT (two) DO UPDATEset three = EXCLUDED.three; INSERTINTO atest5(two) VALUES (6) ON CONFLICT (two) DO UPDATEset one = 8; -- fails (due to UPDATE) INSERTINTO atest5(three) VALUES (4) ON CONFLICT (two) DO UPDATEset three = 10; -- fails (due to INSERT)
-- Check that the columns in the inference require select privileges INSERTINTO atest5(four) VALUES (4); -- fail
SET SESSION AUTHORIZATION regress_priv_user1; GRANTINSERT (four) ON atest5 TO regress_priv_user4; SET SESSION AUTHORIZATION regress_priv_user4;
INSERTINTO atest5(four) VALUES (4) ON CONFLICT (four) DO UPDATEset three = 3; -- fails (due to SELECT) INSERTINTO atest5(four) VALUES (4) ON CONFLICT ONCONSTRAINT atest5_four_key DO UPDATEset three = 3; -- fails (due to SELECT) INSERTINTO atest5(four) VALUES (4); -- ok
SET SESSION AUTHORIZATION regress_priv_user1; GRANTSELECT (four) ON atest5 TO regress_priv_user4; SET SESSION AUTHORIZATION regress_priv_user4;
INSERTINTO atest5(four) VALUES (4) ON CONFLICT (four) DO UPDATEset three = 3; -- ok INSERTINTO atest5(four) VALUES (4) ON CONFLICT ONCONSTRAINT atest5_four_key DO UPDATEset three = 3; -- ok
SET SESSION AUTHORIZATION regress_priv_user1; REVOKEALL (one) ON atest5 FROM regress_priv_user4; GRANTSELECT (one,two,blue) ON atest6 TO regress_priv_user4;
SET SESSION AUTHORIZATION regress_priv_user4; SELECT one FROM atest5; -- fail UPDATE atest5 SET one = 1; -- fail SELECT atest6 FROM atest6; -- ok
COPY atest6 TO stdout; -- ok
-- test column privileges with MERGE SET SESSION AUTHORIZATION regress_priv_user1; CREATETABLE mtarget (a int, b text); CREATETABLE msource (a int, b text); INSERTINTO mtarget VALUES (1, 'init1'), (2, 'init2'); INSERTINTO msource VALUES (1, 'source1'), (2, 'source2'), (3, 'source3');
GRANTSELECT (a) ON msource TO regress_priv_user4; GRANTSELECT (a) ON mtarget TO regress_priv_user4; GRANTINSERT (a,b) ON mtarget TO regress_priv_user4; GRANTUPDATE (b) ON mtarget TO regress_priv_user4;
SET SESSION AUTHORIZATION regress_priv_user4;
-- -- test source privileges --
-- fail (no SELECT priv on s.b)
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED THEN UPDATESET b = s.b WHENNOT MATCHED THEN INSERTVALUES (a, NULL);
-- fail (s.b used in the INSERTed values)
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED THEN UPDATESET b = 'x' WHENNOT MATCHED THEN INSERTVALUES (a, b);
-- fail (s.b used in the WHEN quals)
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED AND s.b = 'x'THEN UPDATESET b = 'x' WHENNOT MATCHED THEN INSERTVALUES (a, NULL);
-- this should be ok since only s.a is accessed
BEGIN;
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED THEN UPDATESET b = 'ok' WHENNOT MATCHED THEN INSERTVALUES (a, NULL);
ROLLBACK;
SET SESSION AUTHORIZATION regress_priv_user1; GRANTSELECT (b) ON msource TO regress_priv_user4; SET SESSION AUTHORIZATION regress_priv_user4;
-- should now be ok
BEGIN;
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED THEN UPDATESET b = s.b WHENNOT MATCHED THEN INSERTVALUES (a, b);
ROLLBACK;
-- -- test target privileges --
-- fail (no SELECT priv on t.b)
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED THEN UPDATESET b = t.b WHENNOT MATCHED THEN INSERTVALUES (a, NULL);
-- fail (no UPDATE on t.a)
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED THEN UPDATESET b = s.b, a = t.a + 1 WHENNOT MATCHED THEN INSERTVALUES (a, b);
-- fail (no SELECT on t.b)
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED AND t.b ISNOTNULLTHEN UPDATESET b = s.b WHENNOT MATCHED THEN INSERTVALUES (a, b);
-- ok
BEGIN;
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED THEN UPDATESET b = s.b;
ROLLBACK;
-- fail (no DELETE)
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED AND t.b ISNOTNULLTHEN DELETE;
-- grant delete privileges SET SESSION AUTHORIZATION regress_priv_user1; GRANTDELETEON mtarget TO regress_priv_user4; -- should be ok now
BEGIN;
MERGE INTO mtarget t USING msource s ON t.a = s.a WHEN MATCHED AND t.b ISNOTNULLTHEN DELETE;
ROLLBACK;
-- check error reporting with column privs SET SESSION AUTHORIZATION regress_priv_user1; CREATETABLE t1 (c1 int, c2 int, c3 intcheck (c3 < 5), primarykey (c1, c2)); GRANTSELECT (c1) ON t1 TO regress_priv_user2; GRANTINSERT (c1, c2, c3) ON t1 TO regress_priv_user2; GRANTUPDATE (c1, c2, c3) ON t1 TO regress_priv_user2;
SET SESSION AUTHORIZATION regress_priv_user2; INSERTINTO t1 (c1, c2) VALUES (1, 1); -- fail, but row not shown UPDATE t1 SET c2 = 1; -- fail, but row not shown INSERTINTO t1 (c1, c2) VALUES (null, null); -- fail, but see columns being inserted INSERTINTO t1 (c3) VALUES (null); -- fail, but see columns being inserted or have SELECT INSERTINTO t1 (c1) VALUES (5); -- fail, but see columns being inserted or have SELECT UPDATE t1 SET c3 = 10; -- fail, but see columns with SELECT rights, or being modified
SET SESSION AUTHORIZATION regress_priv_user1; DROPTABLE t1;
-- check error reporting with column privs on a partitioned table CREATETABLE errtst(a text, b text NOTNULL, c text, secret1 text, secret2 text) PARTITION BY LIST (a); CREATETABLE errtst_part_1(secret2 text, c text, a text, b text NOTNULL, secret1 text); CREATETABLE errtst_part_2(secret1 text, secret2 text, a text, c text, b text NOTNULL);
GRANTSELECT (a, b, c) ONTABLE errtst TO regress_priv_user2; GRANTUPDATE (a, b, c) ONTABLE errtst TO regress_priv_user2; GRANTINSERT (a, b, c) ONTABLE errtst TO regress_priv_user2;
INSERTINTO errtst_part_1 (a, b, c, secret1, secret2) VALUES ('aaa', 'bbb', 'ccc', 'the body', 'is in the attic');
SET SESSION AUTHORIZATION regress_priv_user2;
-- Perform a few updates that violate the NOT NULL constraint. Make sure -- the error messages don't leak the secret fields.
-- simple insert. INSERTINTO errtst (a, b) VALUES ('aaa', NULL); -- simple update. UPDATE errtst SET b = NULL; -- partitioning key is updated, doesn't move the row. UPDATE errtst SET a = 'aaa', b = NULL; -- row is moved to another partition. UPDATE errtst SET a = 'aaaa', b = NULL;
-- row is moved to another partition. This differs from the previous case in -- that the new partition is excluded by constraint exclusion, so its -- ResultRelInfo is not created at ExecInitModifyTable, but needs to be -- constructed on the fly when the updated tuple is routed to it. UPDATE errtst SET a = 'aaaa', b = NULLWHERE a = 'aaa';
SET SESSION AUTHORIZATION regress_priv_user1; DROPTABLE errtst;
-- test column-level privileges when involved with DELETE SET SESSION AUTHORIZATION regress_priv_user1; ALTERTABLE atest6 ADDCOLUMN three integer; GRANTDELETEON atest5 TO regress_priv_user3; GRANTSELECT (two) ON atest5 TO regress_priv_user3; REVOKEALL (one) ON atest5 FROM regress_priv_user3; GRANTSELECT (one) ON atest5 TO regress_priv_user4;
SET SESSION AUTHORIZATION regress_priv_user4; SELECT atest6 FROM atest6; -- fail SELECT one FROM atest5 NATURALJOIN atest6; -- fail
SET SESSION AUTHORIZATION regress_priv_user1; ALTERTABLE atest6 DROPCOLUMN three;
SET SESSION AUTHORIZATION regress_priv_user4; SELECT atest6 FROM atest6; -- ok SELECT one FROM atest5 NATURALJOIN atest6; -- ok
SET SESSION AUTHORIZATION regress_priv_user1; ALTERTABLE atest6 DROPCOLUMN two; REVOKESELECT (one,blue) ON atest6 FROM regress_priv_user4;
SET SESSION AUTHORIZATION regress_priv_user4; SELECT * FROM atest6; -- fail SELECT1FROM atest6; -- fail
SET SESSION AUTHORIZATION regress_priv_user3; DELETEFROM atest5 WHERE one = 1; -- fail DELETEFROM atest5 WHERE two = 2; -- ok
-- check inheritance cases SET SESSION AUTHORIZATION regress_priv_user1; CREATETABLE atestp1 (f1 int, f2 int); CREATETABLE atestp2 (fx int, fy int); CREATETABLE atestc (fz int) INHERITS (atestp1, atestp2); GRANTSELECT(fx,fy,tableoid) ON atestp2 TO regress_priv_user2; GRANTSELECT(fx) ON atestc TO regress_priv_user2;
SET SESSION AUTHORIZATION regress_priv_user2; SELECT fx FROM atestp2; -- ok SELECT fy FROM atestp2; -- ok SELECT atestp2 FROM atestp2; -- ok SELECT tableoid FROM atestp2; -- ok SELECT fy FROM atestc; -- fail
SET SESSION AUTHORIZATION regress_priv_user1; GRANTSELECT(fy,tableoid) ON atestc TO regress_priv_user2;
SET SESSION AUTHORIZATION regress_priv_user2; SELECT fx FROM atestp2; -- still ok SELECT fy FROM atestp2; -- ok SELECT atestp2 FROM atestp2; -- ok SELECT tableoid FROM atestp2; -- ok
-- child's permissions do not apply when operating on parent SET SESSION AUTHORIZATION regress_priv_user1; REVOKEALLON atestc FROM regress_priv_user2; GRANTALLON atestp1 TO regress_priv_user2; SET SESSION AUTHORIZATION regress_priv_user2; SELECT f2 FROM atestp1; -- ok SELECT f2 FROM atestc; -- fail DELETEFROM atestp1; -- ok DELETEFROM atestc; -- fail UPDATE atestp1 SET f1 = 1; -- ok UPDATE atestc SET f1 = 1; -- fail
TRUNCATE atestp1; -- ok
TRUNCATE atestc; -- fail
BEGIN; LOCK atestp1;
END;
BEGIN; LOCK atestc;
END;
-- privileges on functions, languages
-- switch to superuser
\c -
REVOKEALL PRIVILEGES ON LANGUAGE sqlFROM PUBLIC; GRANTUSAGEON LANGUAGE sqlTO regress_priv_user1; -- ok GRANTUSAGEON LANGUAGE c TO PUBLIC; -- fail
SET SESSION AUTHORIZATION regress_priv_user1; GRANTUSAGEON LANGUAGE sqlTO regress_priv_user2; -- fail CREATE FUNCTION priv_testfunc1(int) RETURNS intAS'select 2 * $1;' LANGUAGE sql; CREATE FUNCTION priv_testfunc2(int) RETURNS intAS'select 3 * $1;' LANGUAGE sql; CREATE AGGREGATE priv_testagg1(int) (sfunc = int4pl, stype = int4); CREATEPROCEDURE priv_testproc1(int) AS'select $1;' LANGUAGE sql;
REVOKEALLON FUNCTION priv_testfunc1(int), priv_testfunc2(int), priv_testagg1(int) FROM PUBLIC; GRANT EXECUTE ON FUNCTION priv_testfunc1(int), priv_testfunc2(int), priv_testagg1(int) TO regress_priv_user2; REVOKEALLON FUNCTION priv_testproc1(int) FROM PUBLIC; -- fail, not a function REVOKEALLONPROCEDURE priv_testproc1(int) FROM PUBLIC; GRANT EXECUTE ONPROCEDURE priv_testproc1(int) TO regress_priv_user2; GRANTUSAGEON FUNCTION priv_testfunc1(int) TO regress_priv_user3; -- semantic error GRANTUSAGEON FUNCTION priv_testagg1(int) TO regress_priv_user3; -- semantic error GRANTUSAGEONPROCEDURE priv_testproc1(int) TO regress_priv_user3; -- semantic error GRANTALL PRIVILEGES ON FUNCTION priv_testfunc1(int) TO regress_priv_user4; GRANTALL PRIVILEGES ON FUNCTION priv_testfunc_nosuch(int) TO regress_priv_user4; GRANTALL PRIVILEGES ON FUNCTION priv_testagg1(int) TO regress_priv_user4; GRANTALL PRIVILEGES ONPROCEDURE priv_testproc1(int) TO regress_priv_user4;
CREATE FUNCTION priv_testfunc4(boolean) RETURNS text AS'select col1 from atest2 where col2 = $1;'
LANGUAGE sql SECURITY DEFINER; GRANT EXECUTE ON FUNCTION priv_testfunc4(boolean) TO regress_priv_user3;
SET SESSION AUTHORIZATION regress_priv_user2; SELECT priv_testfunc1(5), priv_testfunc2(5); -- ok CREATE FUNCTION priv_testfunc3(int) RETURNS intAS'select 2 * $1;' LANGUAGE sql; -- fail SELECT priv_testagg1(x) FROM (VALUES (1), (2), (3)) _(x); -- ok CALL priv_testproc1(6); -- ok
SET SESSION AUTHORIZATION regress_priv_user3; SELECT priv_testfunc1(5); -- fail SELECT priv_testagg1(x) FROM (VALUES (1), (2), (3)) _(x); -- fail CALL priv_testproc1(6); -- fail SELECT col1 FROM atest2 WHERE col2 = true; -- fail SELECT priv_testfunc4(true); -- ok
SET SESSION AUTHORIZATION regress_priv_user4; SELECT priv_testfunc1(5); -- ok SELECT priv_testagg1(x) FROM (VALUES (1), (2), (3)) _(x); -- ok CALL priv_testproc1(6); -- ok
DROP FUNCTION priv_testfunc1(int); -- fail DROP AGGREGATE priv_testagg1(int); -- fail DROPPROCEDURE priv_testproc1(int); -- fail
\c -
DROP FUNCTION priv_testfunc1(int); -- ok -- restore to sanity GRANTALL PRIVILEGES ON LANGUAGE sqlTO PUBLIC;
-- verify privilege checks on array-element coercions
BEGIN; SELECT'{1}'::int4[]::int8[]; REVOKEALLON FUNCTION int8(integer) FROM PUBLIC; SELECT'{1}'::int4[]::int8[]; --superuser, succeed SET SESSION AUTHORIZATION regress_priv_user4; SELECT'{1}'::int4[]::int8[]; --other user, fail
ROLLBACK;
-- privileges on types
-- switch to superuser
\c -
CREATE TYPE priv_testtype1 AS (a int, b text); REVOKEUSAGEON TYPE priv_testtype1 FROM PUBLIC; GRANTUSAGEON TYPE priv_testtype1 TO regress_priv_user2; GRANTUSAGEON TYPE _priv_testtype1 TO regress_priv_user2; -- fail GRANTUSAGEON DOMAIN priv_testtype1 TO regress_priv_user2; -- fail
CREATE DOMAIN priv_testdomain1 ASint; REVOKEUSAGEon DOMAIN priv_testdomain1 FROM PUBLIC; GRANTUSAGEON DOMAIN priv_testdomain1 TO regress_priv_user2; GRANTUSAGEON TYPE priv_testdomain1 TO regress_priv_user2; -- ok
CREATE DOMAIN priv_testdomain2a AS priv_testdomain1;
CREATE DOMAIN priv_testdomain3a ASint; CREATE FUNCTION castfunc(int) RETURNS priv_testdomain3a AS $$ SELECT $1::priv_testdomain3a $$ LANGUAGE SQL; CREATE CAST (priv_testdomain1 AS priv_testdomain3a) WITH FUNCTION castfunc(int); DROP FUNCTION castfunc(int) CASCADE; DROP DOMAIN priv_testdomain3a;
CREATE FUNCTION priv_testfunc5a(a priv_testdomain1) RETURNS int LANGUAGE SQLAS $$ SELECT $1 $$; CREATE FUNCTION priv_testfunc6a(b int) RETURNS priv_testdomain1 LANGUAGE SQLAS $$ SELECT $1::priv_testdomain1 $$;
CREATE DOMAIN priv_testdomain2b AS priv_testdomain1;
CREATE DOMAIN priv_testdomain3b ASint; CREATE FUNCTION castfunc(int) RETURNS priv_testdomain3b AS $$ SELECT $1::priv_testdomain3b $$ LANGUAGE SQL; CREATE CAST (priv_testdomain1 AS priv_testdomain3b) WITH FUNCTION castfunc(int);
CREATE FUNCTION priv_testfunc5b(a priv_testdomain1) RETURNS int LANGUAGE SQLAS $$ SELECT $1 $$; CREATE FUNCTION priv_testfunc6b(b int) RETURNS priv_testdomain1 LANGUAGE SQLAS $$ SELECT $1::priv_testdomain1 $$;
CREATETABLE test5b (a int, b priv_testdomain1); CREATETABLE test6b OF priv_testtype1; CREATETABLE test10b (a int[], b priv_testtype1[]);
CREATETABLE test9b (a int, b int); ALTERTABLE test9b ADDCOLUMN c priv_testdomain1; ALTERTABLE test9b ALTERCOLUMN b TYPE priv_testdomain1;
CREATE TYPE test7b AS (a int, b priv_testdomain1);
CREATE TYPE test8b AS (a int, b int); ALTER TYPE test8b ADD ATTRIBUTE c priv_testdomain1; ALTER TYPE test8b ALTER ATTRIBUTE b TYPE priv_testdomain1;
CREATETABLE test11b AS (SELECT1::priv_testdomain1 AS a);
REVOKEALLON TYPE priv_testtype1 FROM PUBLIC;
\c - DROP AGGREGATE priv_testagg1b(priv_testdomain1); DROP DOMAIN priv_testdomain2b; DROP OPERATOR !! (NONE, priv_testdomain1); DROP FUNCTION priv_testfunc5b(a priv_testdomain1); DROP FUNCTION priv_testfunc6b(b int); DROPTABLE test5b; DROPTABLE test6b; DROPTABLE test9b; DROPTABLE test10b; DROP TYPE test7b; DROP TYPE test8b; DROP CAST (priv_testdomain1 AS priv_testdomain3b); DROP FUNCTION castfunc(int) CASCADE; DROP DOMAIN priv_testdomain3b; DROPTABLE test11b;
DROP TYPE priv_testtype1; -- ok DROP DOMAIN priv_testdomain1; -- ok
-- truncate SET SESSION AUTHORIZATION regress_priv_user5;
TRUNCATE atest2; -- ok
TRUNCATE atest3; -- fail
select has_table_privilege(t2.oid,'pg_authid','update') from (select oid from pg_roles where rolname = current_user) as t2; select has_table_privilege(t2.oid,'pg_authid','delete') from (select oid from pg_roles where rolname = current_user) as t2;
select has_table_privilege(current_user,t1.oid,'references') from (select oid from pg_class where relname = 'pg_authid') as t1;
select has_table_privilege(t2.oid,t1.oid,'select') from (select oid from pg_class where relname = 'pg_authid') as t1,
(select oid from pg_roles where rolname = current_user) as t2; select has_table_privilege(t2.oid,t1.oid,'insert') from (select oid from pg_class where relname = 'pg_authid') as t1,
(select oid from pg_roles where rolname = current_user) as t2;
select has_table_privilege(t1.oid,'select') from (select oid from pg_class where relname = 'pg_authid') as t1; select has_table_privilege(t1.oid,'trigger') from (select oid from pg_class where relname = 'pg_authid') as t1;
-- non-superuser SET SESSION AUTHORIZATION regress_priv_user3;
select has_table_privilege(t2.oid,'pg_class','update') from (select oid from pg_roles where rolname = current_user) as t2; select has_table_privilege(t2.oid,'pg_class','delete') from (select oid from pg_roles where rolname = current_user) as t2;
select has_table_privilege(current_user,t1.oid,'references') from (select oid from pg_class where relname = 'pg_class') as t1;
select has_table_privilege(t2.oid,t1.oid,'select') from (select oid from pg_class where relname = 'pg_class') as t1,
(select oid from pg_roles where rolname = current_user) as t2; select has_table_privilege(t2.oid,t1.oid,'insert') from (select oid from pg_class where relname = 'pg_class') as t1,
(select oid from pg_roles where rolname = current_user) as t2;
select has_table_privilege(t1.oid,'select') from (select oid from pg_class where relname = 'pg_class') as t1; select has_table_privilege(t1.oid,'trigger') from (select oid from pg_class where relname = 'pg_class') as t1;
select has_table_privilege(t2.oid,'atest1','update') from (select oid from pg_roles where rolname = current_user) as t2; select has_table_privilege(t2.oid,'atest1','delete') from (select oid from pg_roles where rolname = current_user) as t2;
select has_table_privilege(current_user,t1.oid,'references') from (select oid from pg_class where relname = 'atest1') as t1;
select has_table_privilege(t2.oid,t1.oid,'select') from (select oid from pg_class where relname = 'atest1') as t1,
(select oid from pg_roles where rolname = current_user) as t2; select has_table_privilege(t2.oid,t1.oid,'insert') from (select oid from pg_class where relname = 'atest1') as t1,
(select oid from pg_roles where rolname = current_user) as t2;
select has_table_privilege(t1.oid,'select') from (select oid from pg_class where relname = 'atest1') as t1; select has_table_privilege(t1.oid,'trigger') from (select oid from pg_class where relname = 'atest1') as t1;
GRANTSELECTON atest4 TO regress_priv_user2 WITHGRANTOPTION; GRANTUPDATEON atest4 TO regress_priv_user2; GRANTSELECTON atest4 TOGROUP regress_priv_group1 WITHGRANTOPTION;
SET SESSION AUTHORIZATION regress_priv_user2;
GRANTSELECTON atest4 TO regress_priv_user3; GRANTUPDATEON atest4 TO regress_priv_user3; -- fail
SET SESSION AUTHORIZATION regress_priv_user1;
REVOKESELECTON atest4 FROM regress_priv_user3; -- does nothing SELECT has_table_privilege('regress_priv_user3', 'atest4', 'SELECT'); -- true REVOKESELECTON atest4 FROM regress_priv_user2; -- fail REVOKEGRANTOPTIONFORSELECTON atest4 FROM regress_priv_user2 CASCADE; -- ok SELECT has_table_privilege('regress_priv_user2', 'atest4', 'SELECT'); -- true SELECT has_table_privilege('regress_priv_user3', 'atest4', 'SELECT'); -- false
SELECT has_table_privilege('regress_priv_user1', 'atest4', 'SELECT WITH GRANT OPTION'); -- true
-- security-restricted operations
\c - CREATE ROLE regress_sro_user;
-- Check that index expressions and predicates are run as the table's owner
-- A dummy index function checking current_user CREATE FUNCTION sro_ifun(int) RETURNS intAS $$
BEGIN -- Below we set the table's owner to regress_sro_user
ASSERT current_user = 'regress_sro_user',
format('sro_ifun(%s) called by %s', $1, current_user); RETURN $1;
END;
$$ LANGUAGE plpgsql IMMUTABLE; -- Create a table owned by regress_sro_user CREATETABLE sro_tab (a int); ALTERTABLE sro_tab OWNER TO regress_sro_user; INSERTINTO sro_tab VALUES (1), (2), (3); -- Create an expression index with a predicate CREATEINDEX sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0))) WHERE sro_ifun(a + 10) > sro_ifun(10); DROPINDEX sro_idx; -- Do the same concurrently CREATEINDEX CONCURRENTLY sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0))) WHERE sro_ifun(a + 10) > sro_ifun(10); -- REINDEX
REINDEX TABLE sro_tab;
REINDEX INDEX sro_idx;
REINDEX TABLE CONCURRENTLY sro_tab; DROPINDEX sro_idx; -- CLUSTER CREATEINDEX sro_cluster_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)));
CLUSTER sro_tab USING sro_cluster_idx; DROPINDEX sro_cluster_idx; -- BRIN index CREATEINDEX sro_brin ON sro_tab USING brin ((sro_ifun(a) + sro_ifun(0))); SELECT brin_desummarize_range('sro_brin', 0); SELECT brin_summarize_range('sro_brin', 0); DROPTABLE sro_tab; -- Check with a partitioned table CREATETABLE sro_ptab (a int) PARTITION BY RANGE (a); ALTERTABLE sro_ptab OWNER TO regress_sro_user; CREATETABLE sro_part PARTITION OF sro_ptab FORVALUESFROM (1) TO (10); ALTERTABLE sro_part OWNER TO regress_sro_user; INSERTINTO sro_ptab VALUES (1), (2), (3); CREATEINDEX sro_pidx ON sro_ptab ((sro_ifun(a) + sro_ifun(0))) WHERE sro_ifun(a + 10) > sro_ifun(10);
REINDEX TABLE sro_ptab;
REINDEX INDEX CONCURRENTLY sro_pidx;
SET SESSION AUTHORIZATION regress_sro_user; CREATE FUNCTION unwanted_grant() RETURNS void LANGUAGE sqlAS 'GRANT regress_priv_group2 TO regress_sro_user'; CREATE FUNCTION mv_action() RETURNS bool LANGUAGE sqlAS 'DECLARE c CURSOR WITH HOLD FOR SELECT public.unwanted_grant(); SELECT true'; -- REFRESH of this MV will queue a GRANT at end of transaction CREATE MATERIALIZED VIEW sro_mv ASSELECT mv_action() WITH NO DATA;
REFRESH MATERIALIZED VIEW sro_mv;
\c -
REFRESH MATERIALIZED VIEW sro_mv;
SET SESSION AUTHORIZATION regress_sro_user; -- INSERT to this table will queue a GRANT at end of transaction CREATETABLE sro_trojan_table (); CREATE FUNCTION sro_trojan() RETURNS trigger LANGUAGE plpgsql AS 'BEGIN PERFORM public.unwanted_grant(); RETURN NULL; END'; CREATECONSTRAINTTRIGGER t AFTER INSERTON sro_trojan_table
INITIALLY DEFERRED FOREACH ROW EXECUTE PROCEDURE sro_trojan(); -- Now, REFRESH will issue such an INSERT, queueing the GRANT CREATEORREPLACE FUNCTION mv_action() RETURNS bool LANGUAGE sqlAS 'INSERT INTO public.sro_trojan_table DEFAULT VALUES; SELECT true';
REFRESH MATERIALIZED VIEW sro_mv;
\c -
REFRESH MATERIALIZED VIEW sro_mv;
BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT;
-- REFRESH MATERIALIZED VIEW CONCURRENTLY use of eval_const_expressions() SET SESSION AUTHORIZATION regress_sro_user; CREATE FUNCTION unwanted_grant_nofail(int) RETURNS int
IMMUTABLE LANGUAGE plpgsql AS $$
BEGIN
PERFORM public.unwanted_grant();
RAISE WARNING 'owned'; RETURN1;
EXCEPTION WHEN OTHERS THEN RETURN2;
END$$; CREATE MATERIALIZED VIEW sro_index_mv ASSELECT1AS c; CREATEUNIQUEINDEXON sro_index_mv (c) WHERE unwanted_grant_nofail(1) > 0;
\c -
REFRESH MATERIALIZED VIEW CONCURRENTLY sro_index_mv;
REFRESH MATERIALIZED VIEW sro_index_mv;
DROP OWNED BY regress_sro_user; DROP ROLE regress_sro_user;
-- Admin options
SET SESSION AUTHORIZATION regress_priv_user4; CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS 'GRANT regress_priv_group2 TO regress_priv_user5'; GRANT regress_priv_group2 TO regress_priv_user5; -- ok: had ADMIN OPTION SET ROLE regress_priv_group2; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE suspended privilege
SET SESSION AUTHORIZATION regress_priv_user1; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no ADMIN OPTION SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN SET ROLE regress_priv_group2; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE did not help
SET SESSION AUTHORIZATION regress_priv_group2; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no self-admin
SET SESSION AUTHORIZATION regress_priv_user4; DROP FUNCTION dogrant_ok(); REVOKE regress_priv_group2 FROM regress_priv_user5;
GRANTALLON LARGE OBJECT 1001TO PUBLIC; GRANTSELECTON LARGE OBJECT 1003TO regress_priv_user2; GRANTSELECT,UPDATEON LARGE OBJECT 1004TO regress_priv_user2; GRANTALLON LARGE OBJECT 1005TO regress_priv_user2; GRANTSELECTON LARGE OBJECT 1005TO regress_priv_user2 WITHGRANTOPTION;
GRANTSELECT, INSERTON LARGE OBJECT 1001TO PUBLIC; -- to be failed GRANTSELECT, UPDATEON LARGE OBJECT 1001TO nosuchuser; -- to be failed GRANTSELECT, UPDATEON LARGE OBJECT 999TO PUBLIC; -- to be failed
\c - SET SESSION AUTHORIZATION regress_priv_user2;
SELECT lo_create(2001); SELECT lo_create(2002);
SELECT loread(lo_open(1001, x'20000'::int), 32); -- allowed, for now SELECT lowrite(lo_open(1001, x'40000'::int), 'abcd'); -- fail, wrong mode
SELECT loread(lo_open(1001, x'40000'::int), 32); SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied SELECT loread(lo_open(1003, x'40000'::int), 32); SELECT loread(lo_open(1004, x'40000'::int), 32);
SELECT lowrite(lo_open(1001, x'20000'::int), 'abcd'); SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied SELECT lowrite(lo_open(1003, x'20000'::int), 'abcd'); -- to be denied SELECT lowrite(lo_open(1004, x'20000'::int), 'abcd');
GRANTSELECTON LARGE OBJECT 1005TO regress_priv_user3; GRANTUPDATEON LARGE OBJECT 1006TO regress_priv_user3; -- to be denied REVOKEALLON LARGE OBJECT 2001, 2002FROM PUBLIC; GRANTALLON LARGE OBJECT 2001TO regress_priv_user3;
SELECT lo_unlink(1001); -- to be denied SELECT lo_unlink(2002);
\c - -- confirm ACL setting SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000AND oid < 3000ORDERBY oid;
SET SESSION AUTHORIZATION regress_priv_user3;
SELECT loread(lo_open(1001, x'40000'::int), 32); SELECT loread(lo_open(1003, x'40000'::int), 32); -- to be denied SELECT loread(lo_open(1005, x'40000'::int), 32);
SELECT lo_truncate(lo_open(1005, x'20000'::int), 10); -- to be denied SELECT lo_truncate(lo_open(2001, x'20000'::int), 10);
SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied SELECT lo_put(1002, 1, 'abcd'); -- to be denied SELECT lo_unlink(1002); -- to be denied SELECT lo_export(1001, '/dev/null'); -- to be denied SELECT lo_import('/dev/null'); -- to be denied SELECT lo_import('/dev/null', 2003); -- to be denied
\c - SET lo_compat_privileges = true; -- compatibility mode SET SESSION AUTHORIZATION regress_priv_user4;
-- don't allow unpriv users to access pg_largeobject contents
\c - SELECT * FROM pg_largeobject LIMIT0;
SET SESSION AUTHORIZATION regress_priv_user1; SELECT * FROM pg_largeobject LIMIT0; -- to be denied
-- pg_signal_backend can't signal superusers
RESET SESSION AUTHORIZATION;
BEGIN; CREATEORREPLACE FUNCTION terminate_nothrow(pid int) RETURNS bool
LANGUAGE plpgsql SECURITY DEFINER SET client_min_messages = error AS $$
BEGIN RETURN pg_terminate_backend($1);
EXCEPTION WHEN OTHERS THEN RETURNfalse;
END$$; ALTER FUNCTION terminate_nothrow OWNER TO pg_signal_backend; SELECT backend_type FROM pg_stat_activity WHERECASEWHEN COALESCE(usesysid, 10) = 10THEN terminate_nothrow(pid) END;
ROLLBACK;
-- test pg_database_owner
RESET SESSION AUTHORIZATION; GRANT pg_database_owner TO regress_priv_user1; GRANT regress_priv_user1 TO pg_database_owner; CREATETABLE datdba_only (); ALTERTABLE datdba_only OWNER TO pg_database_owner; REVOKEDELETEON datdba_only FROM pg_database_owner; SELECT
pg_has_role('regress_priv_user1', 'pg_database_owner', 'USAGE') as priv,
pg_has_role('regress_priv_user1', 'pg_database_owner', 'MEMBER') as mem,
pg_has_role('regress_priv_user1', 'pg_database_owner', 'MEMBER WITH ADMIN OPTION') as admin;
BEGIN;
DO $$BEGIN EXECUTE format( 'ALTER DATABASE %I OWNER TO regress_priv_group2', current_catalog); END$$; SELECT
pg_has_role('regress_priv_user1', 'pg_database_owner', 'USAGE') as priv,
pg_has_role('regress_priv_user1', 'pg_database_owner', 'MEMBER') as mem,
pg_has_role('regress_priv_user1', 'pg_database_owner', 'MEMBER WITH ADMIN OPTION') as admin; SET SESSION AUTHORIZATION regress_priv_user1; TABLE information_schema.enabled_roles ORDERBY role_name COLLATE"C"; TABLE information_schema.applicable_roles ORDERBY role_name COLLATE"C"; INSERTINTO datdba_only DEFAULTVALUES;
SAVEPOINT q; DELETEFROM datdba_only; ROLLBACK TO q; SET SESSION AUTHORIZATION regress_priv_user2; TABLE information_schema.enabled_roles; INSERTINTO datdba_only DEFAULTVALUES;
ROLLBACK;
-- test default ACLs
\c -
CREATESCHEMA testns; GRANTALLONSCHEMA testns TO regress_priv_user1;
CREATETABLE testns.acltest1 (x int); SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'SELECT'); -- no SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -- no
-- placeholder for test with duplicated schema and role names ALTERDEFAULT PRIVILEGES INSCHEMA testns,testns GRANTSELECTON TABLES TO public,public;
SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'SELECT'); -- no SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -- no
-- Test quoting and dequoting of user names in ACLs CREATE ROLE "regress_""quoted"; SELECT makeaclitem('regress_"quoted'::regrole, 'regress_"quoted'::regrole, 'SELECT', TRUE); SELECT'"regress_""quoted"=r*/"regress_""quoted"'::aclitem; SELECT'""=r*/""'::aclitem; -- used to be misparsed as """" DROP ROLE "regress_""quoted";
-- Test non-throwing aclitem I/O SELECT pg_input_is_valid('regress_priv_user1=r/regress_priv_user2', 'aclitem'); SELECT pg_input_is_valid('regress_priv_user1=r/', 'aclitem'); SELECT * FROM pg_input_error_info('regress_priv_user1=r/', 'aclitem'); SELECT pg_input_is_valid('regress_priv_user1=r/regress_no_such_user', 'aclitem'); SELECT * FROM pg_input_error_info('regress_priv_user1=r/regress_no_such_user', 'aclitem'); SELECT pg_input_is_valid('regress_priv_user1=rY', 'aclitem'); SELECT * FROM pg_input_error_info('regress_priv_user1=rY', 'aclitem');
-- -- Testing blanket default grants is very hazardous since it might change -- the privileges attached to objects created by concurrent regression tests. -- To avoid that, be sure to revoke the privileges again before committing. --
BEGIN;
-- -- Test for default privileges on large objects. This is done in a -- separate, rollbacked, transaction to avoid any trouble with other -- regression sessions. --
BEGIN;
SELECT lo_create(1007); SELECT has_largeobject_privilege('regress_priv_user2', 1007, 'SELECT'); -- no SELECT has_largeobject_privilege('regress_priv_user2', 1007, 'UPDATE'); -- no
ALTERDEFAULT PRIVILEGES GRANTSELECTON LARGE OBJECTS TO regress_priv_user2;
SELECT lo_create(1008); SELECT has_largeobject_privilege('regress_priv_user2', 1008, 'SELECT'); -- yes SELECT has_largeobject_privilege('regress_priv_user6', 1008, 'SELECT'); -- no SELECT has_largeobject_privilege('regress_priv_user2', 1008, 'UPDATE'); -- no
ALTERDEFAULT PRIVILEGES INSCHEMA public GRANTALLON LARGE OBJECTS TO public; -- error
\c -
-- Test for DROP OWNED BY with shared dependencies. This is done in a -- separate, rollbacked, transaction to avoid any trouble with other -- regression sessions.
BEGIN; ALTERDEFAULT PRIVILEGES GRANTALLON FUNCTIONS TO regress_priv_user2; ALTERDEFAULT PRIVILEGES GRANTALLON LARGE OBJECTS TO regress_priv_user2; ALTERDEFAULT PRIVILEGES GRANTALLONSCHEMASTO regress_priv_user2; ALTERDEFAULT PRIVILEGES GRANTALLON SEQUENCES TO regress_priv_user2; ALTERDEFAULT PRIVILEGES GRANTALLON TABLES TO regress_priv_user2; ALTERDEFAULT PRIVILEGES GRANTALLON TYPES TO regress_priv_user2; SELECT count(*) FROM pg_shdepend WHERE deptype = 'a'AND
refobjid = 'regress_priv_user2'::regrole AND
classid = 'pg_default_acl'::regclass; DROP OWNED BY regress_priv_user2, regress_priv_user2; SELECT count(*) FROM pg_shdepend WHERE deptype = 'a'AND
refobjid = 'regress_priv_user2'::regrole AND
classid = 'pg_default_acl'::regclass;
ROLLBACK;
CREATESCHEMA testns5;
SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'USAGE'); -- no SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'CREATE'); -- no
SET ROLE regress_priv_user1;
CREATE FUNCTION testns.foo() RETURNS intAS'select 1' LANGUAGE sql; CREATE AGGREGATE testns.agg1(int) (sfunc = int4pl, stype = int4); CREATEPROCEDURE testns.bar() AS'select 1' LANGUAGE sql;
SELECT has_function_privilege('regress_priv_user2', 'testns.foo()', 'EXECUTE'); -- no SELECT has_function_privilege('regress_priv_user2', 'testns.agg1(int)', 'EXECUTE'); -- no SELECT has_function_privilege('regress_priv_user2', 'testns.bar()', 'EXECUTE'); -- no
ALTERDEFAULT PRIVILEGES INSCHEMA testns GRANT EXECUTE ON ROUTINES to public;
DROP FUNCTION testns.foo(); CREATE FUNCTION testns.foo() RETURNS intAS'select 1' LANGUAGE sql; DROP AGGREGATE testns.agg1(int); CREATE AGGREGATE testns.agg1(int) (sfunc = int4pl, stype = int4); DROPPROCEDURE testns.bar(); CREATEPROCEDURE testns.bar() AS'select 1' LANGUAGE sql;
SELECT d.* -- check that entries went away FROM pg_default_acl d LEFTJOIN pg_namespace n ON defaclnamespace = n.oid WHERE nspname ISNULLAND defaclnamespace != 0;
-- Grant on all objects of given type in a schema
\c -
-- Change owner of the schema & and rename of new schema owner
\c -
CREATE ROLE regress_schemauser1 superuser login; CREATE ROLE regress_schemauser2 superuser login;
SET SESSION ROLE regress_schemauser1; CREATESCHEMA testns;
SELECT nspname, rolname FROM pg_namespace, pg_roles WHERE pg_namespace.nspname = 'testns'AND pg_namespace.nspowner = pg_roles.oid;
ALTERSCHEMA testns OWNER TO regress_schemauser2; ALTER ROLE regress_schemauser2 RENAMETO regress_schemauser_renamed; SELECT nspname, rolname FROM pg_namespace, pg_roles WHERE pg_namespace.nspname = 'testns'AND pg_namespace.nspowner = pg_roles.oid;
set session role regress_schemauser_renamed; DROPSCHEMA testns CASCADE;
-- clean up
\c -
DROP ROLE regress_schemauser1; DROP ROLE regress_schemauser_renamed;
-- test that dependent privileges are revoked (or not) properly
\c -
set session role regress_priv_user1; createtable dep_priv_test (a int); grantselecton dep_priv_test to regress_priv_user2 withgrantoption; grantselecton dep_priv_test to regress_priv_user3 withgrantoption; set session role regress_priv_user2; grantselecton dep_priv_test to regress_priv_user4 withgrantoption; set session role regress_priv_user3; grantselecton dep_priv_test to regress_priv_user4 withgrantoption; set session role regress_priv_user4; grantselecton dep_priv_test to regress_priv_user5;
\dp dep_priv_test set session role regress_priv_user2; revokeselecton dep_priv_test from regress_priv_user4 cascade;
\dp dep_priv_test set session role regress_priv_user3; revokeselecton dep_priv_test from regress_priv_user4 cascade;
\dp dep_priv_test set session role regress_priv_user1; droptable dep_priv_test;
-- clean up
\c
drop sequence x_seq;
DROP AGGREGATE priv_testagg1(int); DROP FUNCTION priv_testfunc2(int); DROP FUNCTION priv_testfunc4(boolean); DROPPROCEDURE priv_testproc1(int);
DROP VIEW atestv0; DROP VIEW atestv1; DROP VIEW atestv2; -- this should cascade to drop atestv4 DROP VIEW atestv3 CASCADE; -- this should complain "does not exist" DROP VIEW atestv4;
-- these are needed to clean up permissions REVOKEUSAGEON LANGUAGE sqlFROM regress_priv_user1; DROP OWNED BY regress_priv_user1;
DROP USER regress_priv_user1; DROP USER regress_priv_user2; DROP USER regress_priv_user3; DROP USER regress_priv_user4; DROP USER regress_priv_user5; DROP USER regress_priv_user6; DROP USER regress_priv_user7; DROP USER regress_priv_user8; -- does not exist
-- leave some default ACLs for pg_upgrade's dump-restore test input. ALTERDEFAULT PRIVILEGES FOR ROLE pg_signal_backend REVOKEUSAGEON TYPES FROM pg_signal_backend; ALTERDEFAULT PRIVILEGES FOR ROLE pg_read_all_settings REVOKEUSAGEON TYPES FROM pg_read_all_settings;
-- permissions with LOCK TABLE CREATE USER regress_locktable_user; CREATETABLE lock_table (a int);
-- LOCK TABLE and SELECT permission GRANTSELECTON lock_table TO regress_locktable_user; SET SESSION AUTHORIZATION regress_locktable_user;
BEGIN; LOCKTABLE lock_table IN ACCESS SHARE MODE; -- should pass COMMIT;
BEGIN; LOCKTABLE lock_table IN ROW EXCLUSIVE MODE; -- should fail
ROLLBACK;
BEGIN; LOCKTABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should fail
ROLLBACK;
\c REVOKESELECTON lock_table FROM regress_locktable_user;
-- LOCK TABLE and INSERT permission GRANTINSERTON lock_table TO regress_locktable_user; SET SESSION AUTHORIZATION regress_locktable_user;
BEGIN; LOCKTABLE lock_table IN ACCESS SHARE MODE; -- should pass
ROLLBACK;
BEGIN; LOCKTABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass COMMIT;
BEGIN; LOCKTABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should fail
ROLLBACK;
\c REVOKEINSERTON lock_table FROM regress_locktable_user;
-- LOCK TABLE and UPDATE permission GRANTUPDATEON lock_table TO regress_locktable_user; SET SESSION AUTHORIZATION regress_locktable_user;
BEGIN; LOCKTABLE lock_table IN ACCESS SHARE MODE; -- should pass
ROLLBACK;
BEGIN; LOCKTABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass COMMIT;
BEGIN; LOCKTABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass COMMIT;
\c REVOKEUPDATEON lock_table FROM regress_locktable_user;
-- LOCK TABLE and DELETE permission GRANTDELETEON lock_table TO regress_locktable_user; SET SESSION AUTHORIZATION regress_locktable_user;
BEGIN; LOCKTABLE lock_table IN ACCESS SHARE MODE; -- should pass
ROLLBACK;
BEGIN; LOCKTABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass COMMIT;
BEGIN; LOCKTABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass COMMIT;
\c REVOKEDELETEON lock_table FROM regress_locktable_user;
-- LOCK TABLE and TRUNCATE permission GRANT TRUNCATE ON lock_table TO regress_locktable_user; SET SESSION AUTHORIZATION regress_locktable_user;
BEGIN; LOCKTABLE lock_table IN ACCESS SHARE MODE; -- should pass
ROLLBACK;
BEGIN; LOCKTABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass COMMIT;
BEGIN; LOCKTABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass COMMIT;
\c REVOKE TRUNCATE ON lock_table FROM regress_locktable_user;
-- LOCK TABLE and MAINTAIN permission GRANT MAINTAIN ON lock_table TO regress_locktable_user; SET SESSION AUTHORIZATION regress_locktable_user;
BEGIN; LOCKTABLE lock_table IN ACCESS SHARE MODE; -- should pass
ROLLBACK;
BEGIN; LOCKTABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass COMMIT;
BEGIN; LOCKTABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass COMMIT;
\c REVOKE MAINTAIN ON lock_table FROM regress_locktable_user;
-- clean up DROPTABLE lock_table; DROP USER regress_locktable_user;
-- test to check privileges of system views pg_shmem_allocations, -- pg_shmem_allocations_numa and pg_backend_memory_contexts.
-- switch to superuser
\c -
CREATE ROLE regress_readallstats;
SELECT has_table_privilege('regress_readallstats','pg_aios','SELECT'); -- no SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT'); -- no SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations_numa','SELECT'); -- no
-- run query to ensure that functions within views can be executed SET ROLE regress_readallstats; SELECT COUNT(*) >= 0AS ok FROM pg_aios; SELECT COUNT(*) >= 0AS ok FROM pg_backend_memory_contexts; SELECT COUNT(*) >= 0AS ok FROM pg_shmem_allocations;
RESET ROLE;
-- clean up DROP ROLE regress_readallstats;
-- test role grantor machinery CREATE ROLE regress_group; CREATE ROLE regress_group_direct_manager; CREATE ROLE regress_group_indirect_manager; CREATE ROLE regress_group_member;
GRANT regress_group TO regress_group_direct_manager WITH INHERIT FALSE, ADMIN TRUE; GRANT regress_group_direct_manager TO regress_group_indirect_manager;
SET SESSION AUTHORIZATION regress_group_direct_manager; GRANT regress_group TO regress_group_member; SELECT member::regrole::text, CASEWHEN grantor = 10THEN'BOOTSTRAP SUPERUSER'ELSE grantor::regrole::text END FROM pg_auth_members WHERE roleid = 'regress_group'::regrole ORDERBY1, 2; REVOKE regress_group FROM regress_group_member;
SET SESSION AUTHORIZATION regress_group_indirect_manager; GRANT regress_group TO regress_group_member; SELECT member::regrole::text, CASEWHEN grantor = 10THEN'BOOTSTRAP SUPERUSER'ELSE grantor::regrole::text END FROM pg_auth_members WHERE roleid = 'regress_group'::regrole ORDERBY1, 2; REVOKE regress_group FROM regress_group_member;
RESET SESSION AUTHORIZATION; DROP ROLE regress_group; DROP ROLE regress_group_direct_manager; DROP ROLE regress_group_indirect_manager; DROP ROLE regress_group_member;
-- test SET and INHERIT options with object ownership changes CREATE ROLE regress_roleoption_protagonist; CREATE ROLE regress_roleoption_donor; CREATE ROLE regress_roleoption_recipient; CREATESCHEMA regress_roleoption; GRANTCREATE, USAGEONSCHEMA regress_roleoption TO PUBLIC; GRANT regress_roleoption_donor TO regress_roleoption_protagonist WITH INHERIT TRUE, SETFALSE; GRANT regress_roleoption_recipient TO regress_roleoption_protagonist WITH INHERIT FALSE, SETTRUE; SET SESSION AUTHORIZATION regress_roleoption_protagonist; CREATETABLE regress_roleoption.t1 (a int); CREATETABLE regress_roleoption.t2 (a int); SET SESSION AUTHORIZATION regress_roleoption_donor; CREATETABLE regress_roleoption.t3 (a int); SET SESSION AUTHORIZATION regress_roleoption_recipient; CREATETABLE regress_roleoption.t4 (a int); SET SESSION AUTHORIZATION regress_roleoption_protagonist; ALTERTABLE regress_roleoption.t1 OWNER TO regress_roleoption_donor; -- fails, can't be come donor ALTERTABLE regress_roleoption.t2 OWNER TO regress_roleoption_recipient; -- works ALTERTABLE regress_roleoption.t3 OWNER TO regress_roleoption_protagonist; -- works ALTERTABLE regress_roleoption.t4 OWNER TO regress_roleoption_protagonist; -- fails, we don't inherit from recipient
RESET SESSION AUTHORIZATION; DROPTABLE regress_roleoption.t1; DROPTABLE regress_roleoption.t2; DROPTABLE regress_roleoption.t3; DROPTABLE regress_roleoption.t4; DROPSCHEMA regress_roleoption; DROP ROLE regress_roleoption_protagonist; DROP ROLE regress_roleoption_donor; DROP ROLE regress_roleoption_recipient;
-- MAINTAIN CREATE ROLE regress_no_maintain; CREATE ROLE regress_maintain; CREATE ROLE regress_maintain_all IN ROLE pg_maintain; CREATETABLE maintain_test (a INT); CREATEINDEXON maintain_test (a); GRANT MAINTAIN ON maintain_test TO regress_maintain; CREATE MATERIALIZED VIEW refresh_test ASSELECT1; GRANT MAINTAIN ON refresh_test TO regress_maintain; CREATESCHEMA reindex_test;
-- negative tests; should fail SET ROLE regress_no_maintain;
VACUUM maintain_test; ANALYZE maintain_test;
VACUUM (ANALYZE) maintain_test;
CLUSTER maintain_test USING maintain_test_a_idx;
REFRESH MATERIALIZED VIEW refresh_test;
REINDEX TABLE maintain_test;
REINDEX INDEX maintain_test_a_idx;
REINDEX SCHEMA reindex_test;
RESET ROLE;
SET ROLE regress_maintain;
VACUUM maintain_test; ANALYZE maintain_test;
VACUUM (ANALYZE) maintain_test;
CLUSTER maintain_test USING maintain_test_a_idx;
REFRESH MATERIALIZED VIEW refresh_test;
REINDEX TABLE maintain_test;
REINDEX INDEX maintain_test_a_idx;
REINDEX SCHEMA reindex_test;
RESET ROLE;
SET ROLE regress_maintain_all;
VACUUM maintain_test; ANALYZE maintain_test;
VACUUM (ANALYZE) maintain_test;
CLUSTER maintain_test USING maintain_test_a_idx;
REFRESH MATERIALIZED VIEW refresh_test;
REINDEX TABLE maintain_test;
REINDEX INDEX maintain_test_a_idx;
REINDEX SCHEMA reindex_test;
RESET ROLE;
DROPTABLE maintain_test; DROP MATERIALIZED VIEW refresh_test; DROPSCHEMA reindex_test; DROP ROLE regress_no_maintain; DROP ROLE regress_maintain; DROP ROLE regress_maintain_all;
-- grantor selection CREATE ROLE regress_grantor1; CREATE ROLE regress_grantor2 ROLE regress_grantor1; CREATE ROLE regress_grantor3; CREATETABLE grantor_test1 (); CREATETABLE grantor_test2 (); CREATETABLE grantor_test3 (); GRANTSELECTON grantor_test2 TO regress_grantor1 WITHGRANTOPTION; GRANTSELECT, UPDATEON grantor_test3 TO regress_grantor2 WITHGRANTOPTION;
SET ROLE regress_grantor1; GRANTSELECT, UPDATEON grantor_test1 TO regress_grantor3; GRANTSELECT, UPDATEON grantor_test2 TO regress_grantor3; GRANTSELECT, UPDATEON grantor_test3 TO regress_grantor3;
RESET ROLE;
SELECT * FROM information_schema.table_privileges t WHERE grantor LIKE'regress_grantor%'ORDERBY ROW(t.*);
DROPTABLE grantor_test1, grantor_test2, grantor_test3; DROP ROLE regress_grantor1, regress_grantor2, regress_grantor3;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.39 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.