Skip to content

tests.rls_enabled(schema_name) fails on views #16

@inslayn

Description

@inslayn

I have a public schema that has only views in it (code and log output is an illustration created from the actual code involved).

create view public.public_view as select * from private.private_table;
create view public.secure_view with (security_barrier = true) as select * from private.private_table;

If I use the following:

select plan(1);
select tests.rls_enabled('public');
select * from finish();
rollback;

It fails with output similar to the following:

supabase test db
supabase/tests/20231107180900-app-schema.test.sql ...................... 
# Failed test 1: "All tables in thepublic schema should have row level security enabled"
#         have: 2
#         want: 0
# Looks like you failed 1 test of 1
Failed 1/1 subtests 

Now, since they are views, I can't enable row level security, so I tried to set security_barrier = true on the views which didn't work either.

Looking at the function code, there is no special handling for views, so I added the following after creating the extension at the start of the test plan:
Key parts are:

  1. only applying the row security check if the subject is not a view.
  2. enforcing that views in the test schema have security_barrier enabled.
CREATE OR REPLACE FUNCTION tests.rls_enabled (testing_schema text)
RETURNS text AS $$
    select is(
        coalesce((select count(pc.relname)::integer
            from pg_class pc
                join pg_namespace pn on pn.oid = pc.relnamespace and pn.nspname = rls_enabled.testing_schema
                join pg_type pt on pt.oid = pc.reltype
            where (pc.relkind != 'v' and pc.relrowsecurity = false) 
            or (pc.relkind = 'v' and (reloptions is null or 'security_barrier=true' != any(reloptions)))
            group by pc.relname, reloptions), 0) 
        ,
        0,
        'All tables in the ' || testing_schema || ' schema should have row level security enabled');
$$ LANGUAGE sql;

CREATE OR REPLACE FUNCTION tests.rls_enabled (testing_schema text, testing_table text)
RETURNS TEXT AS $$
    select is(
        coalesce((select count(*)::integer
            from pg_class pc
                join pg_namespace pn on pn.oid = pc.relnamespace and pn.nspname = rls_enabled.testing_schema and pc.relname = rls_enabled.testing_table
                join pg_type pt on pt.oid = pc.reltype
            where (pc.relkind != 'v' and pc.relrowsecurity = true) 
            or (pc.relkind = 'v' and 'security_barrier=true' = any(reloptions))
            group by pc.relname, reloptions), 0),
        1,
        testing_table || 'table in the' || testing_schema || ' schema should have row level security enabled'
    );
$$ LANGUAGE sql;

I honestly don't know the implications of this change, which is why I didn't make a PR instead. I would have thought someone must have come across this before, though it's more likely that I'm missing something 😅

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions