Skip to content

Commit 90efa2f

Browse files
committed
Add a test module for Object Access hooks
This includes tests of both the newly added name type object access hooks and the older Oid type hooks, and provides a useful example of how to use the hooks. Mark Dilger, based on some code from Joshua Brindle. Discussion: https://postgr.es/m/47F87A0E-C0E5-43A6-89F6-D403F2B45175@enterprisedb.com
1 parent d11e84e commit 90efa2f

File tree

8 files changed

+1311
-0
lines changed

8 files changed

+1311
-0
lines changed

src/test/modules/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SUBDIRS = \
2020
test_ginpostinglist \
2121
test_integerset \
2222
test_misc \
23+
test_oat_hooks \
2324
test_parser \
2425
test_pg_dump \
2526
test_predtest \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Generated subdirectories
2+
/log/
3+
/results/
4+
/tmp_check/
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# src/test/modules/test_oat_hooks/Makefile
2+
3+
MODULE_big = test_oat_hooks
4+
OBJS = \
5+
$(WIN32RES) \
6+
test_oat_hooks.o
7+
PGFILEDESC = "test_oat_hooks - example use of object access hooks"
8+
9+
REGRESS = test_oat_hooks
10+
REGRESS_OPTS = --temp-config=$(top_srcdir)/src/test/modules/test_oat_hooks/test_oat_hooks.conf
11+
# Disabled because these tests require "shared_preload_libraries=test_oat_hooks",
12+
# which typical installcheck users do not have (e.g. buildfarm clients).
13+
NO_INSTALLCHECK = 1
14+
15+
ifdef USE_PGXS
16+
PG_CONFIG = pg_config
17+
PGXS := $(shell $(PG_CONFIG) --pgxs)
18+
include $(PGXS)
19+
else
20+
subdir = src/test/modules/test_oat_hooks
21+
top_builddir = ../../../..
22+
include $(top_builddir)/src/Makefile.global
23+
include $(top_srcdir)/contrib/contrib-global.mk
24+
endif
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
OVERVIEW
2+
========
3+
4+
This test module, "test_oat_hooks", is an example of how to use the object
5+
access hooks (OAT) to enforce mandatory access controls (MAC).
6+
7+
The testing strategy is as follows: When this module loads, it registers hooks
8+
of various types. (See below.) GUCs are defined to control each hook,
9+
determining whether the hook allows or denies actions for which it fires. A
10+
single additional GUC controls the verbosity of the hooks. GUCs default to
11+
permissive/quiet, which allows the module to load without generating noise in
12+
the log or denying any activity in the run-up to the regression test beginning.
13+
When the test begins, it uses SET commands to turn on logging and to control
14+
each hook's permissive/restrictive behavior. Various SQL statements are run
15+
under both superuser and ordinary user permissions. The output is compared
16+
against the expected output to verify that the hooks behaved and fired in the
17+
order by expect.
18+
19+
Because users may care about the firing order of other system hooks relative to
20+
OAT hooks, ProcessUtility hooks and ExecutorCheckPerms hooks are also
21+
registered by this module, with their own logging and allow/deny behavior.
22+
23+
24+
SUSET test configuration GUCs
25+
=============================
26+
27+
The following configuration parameters (GUCs) control this test module's Object
28+
Access Type (OAT), Process Utility and Executor Check Permissions hooks. The
29+
general pattern is that each hook has a corresponding GUC which controls
30+
whether the hook will allow or deny operations for which the hook gets called.
31+
A real-world OAT hook should certainly provide more fine-grained conrol than
32+
merely "allow-all" vs. "deny-all", but for testing this is sufficient.
33+
34+
Note that even when these hooks allow an action, the core permissions system
35+
may still refuse the action. The firing order of the hooks relative to the
36+
core permissions system can be inferred from which NOTICE messages get emitted
37+
before an action is refused.
38+
39+
Each hook applies the allow vs. deny setting to all operations performed by
40+
non-superusers.
41+
42+
- test_oat_hooks.deny_set_variable
43+
44+
Controls whether the object_access_hook_str MAC function rejects attempts to
45+
set a configuration parameter.
46+
47+
- test_oat_hooks.deny_alter_system
48+
49+
Controls whether the object_access_hook_str MAC function rejects attempts to
50+
alter system set a configuration parameter.
51+
52+
- test_oat_hooks.deny_object_access
53+
54+
Controls whether the object_access_hook MAC function rejects all operations
55+
for which it is called.
56+
57+
- test_oat_hooks.deny_exec_perms
58+
59+
Controls whether the exec_check_perms MAC function rejects all operations for
60+
which it is called.
61+
62+
- test_oat_hooks.deny_utility_commands
63+
64+
Controls whether the ProcessUtility_hook function rejects all operations for
65+
which it is called.
66+
67+
- test_oat_hooks.audit
68+
69+
Controls whether each hook logs NOTICE messages for each attempt, along with
70+
success or failure status. Note that clearing or setting this GUC may itself
71+
generate NOTICE messages appearing before but not after, or after but not
72+
before, the new setting takes effect.
73+
74+
75+
Functions
76+
=========
77+
78+
The module registers hooks by the following names:
79+
80+
- REGRESS_object_access_hook
81+
82+
- REGRESS_object_access_hook_str
83+
84+
- REGRESS_exec_check_perms
85+
86+
- REGRESS_utility_command
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
-- SET commands fire both the ProcessUtility_hook and the
2+
-- object_access_hook_str. Since the auditing GUC starts out false, we miss the
3+
-- initial "attempting" audit message from the ProcessUtility_hook, but we
4+
-- should thereafter see the audit messages
5+
SET test_oat_hooks.audit = true;
6+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [test_oat_hooks.audit]
7+
NOTICE: in object_access_hook_str: superuser finished alter (set) [test_oat_hooks.audit]
8+
NOTICE: in process utility: superuser finished set
9+
-- Create objects for use in the test
10+
CREATE USER regress_test_user;
11+
NOTICE: in process utility: superuser attempting CreateRoleStmt
12+
NOTICE: in object access: superuser attempting create (subId=0) [explicit]
13+
NOTICE: in object access: superuser finished create (subId=0) [explicit]
14+
NOTICE: in process utility: superuser finished CreateRoleStmt
15+
CREATE TABLE regress_test_table (t text);
16+
NOTICE: in process utility: superuser attempting CreateStmt
17+
NOTICE: in object access: superuser attempting namespace search (subId=0) [no report on violation, allowed]
18+
LINE 1: CREATE TABLE regress_test_table (t text);
19+
^
20+
NOTICE: in object access: superuser finished namespace search (subId=0) [no report on violation, allowed]
21+
LINE 1: CREATE TABLE regress_test_table (t text);
22+
^
23+
NOTICE: in object access: superuser attempting create (subId=0) [explicit]
24+
NOTICE: in object access: superuser finished create (subId=0) [explicit]
25+
NOTICE: in object access: superuser attempting create (subId=0) [explicit]
26+
NOTICE: in object access: superuser finished create (subId=0) [explicit]
27+
NOTICE: in object access: superuser attempting create (subId=0) [explicit]
28+
NOTICE: in object access: superuser finished create (subId=0) [explicit]
29+
NOTICE: in object access: superuser attempting create (subId=0) [internal]
30+
NOTICE: in object access: superuser finished create (subId=0) [internal]
31+
NOTICE: in object access: superuser attempting create (subId=0) [internal]
32+
NOTICE: in object access: superuser finished create (subId=0) [internal]
33+
NOTICE: in process utility: superuser finished CreateStmt
34+
GRANT SELECT ON Table regress_test_table TO public;
35+
NOTICE: in process utility: superuser attempting GrantStmt
36+
NOTICE: in process utility: superuser finished GrantStmt
37+
CREATE FUNCTION regress_test_func (t text) RETURNS text AS $$
38+
SELECT $1;
39+
$$ LANGUAGE sql;
40+
NOTICE: in process utility: superuser attempting CreateFunctionStmt
41+
NOTICE: in object access: superuser attempting create (subId=0) [explicit]
42+
NOTICE: in object access: superuser finished create (subId=0) [explicit]
43+
NOTICE: in process utility: superuser finished CreateFunctionStmt
44+
GRANT EXECUTE ON FUNCTION regress_test_func (text) TO public;
45+
NOTICE: in process utility: superuser attempting GrantStmt
46+
NOTICE: in process utility: superuser finished GrantStmt
47+
-- Do a few things as superuser
48+
SELECT * FROM regress_test_table;
49+
NOTICE: in executor check perms: superuser attempting execute
50+
NOTICE: in executor check perms: superuser finished execute
51+
t
52+
---
53+
(0 rows)
54+
55+
SELECT regress_test_func('arg');
56+
NOTICE: in executor check perms: superuser attempting execute
57+
NOTICE: in executor check perms: superuser finished execute
58+
regress_test_func
59+
-------------------
60+
arg
61+
(1 row)
62+
63+
SET work_mem = 8192;
64+
NOTICE: in process utility: superuser attempting set
65+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [work_mem]
66+
NOTICE: in object_access_hook_str: superuser finished alter (set) [work_mem]
67+
NOTICE: in process utility: superuser finished set
68+
RESET work_mem;
69+
NOTICE: in process utility: superuser attempting set
70+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [work_mem]
71+
NOTICE: in object_access_hook_str: superuser finished alter (set) [work_mem]
72+
NOTICE: in process utility: superuser finished set
73+
ALTER SYSTEM SET work_mem = 8192;
74+
NOTICE: in process utility: superuser attempting alter system
75+
NOTICE: in object_access_hook_str: superuser attempting alter (alter system set) [work_mem]
76+
NOTICE: in object_access_hook_str: superuser finished alter (alter system set) [work_mem]
77+
NOTICE: in process utility: superuser finished alter system
78+
ALTER SYSTEM RESET work_mem;
79+
NOTICE: in process utility: superuser attempting alter system
80+
NOTICE: in object_access_hook_str: superuser attempting alter (alter system set) [work_mem]
81+
NOTICE: in object_access_hook_str: superuser finished alter (alter system set) [work_mem]
82+
NOTICE: in process utility: superuser finished alter system
83+
-- Do those same things as non-superuser
84+
SET SESSION AUTHORIZATION regress_test_user;
85+
NOTICE: in process utility: superuser attempting set
86+
NOTICE: in object_access_hook_str: non-superuser attempting alter (set) [session_authorization]
87+
NOTICE: in object_access_hook_str: non-superuser finished alter (set) [session_authorization]
88+
NOTICE: in process utility: non-superuser finished set
89+
SELECT * FROM regress_test_table;
90+
NOTICE: in object access: non-superuser attempting namespace search (subId=0) [no report on violation, allowed]
91+
LINE 1: SELECT * FROM regress_test_table;
92+
^
93+
NOTICE: in object access: non-superuser finished namespace search (subId=0) [no report on violation, allowed]
94+
LINE 1: SELECT * FROM regress_test_table;
95+
^
96+
NOTICE: in executor check perms: non-superuser attempting execute
97+
NOTICE: in executor check perms: non-superuser finished execute
98+
t
99+
---
100+
(0 rows)
101+
102+
SELECT regress_test_func('arg');
103+
NOTICE: in executor check perms: non-superuser attempting execute
104+
NOTICE: in executor check perms: non-superuser finished execute
105+
regress_test_func
106+
-------------------
107+
arg
108+
(1 row)
109+
110+
SET work_mem = 8192;
111+
NOTICE: in process utility: non-superuser attempting set
112+
NOTICE: in object_access_hook_str: non-superuser attempting alter (set) [work_mem]
113+
NOTICE: in object_access_hook_str: non-superuser finished alter (set) [work_mem]
114+
NOTICE: in process utility: non-superuser finished set
115+
RESET work_mem;
116+
NOTICE: in process utility: non-superuser attempting set
117+
NOTICE: in object_access_hook_str: non-superuser attempting alter (set) [work_mem]
118+
NOTICE: in object_access_hook_str: non-superuser finished alter (set) [work_mem]
119+
NOTICE: in process utility: non-superuser finished set
120+
ALTER SYSTEM SET work_mem = 8192;
121+
NOTICE: in process utility: non-superuser attempting alter system
122+
ERROR: must be superuser to execute ALTER SYSTEM command
123+
ALTER SYSTEM RESET work_mem;
124+
NOTICE: in process utility: non-superuser attempting alter system
125+
ERROR: must be superuser to execute ALTER SYSTEM command
126+
RESET SESSION AUTHORIZATION;
127+
NOTICE: in process utility: non-superuser attempting set
128+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [session_authorization]
129+
NOTICE: in object_access_hook_str: superuser finished alter (set) [session_authorization]
130+
NOTICE: in process utility: superuser finished set
131+
-- Turn off non-superuser permissions
132+
SET test_oat_hooks.deny_set_variable = true;
133+
NOTICE: in process utility: superuser attempting set
134+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [test_oat_hooks.deny_set_variable]
135+
NOTICE: in object_access_hook_str: superuser finished alter (set) [test_oat_hooks.deny_set_variable]
136+
NOTICE: in process utility: superuser finished set
137+
SET test_oat_hooks.deny_alter_system = true;
138+
NOTICE: in process utility: superuser attempting set
139+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [test_oat_hooks.deny_alter_system]
140+
NOTICE: in object_access_hook_str: superuser finished alter (set) [test_oat_hooks.deny_alter_system]
141+
NOTICE: in process utility: superuser finished set
142+
SET test_oat_hooks.deny_object_access = true;
143+
NOTICE: in process utility: superuser attempting set
144+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [test_oat_hooks.deny_object_access]
145+
NOTICE: in object_access_hook_str: superuser finished alter (set) [test_oat_hooks.deny_object_access]
146+
NOTICE: in process utility: superuser finished set
147+
SET test_oat_hooks.deny_exec_perms = true;
148+
NOTICE: in process utility: superuser attempting set
149+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [test_oat_hooks.deny_exec_perms]
150+
NOTICE: in object_access_hook_str: superuser finished alter (set) [test_oat_hooks.deny_exec_perms]
151+
NOTICE: in process utility: superuser finished set
152+
SET test_oat_hooks.deny_utility_commands = true;
153+
NOTICE: in process utility: superuser attempting set
154+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [test_oat_hooks.deny_utility_commands]
155+
NOTICE: in object_access_hook_str: superuser finished alter (set) [test_oat_hooks.deny_utility_commands]
156+
NOTICE: in process utility: superuser finished set
157+
-- Try again as non-superuser with permisisons denied
158+
SET SESSION AUTHORIZATION regress_test_user;
159+
NOTICE: in process utility: superuser attempting set
160+
NOTICE: in object_access_hook_str: non-superuser attempting alter (set) [session_authorization]
161+
ERROR: permission denied: set session_authorization
162+
SELECT * FROM regress_test_table;
163+
NOTICE: in object access: superuser attempting namespace search (subId=0) [no report on violation, allowed]
164+
LINE 1: SELECT * FROM regress_test_table;
165+
^
166+
NOTICE: in object access: superuser finished namespace search (subId=0) [no report on violation, allowed]
167+
LINE 1: SELECT * FROM regress_test_table;
168+
^
169+
NOTICE: in executor check perms: superuser attempting execute
170+
NOTICE: in executor check perms: superuser finished execute
171+
t
172+
---
173+
(0 rows)
174+
175+
SELECT regress_test_func('arg');
176+
NOTICE: in executor check perms: superuser attempting execute
177+
NOTICE: in executor check perms: superuser finished execute
178+
regress_test_func
179+
-------------------
180+
arg
181+
(1 row)
182+
183+
SET work_mem = 8192;
184+
NOTICE: in process utility: superuser attempting set
185+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [work_mem]
186+
NOTICE: in object_access_hook_str: superuser finished alter (set) [work_mem]
187+
NOTICE: in process utility: superuser finished set
188+
RESET work_mem;
189+
NOTICE: in process utility: superuser attempting set
190+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [work_mem]
191+
NOTICE: in object_access_hook_str: superuser finished alter (set) [work_mem]
192+
NOTICE: in process utility: superuser finished set
193+
ALTER SYSTEM SET work_mem = 8192;
194+
NOTICE: in process utility: superuser attempting alter system
195+
NOTICE: in object_access_hook_str: superuser attempting alter (alter system set) [work_mem]
196+
NOTICE: in object_access_hook_str: superuser finished alter (alter system set) [work_mem]
197+
NOTICE: in process utility: superuser finished alter system
198+
ALTER SYSTEM RESET work_mem;
199+
NOTICE: in process utility: superuser attempting alter system
200+
NOTICE: in object_access_hook_str: superuser attempting alter (alter system set) [work_mem]
201+
NOTICE: in object_access_hook_str: superuser finished alter (alter system set) [work_mem]
202+
NOTICE: in process utility: superuser finished alter system
203+
RESET SESSION AUTHORIZATION;
204+
NOTICE: in process utility: superuser attempting set
205+
NOTICE: in object_access_hook_str: superuser attempting alter (set) [session_authorization]
206+
NOTICE: in object_access_hook_str: superuser finished alter (set) [session_authorization]
207+
NOTICE: in process utility: superuser finished set
208+
SET test_oat_hooks.audit = false;
209+
NOTICE: in process utility: superuser attempting set
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
-- SET commands fire both the ProcessUtility_hook and the
2+
-- object_access_hook_str. Since the auditing GUC starts out false, we miss the
3+
-- initial "attempting" audit message from the ProcessUtility_hook, but we
4+
-- should thereafter see the audit messages
5+
SET test_oat_hooks.audit = true;
6+
7+
-- Create objects for use in the test
8+
CREATE USER regress_test_user;
9+
CREATE TABLE regress_test_table (t text);
10+
GRANT SELECT ON Table regress_test_table TO public;
11+
CREATE FUNCTION regress_test_func (t text) RETURNS text AS $$
12+
SELECT $1;
13+
$$ LANGUAGE sql;
14+
GRANT EXECUTE ON FUNCTION regress_test_func (text) TO public;
15+
16+
-- Do a few things as superuser
17+
SELECT * FROM regress_test_table;
18+
SELECT regress_test_func('arg');
19+
SET work_mem = 8192;
20+
RESET work_mem;
21+
ALTER SYSTEM SET work_mem = 8192;
22+
ALTER SYSTEM RESET work_mem;
23+
24+
-- Do those same things as non-superuser
25+
SET SESSION AUTHORIZATION regress_test_user;
26+
SELECT * FROM regress_test_table;
27+
SELECT regress_test_func('arg');
28+
SET work_mem = 8192;
29+
RESET work_mem;
30+
ALTER SYSTEM SET work_mem = 8192;
31+
ALTER SYSTEM RESET work_mem;
32+
RESET SESSION AUTHORIZATION;
33+
34+
-- Turn off non-superuser permissions
35+
SET test_oat_hooks.deny_set_variable = true;
36+
SET test_oat_hooks.deny_alter_system = true;
37+
SET test_oat_hooks.deny_object_access = true;
38+
SET test_oat_hooks.deny_exec_perms = true;
39+
SET test_oat_hooks.deny_utility_commands = true;
40+
41+
-- Try again as non-superuser with permisisons denied
42+
SET SESSION AUTHORIZATION regress_test_user;
43+
SELECT * FROM regress_test_table;
44+
SELECT regress_test_func('arg');
45+
SET work_mem = 8192;
46+
RESET work_mem;
47+
ALTER SYSTEM SET work_mem = 8192;
48+
ALTER SYSTEM RESET work_mem;
49+
50+
RESET SESSION AUTHORIZATION;
51+
52+
SET test_oat_hooks.audit = false;

0 commit comments

Comments
 (0)