Thread: Before/After Trigger User Switching
When an operation is done throug a SECURITY DEFINER style function and causes a trigger the current_user depends on whether it is executed BEFORE or AFTER. I currently run 7.3.2. I believe the BEFORE behavior is correct while the AFTER behavior is wrong. A bug? already fixed? regards, Aasmund. CREATE TABLE a (b text); CREATE OR REPLACE FUNCTION public.ut () RETURNS TRIGGER SECURITY INVOKER LANGUAGE 'plpgsql' AS' DECLARE t TEXT; t2 TEXT; BEGIN t := current_user; t2 := session_user; RAISE NOTICE ''% Current: % Session: %'', TG_WHEN, t, t2; RETURN NEW; END '; CREATE TRIGGER "ut_trig_before" BEFORE UPDATE OR INSERT OR DELETE ON a FOR EACH ROW EXECUTE PROCEDURE public.ut(); CREATE TRIGGER "ut_trig_after" AFTER UPDATE OR INSERT OR DELETE ON a FOR EACH ROW EXECUTE PROCEDURE public.ut(); CREATE OR REPLACE FUNCTION public.at_test () RETURNS TEXT SECURITY DEFINER LANGUAGE 'sql' AS' INSERT INTO a VALUES (current_user); SELECT session_user::TEXT || ''/'' ||current_user::TEXT; '; db=> SELECT at_test(); NOTICE: BEFORE Current: godal Session: www NOTICE: AFTER Current: www Session: wwwat_test----------- www/godal (1 row) Aasmund Midttun Godal aasmund@godal.com - http://godal.com +47 40 45 20 46 - Leiv Tronstadsvei 2, NO-7051 Trondheim
I have upgraded to 7.3.4 and the problem persists. Aasmund Midttun Godal writes: > When an operation is done throug a SECURITY DEFINER style function and > causes a trigger the current_user depends on whether it is executed BEFORE > or AFTER. I currently run 7.3.2. I believe the BEFORE behavior is correct > while the AFTER behavior is wrong. A bug? already fixed? > > regards, > > Aasmund. > > > CREATE TABLE a (b text); > > > > CREATE OR REPLACE FUNCTION public.ut () RETURNS TRIGGER SECURITY INVOKER > LANGUAGE 'plpgsql' AS' > DECLARE > t TEXT; > t2 TEXT; > BEGIN > t := current_user; > t2 := session_user; > RAISE NOTICE ''% Current: % Session: %'', TG_WHEN, t, t2; > RETURN NEW; > END > '; > > CREATE TRIGGER "ut_trig_before" BEFORE UPDATE OR INSERT OR DELETE > ON a FOR EACH ROW EXECUTE PROCEDURE public.ut(); > > CREATE TRIGGER "ut_trig_after" AFTER UPDATE OR INSERT OR DELETE > ON a FOR EACH ROW EXECUTE PROCEDURE public.ut(); > > > > CREATE OR REPLACE FUNCTION public.at_test () RETURNS TEXT SECURITY DEFINER > LANGUAGE 'sql' AS' > INSERT INTO a VALUES (current_user); > SELECT session_user::TEXT || ''/'' ||current_user::TEXT; > '; > > > > db=> SELECT at_test(); > NOTICE: BEFORE Current: godal Session: www > NOTICE: AFTER Current: www Session: www > at_test > ----------- > www/godal > (1 row) > > > > > Aasmund Midttun Godal > > aasmund@godal.com - http://godal.com > +47 40 45 20 46 - Leiv Tronstadsvei 2, NO-7051 Trondheim > > ---------------------------(end of broadcast)--------------------------- > TIP 2: you can get off all lists at once with the unregister command > (send "unregister YourEmailAddressHere" to majordomo@postgresql.org) Aasmund Midttun Godal aasmund@godal.com - http://godal.com +47 40 45 20 46 - Leiv Tronstadsvei 2, NO-7051 Trondheim
"Aasmund Midttun Godal" <postgresql@aasmund.com> writes: > When an operation is done throug a SECURITY DEFINER style function and > causes a trigger the current_user depends on whether it is executed BEFORE > or AFTER. I currently run 7.3.2. I believe the BEFORE behavior is correct > while the AFTER behavior is wrong. A bug? already fixed? An AFTER trigger is not fired until the interactive statement is about to complete --- ie, after the SECURITY DEFINER function has returned. There has been previous discussion (inconclusive) about changing the time of invocation of AFTER triggers, but given the current timing this is the behavior I'd expect. regards, tom lane
Thank you for your quick reply! I understand your point of view, however the fact remains that you want the action to be done as though it was the DEFINER user that did it, and that has not changed even thoug the function itself has finished? regards, aasmund. Tom Lane writes: > "Aasmund Midttun Godal" <postgresql@aasmund.com> writes: >> When an operation is done throug a SECURITY DEFINER style function and >> causes a trigger the current_user depends on whether it is executed BEFORE >> or AFTER. I currently run 7.3.2. I believe the BEFORE behavior is correct >> while the AFTER behavior is wrong. A bug? already fixed? > > An AFTER trigger is not fired until the interactive statement is about > to complete --- ie, after the SECURITY DEFINER function has returned. > There has been previous discussion (inconclusive) about changing the > time of invocation of AFTER triggers, but given the current timing this > is the behavior I'd expect. > > regards, tom lane Aasmund Midttun Godal aasmund@godal.com - http://godal.com +47 40 45 20 46 - Leiv Tronstadsvei 2, NO-7051 Trondheim
"Aasmund Midttun Godal" <postgresql@aasmund.com> writes: > Thank you for your quick reply! > I understand your point of view, however the fact remains that you want the > action to be done as though it was the DEFINER user that did it, and that > has not changed even thoug the function itself has finished? <shrug> ... if there's any bug here, I'd argue that it's that we don't force trigger functions to run as the owner of the table they're on. The privileges of the user that did the INSERT or whatever are the wrong thing in any case, I'd say. Which suggests a workaround for the moment: your trigger function should be a SECURITY DEFINER. regards, tom lane