From 99bf3252d22233d14a11c9f95165237eb6c0d9fa Mon Sep 17 00:00:00 2001 From: Steven Schmid Date: Wed, 24 Apr 2024 09:12:59 +0200 Subject: [PATCH] Apply RLS policy to all users (not just the current role) Rails schema/migrations should be isolated from the upper user/role layer. Leverage the BYPASS RLS flag so we can connect with a admin user (or database owner) which by default bypasses rls (for migrations etc.), but all other roles should be subject to the RLS policy. Tables should not be hardwired to a specific role within postgres, otherwise we get exceptions such as `role "koleo_rls" cannot be dropped because some objects depend on it` when trying to drop the role (messy). --- lib/rls/migration.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rls/migration.rb b/lib/rls/migration.rb index b93b527..c1ea19a 100644 --- a/lib/rls/migration.rb +++ b/lib/rls/migration.rb @@ -4,18 +4,18 @@ module Migration # RESET rls.tenant_id will not remove the setting, current_setting(missing_ok=FALSE) will still return '' # There is no way to remove a setting right now in PostgreSQL, so missing_ok=FALSE is not useful # https://stackoverflow.com/questions/50923911/how-to-remove-configuration-parameter/50929568#50929568 - def rls_tenant_table(table_name, column: :tenant_id, role: RLS.role, &block) + def rls_tenant_table(table_name, column: :tenant_id, &block) reversible do |dir| dir.up do execute <<~SQL ALTER TABLE "#{table_name}" ENABLE ROW LEVEL SECURITY; - CREATE POLICY "#{table_name}_#{role}" ON "#{table_name}" TO "#{role}" + CREATE POLICY "#{table_name}_rls" ON "#{table_name}" FOR ALL USING ("#{column}" = NULLIF(current_setting('rls.tenant_id', TRUE), '')::bigint); SQL end dir.down do execute <<~SQL - DROP POLICY "#{table_name}_#{role}" ON "#{table_name}"; + DROP POLICY "#{table_name}_rls" ON "#{table_name}"; ALTER TABLE "#{table_name}" DISABLE ROW LEVEL SECURITY; SQL end