db: add strict rls policy to protect user roles from self-escalation
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
-- Migration: Secure User Roles from Self-Escalation
|
||||||
|
-- Purpose: Prevent users from updating their own roles to 'admin' using RLS / Triggers.
|
||||||
|
|
||||||
|
-- Ensure RLS is enabled on users
|
||||||
|
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
-- Policy to allow users to view their own records
|
||||||
|
CREATE POLICY select_own_user ON public.users
|
||||||
|
FOR SELECT
|
||||||
|
TO authenticated
|
||||||
|
USING (auth.uid() = id);
|
||||||
|
|
||||||
|
-- Policy to allow admins to view all users
|
||||||
|
CREATE POLICY select_all_users_for_admin ON public.users
|
||||||
|
FOR SELECT
|
||||||
|
TO authenticated
|
||||||
|
USING (
|
||||||
|
(SELECT role FROM public.users WHERE id = auth.uid()) = 'admin'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Trigger to prevent any role updates to 'admin' from unauthorized users
|
||||||
|
CREATE OR REPLACE FUNCTION check_user_role_escalation()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
-- Only allow changes to the role column if executed by the service_role
|
||||||
|
IF (TG_OP = 'UPDATE' AND OLD.role IS DISTINCT FROM NEW.role) OR (TG_OP = 'INSERT') THEN
|
||||||
|
IF current_setting('role', true) <> 'service_role' THEN
|
||||||
|
-- Partners cannot upgrade themselves or others to admin
|
||||||
|
IF NEW.role = 'admin' THEN
|
||||||
|
RAISE EXCEPTION 'Unberechtigtes Rollen-Upgrade verweigert.';
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS enforce_role_protection ON public.users;
|
||||||
|
CREATE TRIGGER enforce_role_protection
|
||||||
|
BEFORE INSERT OR UPDATE ON public.users
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION check_user_role_escalation();
|
||||||
Reference in New Issue
Block a user