Re: RLS policy dump/restore failure due to elided type-casts

Поиск
Список
Период
Сортировка
От David G. Johnston
Тема Re: RLS policy dump/restore failure due to elided type-casts
Дата
Msg-id CAKFQuwYM__6TZzn5Na05wN7icZX7_R10LsvtNQbBmFG+v4BRGg@mail.gmail.com
обсуждение исходный текст
Ответ на Re: RLS policy dump/restore failure due to elided type-casts  (Adrian Klaver <adrian.klaver@aklaver.com>)
Ответы Re: RLS policy dump/restore failure due to elided type-casts  (Karl Czajkowski <karlcz@isi.edu>)
Список pgsql-general
On Wed, Apr 20, 2016 at 5:35 PM, Adrian Klaver <adrian.klaver@aklaver.com> wrote:
On 04/20/2016 05:18 PM, Karl Czajkowski wrote:
Our row level policies require very explicit casts in order to be
accepted by the DB, but those casts are discarded in the dumped policy
statements. Thus, an attempt to reload the dump file fails.  I'm not
sure if the underlying problem is that the cast shouldn't be required
in the first place, or if the normalization applied to the policy
expression is just incorrect.

Below is a trivialized example that shows the problem while removing
complexity found in our real policies.  We are doing this to implement
differentiated policies in a web application, where the web server
stores authenticated web client context into session parameters and
our policies check against those attributes rather than DB roles.

To work around this, we have to maintain our policies in a separate
SQL file, manually edit the dumps, and reapply our working policies.
This is obviously undesirable in the long run, where dumps taken as
periodic backups are not directly usable to reconstruct the DB...


Karl


Create a test database with these contents:

   CREATE FUNCTION current_attributes() RETURNS text[]
   STABLE AS $$
   BEGIN
     RETURN (
       SELECT array_agg(value)
       FROM json_array_elements_text(current_setting('ourapp.attributes')::json)
     );
   EXCEPTION WHEN OTHERS THEN
     RETURN NULL::text[];
   END;
   $$ LANGUAGE plpgsql;

   CREATE TABLE stuff (
     value text PRIMARY KEY
   );

   CREATE POLICY delete_stuff ON stuff
   FOR DELETE USING ('example attribute value' = ANY ( ((SELECT current_attributes()))::text[] ));


Trying to figure out how this works in the case above. Looks to me like you are comparing a text value to a text[].

Also why the the cast to text[], when the return value from the function is text[]?


The problem here is that:

scalar = ANY (array)
is different than
scalar = ANY (subquery)

The normalization in ?ruleutils? is munging things so that a query that is written as "scalar = ANY(array) is transformed into one that is "scalar = ANY(subquery)"

The extra parentheses and the cast are needed to force a "scalar = ANY(array)" where the basic expression looks like "scalar = ANY(subquery)"

Hope that helps - I could probably explain better but hopefully its not necessary..

David J.
 


The output of pg_dump (and similarly the '\d' command in psql) drops
the cast:

   CREATE POLICY delete_stuff ON stuff
   FOR DELETE TO PUBLIC USING (('example attribute value'::text = ANY (( SELECT current_attributes() AS current_attributes))));


And this causes an error when executing the dump file on a new database:

   ERROR:  operator does not exist: text = text[]
   HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.


 

В списке pgsql-general по дате отправления:

Предыдущее
От: "David G. Johnston"
Дата:
Сообщение: Re: Add relcreated (timestamp) column to pg_class catalog to record the time an object was created
Следующее
От: "David G. Johnston"
Дата:
Сообщение: Re: RLS policy dump/restore failure due to elided type-casts