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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions