I ran this query
REVOKE SELECT ON services_connected FROM anon;
and added this policy
create policy "workspace_only"
on "public"."services_connected"
for all
to anon
using ((workspace_id = (((current_setting('request.jwt.claims'::text, true))::json ->> 'workspace_id'::text))::bigint));
My Expectation was that this would restrict select operation but allow other operations (insert, update, delete) but now I am getting permission denied for all my responses
This is a function I am calling
DROP FUNCTION IF EXISTS public.disconnect_service;
CREATE OR REPLACE FUNCTION public.disconnect_service(service_name_value TEXT)
RETURNS VOID AS $$
DECLARE
workspace_id_value BIGINT := ((current_setting('request.jwt.claims'::text, TRUE))::JSON ->> 'workspace_id')::BIGINT;
BEGIN
DELETE from services_connected where workspace_id = workspace_id_value and service_name = service_name_value;
DELETE FROM users_list WHERE workspace_id = workspace_id_value and service_name = service_name_value;
END;
$$ LANGUAGE plpgsql;
any idea what I am doing wrong?
2
Answers
For must
UPDATE
andDELETE
statements you also needSELECT
privileges. ConsiderPostgreSQL first has to read the table to identify the rows that meet the
WHERE
condition, only then it can delete the rows. That is not allowed without theSELECT
privilege, so you get a "permission denied" error. This statement would work:because it has no
WHERE
condition.If you have a policy in place that can verify the
workspace_id
condition, you don’t need to do it again in the function. You can go one step further and pass theservice_name
as a setting and leave it to the policy to check and compare it the same way you do forworkspace_id
: demoWithout the
where
, there’s no need forselect
permission. It’s breaking these statement the same way areturning
clause would – both of them potentially leak the contents of the tableanon
shouldn’t be able to inspect, soThat, or define the function with
security definer
parameter the way you did for a selector function you mentioned in the other thread.