public inbox for [email protected]  
help / color / mirror / Atom feed
From: Vydehi Ganti <[email protected]>
To: Dominique Devienne <[email protected]>
Cc: Laurenz Albe <[email protected]>
Cc: [email protected]
Subject: Re: Clarification on RLS policy
Date: Fri, 25 Apr 2025 18:31:00 +0530
Message-ID: <CAMH-PzXe7AR2QDCDx3eRZPMGuixfTwm3sLF3kMZQkyNhtu=5qQ@mail.gmail.com> (raw)
In-Reply-To: <CAFCRh-_fXGfKk6b26xaDD1fg5OhLy92bNofmeDfX2TFjkQLLXA@mail.gmail.com>
References: <CAMH-PzUPN7JcLXJx-aJzGnJD2T-aSMo8gaMFkzO_x26urpMqSA@mail.gmail.com>
	<[email protected]>
	<CAFCRh-_fXGfKk6b26xaDD1fg5OhLy92bNofmeDfX2TFjkQLLXA@mail.gmail.com>

This is my Scenario:

I would need a policy on table Activity which has a column country_code .
In the policy i would need to call a function get_country as below which
queries the users table based on current user and checks which country code
that user has access to.
Then it should build up the lPredicate with the filter condition and append
to the query user runs on the Activity table.
*Can you please guide how to achieve this?*

CREATE OR REPLACE FUNCTION one.get_country(
powner name,
ptable_name name)
    RETURNS character varying
LANGUAGE 'plpgsql'
    COST 100
    STABLE PARALLEL UNSAFE
AS $BODY$
DECLARE

    lOSUser         varchar(4000) := UPPER(SUBSTRING(current_user FROM
POSITION('\' IN current_user) + 1));
    lPredicate      varchar(4000) := NULL;
    lCount          integer;

  i RECORD;

BEGIN
    IF position('ro' in current_user) = 0 THEN
        lPredicate := '1=1';
    ELSE
        -- Users associated to explicit country_code
        FOR i IN (SELECT r.country_code AS country_code
                    FROM one.users  u
                        where UPPER(SUBSTR(u.Login, INSTR(u.Login, '\', -1)
+ 1)) = lOSUser )
                    WHERE u.role_type = 'reader') LOOP
            lPredicate := lPredicate||''''||i.country_code||''',';
        END LOOP;

        IF lPredicate IS NOT NULL THEN
            lPredicate := 'SUBSTR("id",1,3) IN ('||SUBSTR(lPredicate, 1,
LENGTH(lPredicate)-1)||')';
        ELSE
            lPredicate := '1=1';
        END IF;
    END IF;

    RETURN lPredicate;

END;
$BODY$;

For the below policy statement it created the policy but i cant call that
CREATE POLICY "Codebase_Filter"
    ON one.activity
    FOR SELECT
    TO one
    USING (one.get_country('one','activity'));

On Fri, Apr 25, 2025 at 6:23 PM Dominique Devienne <[email protected]>
wrote:

> On Fri, Apr 25, 2025 at 2:43 PM Laurenz Albe <[email protected]>
> wrote:
> > On Fri, 2025-04-25 at 12:38 +0530, Vydehi Ganti wrote:
> > > We are presently using Postgresql:PostgreSQL 15.12 on
> x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat
> 8.5.0-23), 64-bit
> > > 2.The function would return a character varying string which should be
> appended
> > >   to the select as a filter.
> >
> > You cannot add whole WHERE conditions to a query dynamically.
> > The only way to fix that is to solve the problem differently.
> > Since you didn't tell us details, we cannot tell you how.
>
> Laurenz is right. That's not how RLS works in PostgreSQL, unlike Oracle.
> In PostgreSQL, you must use a boolean SQL expression, often by calling
> a function.
> You don't simply return some SQL text that Oracle then "splices" into
> the SELECT.
>
> E.g., if you use custom ROLEs as an implementation detail for your
> security rules,
> your policy can be as simple as calling the pg_has_role() built-in
> function. FWIW. --DD
>
> CREATE POLICY ... USING (pg_has_role('SomeRole', 'MEMBER'))
>


view thread (10+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected]
  Subject: Re: Clarification on RLS policy
  In-Reply-To: <CAMH-PzXe7AR2QDCDx3eRZPMGuixfTwm3sLF3kMZQkyNhtu=5qQ@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox