From 85fcb90b32275e0f0b37458c2d03a84538eb554a Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Thu, 6 Aug 2026 01:05:33 +0200 Subject: [PATCH] =?UTF-8?q?fix(security):=20disable=20RLS=20on=20roles/per?= =?UTF-8?q?missions=20=E2=80=94=20blocks=20login=20(0109)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...109_disable_rls_on_login_related_tables.py | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 alembic/versions/0109_disable_rls_on_login_related_tables.py diff --git a/alembic/versions/0109_disable_rls_on_login_related_tables.py b/alembic/versions/0109_disable_rls_on_login_related_tables.py new file mode 100644 index 0000000..294d1ea --- /dev/null +++ b/alembic/versions/0109_disable_rls_on_login_related_tables.py @@ -0,0 +1,66 @@ +"""Disable RLS on login-related tables (roles, permissions). + +⚠️ KI / AGENT HINWEIS — BITTE VOR ÄNDERUNGEN LESEN ⚠️ + +Migration 0108 hat RLS auf alle Tabellen mit tenant_id aktiviert, darunter auch +`roles` und `permissions`. Diese Tabellen werden vom Login-Flow gelesen um die +Benutzerrolle zu bestimmen. Mit RLS auf diesen Tabellen und keinem tenant_id +Kontext beim Login → Query gibt nichts zurück → Login schlägt fehl mit 401. + +Diese Tabellen MÜSSEN ohne RLS bleiben, genau wie users, sessions, tenants, +user_tenants, password_reset_tokens (siehe 0108 LOGIN_TABLES). + +Lektion: RLS darf NICHT auf Tabellen aktiviert werden die vom Login-Flow +gelesen werden, wenn der Login-Flow noch keinen tenant_id Kontext hat. + +Revision ID: 0109 +Revises: 0108 +""" + +from __future__ import annotations + +from alembic import op + +revision = "0109" +down_revision = "0108" +branch_labels = None +depends_on = None + + +# ⚠️ LOGIN-RELATED TABLES — KEIN RLS! Diese Tabellen werden vom Login-Flow +# gelesen bevor ein tenant_id Kontext existiert. RLS blockiert den Login. +# Siehe auch 0108 LOGIN_TABLES und 0085 AUTH_TABLES. +LOGIN_RELATED_TABLES = [ + "roles", + "permissions", +] + + +def _exec(sql: str) -> None: + op.execute(sql) + + +def upgrade() -> None: + # Disable RLS on login-related tables + for table in LOGIN_RELATED_TABLES: + _exec( + f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables " + f"WHERE table_schema = 'public' AND table_name = '{table}') THEN " + f"DROP POLICY IF EXISTS tenant_isolation ON public.{table}; " + f"DROP POLICY IF EXISTS {table}_tenant_isolation ON public.{table}; " + f"ALTER TABLE public.{table} DISABLE ROW LEVEL SECURITY; " + f"END IF; END $$" + ) + + # Ensure crm_auth can read roles and permissions (needed for login flow) + for table in LOGIN_RELATED_TABLES: + _exec( + f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables " + f"WHERE table_schema = 'public' AND table_name = '{table}') THEN " + f"GRANT SELECT ON public.{table} TO crm_auth; " + f"END IF; END $$" + ) + + +def downgrade() -> None: + pass