cockroach
cockroach copied to clipboard
sql: support SECURITY DEFINER for routines
sql: correct error code
This patch assigns the pgcode (42501) to an ownership privilege check error. This aligns with postgres behavior.
postgres=> alter function testfn1(int) security definer;
ERROR: 42501: must be owner of function testfn1
LOCATION: aclcheck_error, aclchk.c:3790
Release note: None
opt/cat: add sentinel const for StableID
This patch adds the InvalidStableID constant
of 0 to describe an uninitialized stable ID.
Release note: None
sql: support SECURITY DEFINER for routines
Epic: CRDB-37477 Fixes: https://github.com/cockroachdb/cockroach/issues/121514
Release note (sql change): Added support for SECURITY DEFINER in user defined
functions (UDFs) and stored procedures (SPs). When a UDF/SP (routine) is created
with SECURITY DEFINER, at execution, the privileges of the owner will be
checked.
Routines can now specify [EXTERNAL] SECURITY INVOKER (this is the
default -- privileges of the invoker are checked at execution) or
[EXTERNAL] SECURITY DEFINER. Note that the EXTERNAL keyword is
optional and solely exists for sql conformity.
In addition, altering a UDF's security "mode" is accomplished by:
ALTER FUNCTION ... [EXTERNAL] SECURITY {INVOKER/DEFINER}.
@mgartner this is RFAL!
pkg/sql/opt/optbuilder/routine.go line 231 at r13 (raw file):
Previously, mgartner (Marcus Gartner) wrote…
We need to reset the user back to what it was previously after building the body of the function. I think we should move this block of code down to where other fields are reset in a
defer: https://github.com/cockroachdb/cockroach/blob/9f61a38b670e57873509568f67bb665e50cd1935/pkg/sql/opt/optbuilder/routine.go#L341-L356Can you also add this test case which shows the problem (the last SELECT should not be an error):
CREATE USER a; CREATE USER b; CREATE TABLE t (i INT); GRANT SELECT ON t TO a; SET ROLE b; CREATE FUNCTION f() RETURNS INT LANGUAGE SQL SECURITY DEFINER AS $$ SELECT 1 $$; SET ROLE a; SELECT i FROM t; -- i -- ----- -- (0 rows) SELECT f() UNION SELECT i FROM t; -- ERROR: user b does not have SELECT privilege on relation t -- SQLSTATE: 42501
(Feel free to adjust the test case to use the invoker, owner pattern already used in your tests, if you'd like.)
TFTR! ('-')7
bors r=mgartner, rafiss