Re: DEFINER / INVOKER conundrum

From: Erik Wienhold <ewie(at)ewie(dot)name>
To: walther(at)technowledgy(dot)de, Dominique Devienne <ddevienne(at)gmail(dot)com>, pgsql-general(at)lists(dot)postgresql(dot)org
Subject: Re: DEFINER / INVOKER conundrum
Date: 2023-04-04 08:46:49
Message-ID: 1333359937.578652.1680598009141@office.mailbox.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

> On 04/04/2023 07:55 CEST walther(at)technowledgy(dot)de wrote:
>
> Erik Wienhold:
> > A single DEFINER function works if you capture current_user with a parameter
> > and default value. Let's call it claimed_role. Use pg_has_role[0] to check
> > that session_user has the privilege for claimed_role (in case the function is
> > called with an explicit value), otherwise raise an exception.
> >
> > Connect as postgres:
> >
> > CREATE FUNCTION f(claimed_role text default current_user)
> > RETURNS TABLE (claimed_role text, curr_user text, sess_user text)
> > SECURITY DEFINER
> > LANGUAGE sql
> > $$ SELECT claimed_role, current_user, session_user $$;
>
> For me, checking whether session_user has the privilege for claimed_role
> is not enough, so I add a DOMAIN to the mix:
>
> CREATE DOMAIN current_user_only AS NAME CHECK (VALUE = CURRENT_USER);
>
> CREATE FUNCTION f(calling_user current_user_only DEFAULT CURRENT_USER)
> ...
> SECURITY DEFINER;
>
> This works, because the domain check is evaluated in the calling context.

Nice. It's equivalent to my version without the domain if the client can
execute SET ROLE before calling f, thereby injecting any role for which
pg_has_role(session_user, calling_user, 'MEMBER') returns true.

Dominique did not say whether he controls the clients or not.

--
Erik

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Erik Wienhold 2023-04-04 09:01:46 Re: ​jsonb @@ jsonpath operator doc: ​Only the first item of the result is taken into account
Previous Message walther 2023-04-04 05:55:25 Re: DEFINER / INVOKER conundrum