-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make the custom GUCs default to on rather than off. This allows
the regression test to check the command blocking functionality by simply doing a "LOAD 'set_user'" since that runs the library init function. The GUCs being SIGHUP cannot be changed in the regression session, so just make "on" the default. Still need to adjust the docs to reflect this switch. Additionally, add tests to the regression test to cover all three blocked commands. Since coverage differs with Postgres major version, there are actually three variants of expected file now.
- Loading branch information
Joe Conway
committed
Dec 12, 2015
1 parent
e1c308a
commit dd69f35
Showing
5 changed files
with
418 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
CREATE EXTENSION set_user; | ||
-- Ensure the library is loaded. | ||
LOAD 'set_user'; | ||
-- Clean up in case a prior regression run failed | ||
-- First suppress NOTICE messages when users/groups don't exist | ||
SET client_min_messages TO 'warning'; | ||
DROP USER IF EXISTS dba, bob, joe, newbs, su; | ||
RESET client_min_messages; | ||
-- Create some users to work with | ||
CREATE USER dba; | ||
CREATE USER bob; | ||
CREATE USER joe; | ||
CREATE ROLE newbs; | ||
CREATE ROLE su NOINHERIT; | ||
-- dba is the role we want to allow to execute set_user() | ||
GRANT EXECUTE ON FUNCTION set_user(text) TO dba; | ||
GRANT newbs TO bob; | ||
-- joe will be able to escalate without set_user() via su | ||
GRANT su TO joe; | ||
GRANT postgres TO su; | ||
-- test set_user | ||
SET SESSION AUTHORIZATION dba; | ||
SELECT SESSION_USER, CURRENT_USER; | ||
session_user | current_user | ||
--------------+-------------- | ||
dba | dba | ||
(1 row) | ||
|
||
SELECT set_user('postgres'); | ||
set_user | ||
---------- | ||
OK | ||
(1 row) | ||
|
||
SELECT SESSION_USER, CURRENT_USER; | ||
session_user | current_user | ||
--------------+-------------- | ||
dba | postgres | ||
(1 row) | ||
|
||
-- ALTER SYSTEM should fail | ||
ALTER SYSTEM SET wal_level = minimal; | ||
ERROR: syntax error at or near "SYSTEM" | ||
LINE 1: ALTER SYSTEM SET wal_level = minimal; | ||
^ | ||
-- COPY PROGRAM should fail | ||
COPY (select 42) TO PROGRAM 'cat'; | ||
ERROR: COPY PROGRAM blocked by set_user config | ||
-- SET log_statement should fail | ||
SET log_statement = 'none'; | ||
ERROR: "SET log_statement" blocked by set_user config | ||
SET log_statement = DEFAULT; | ||
ERROR: "SET log_statement" blocked by set_user config | ||
RESET log_statement; | ||
ERROR: "SET log_statement" blocked by set_user config | ||
BEGIN; SET LOCAL log_statement = 'none'; ABORT; | ||
ERROR: "SET log_statement" blocked by set_user config | ||
-- test reset_user | ||
SELECT reset_user(); | ||
reset_user | ||
------------ | ||
OK | ||
(1 row) | ||
|
||
SELECT SESSION_USER, CURRENT_USER; | ||
session_user | current_user | ||
--------------+-------------- | ||
dba | dba | ||
(1 row) | ||
|
||
RESET SESSION AUTHORIZATION; | ||
ALTER SYSTEM SET wal_level = minimal; | ||
ERROR: syntax error at or near "SYSTEM" | ||
LINE 1: ALTER SYSTEM SET wal_level = minimal; | ||
^ | ||
COPY (select 42) TO PROGRAM 'cat'; | ||
SET log_statement = DEFAULT; | ||
-- this is an example of how we might audit existing roles | ||
SET SESSION AUTHORIZATION dba; | ||
SELECT set_user('postgres'); | ||
set_user | ||
---------- | ||
OK | ||
(1 row) | ||
|
||
SELECT rolname FROM pg_authid WHERE rolsuper and rolcanlogin; | ||
rolname | ||
---------- | ||
postgres | ||
(1 row) | ||
|
||
CREATE OR REPLACE VIEW roletree AS | ||
WITH RECURSIVE | ||
roltree AS ( | ||
SELECT u.rolname AS rolname, | ||
u.oid AS roloid, | ||
u.rolcanlogin, | ||
u.rolsuper, | ||
'{}'::name[] AS rolparents, | ||
NULL::oid AS parent_roloid, | ||
NULL::name AS parent_rolname | ||
FROM pg_catalog.pg_authid u | ||
LEFT JOIN pg_catalog.pg_auth_members m on u.oid = m.member | ||
LEFT JOIN pg_catalog.pg_authid g on m.roleid = g.oid | ||
WHERE g.oid IS NULL | ||
UNION ALL | ||
SELECT u.rolname AS rolname, | ||
u.oid AS roloid, | ||
u.rolcanlogin, | ||
u.rolsuper, | ||
t.rolparents || g.rolname AS rolparents, | ||
g.oid AS parent_roloid, | ||
g.rolname AS parent_rolname | ||
FROM pg_catalog.pg_authid u | ||
JOIN pg_catalog.pg_auth_members m on u.oid = m.member | ||
JOIN pg_catalog.pg_authid g on m.roleid = g.oid | ||
JOIN roltree t on t.roloid = g.oid | ||
) | ||
SELECT | ||
r.rolname, | ||
r.roloid, | ||
r.rolcanlogin, | ||
r.rolsuper, | ||
r.rolparents | ||
FROM roltree r | ||
ORDER BY 1; | ||
-- this will show unacceptable results | ||
-- since postgres can log in directly and | ||
-- joe can escalate via su to postgres | ||
SELECT | ||
ro.rolname, | ||
ro.rolcanlogin, | ||
ro.rolsuper, | ||
ro.rolparents | ||
FROM roletree ro | ||
WHERE (ro.rolcanlogin AND ro.rolsuper) | ||
OR | ||
( | ||
ro.rolcanlogin AND EXISTS | ||
( | ||
SELECT TRUE FROM roletree ri | ||
WHERE ri.rolname = ANY (ro.rolparents) | ||
AND ri.rolsuper | ||
) | ||
); | ||
rolname | rolcanlogin | rolsuper | rolparents | ||
----------+-------------+----------+--------------- | ||
joe | t | f | {postgres,su} | ||
postgres | t | t | {} | ||
(2 rows) | ||
|
||
-- here is how we fix the environment | ||
-- running this in a transaction that will be aborted | ||
-- since we don't really want to make the postgres user | ||
-- nologin during regression testing | ||
BEGIN; | ||
REVOKE postgres FROM su; | ||
ALTER USER postgres NOLOGIN; | ||
-- retest, this time successfully | ||
SELECT | ||
ro.rolname, | ||
ro.rolcanlogin, | ||
ro.rolsuper, | ||
ro.rolparents | ||
FROM roletree ro | ||
WHERE (ro.rolcanlogin AND ro.rolsuper) | ||
OR | ||
( | ||
ro.rolcanlogin AND EXISTS | ||
( | ||
SELECT TRUE FROM roletree ri | ||
WHERE ri.rolname = ANY (ro.rolparents) | ||
AND ri.rolsuper | ||
) | ||
); | ||
rolname | rolcanlogin | rolsuper | rolparents | ||
---------+-------------+----------+------------ | ||
(0 rows) | ||
|
||
-- undo those changes | ||
ABORT; |
Oops, something went wrong.