Supported Migration and Function Ownership Model for Constrained PostgreSQL Roles #52660
Replies: 1 comment
|
Most of this is plain Postgres 16+ behaviour, so I checked it against the Postgres 17 docs and against the SQL that builds a hosted Supabase database (supabase/postgres), and ran the role setup on a scratch Postgres. Where Supabase has an official statement I link it; where it does not, I say so. 1. Migration identity. A dedicated LOGIN role works. The roles guide recommends "a new user for every service" instead of handing out the
2. Roles. On hosted projects
-- once, as postgres
create role app_owner nologin;
create role app_migrator login noinherit;
create role app_runtime nologin noinherit;
grant app_owner to postgres with set true;
grant app_owner to app_migrator with set true, inherit false; -- its only membership
grant create on database postgres to app_owner;
create schema app authorization app_owner;The migrator needs no 3. Functions. Two Postgres rules decide this. What I got when I ran this: with 4. Auth. Two options that need no -- a) read the claim directly (pg_catalog only)
(nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub')::uuid
-- b) one wrapper owned by postgres, EXECUTE granted to your roles
create function app.current_uid() returns uuid
language sql stable security definer set search_path = ''
as $$ select auth.uid() $$;
revoke execute on function app.current_uid() from public;
grant execute on function app.current_uid() to app_owner, app_runtime;5. Is any of this "officially supported"? The documented pieces are: one user per service, custom roles through the pooler, Checked on Postgres 18 (PGlite) against the 17 docs; the membership rules are the same from 16 up. Projects still on Postgres 15 behave differently (no |
Uh oh!
There was an error while loading. Please reload this page.
Supported Migration and Function Ownership Model for Constrained PostgreSQL Roles
Hello Supabase team and community,
I'm seeking guidance on an officially supported, least-privilege migration and function ownership model for hosted Supabase on the Free plan.
Our application uses PostgreSQL Row Level Security (RLS), dedicated runtime roles, and narrowly scoped database functions. Before deploying our security foundation, we need to establish a migration process that works within Supabase's hosted PostgreSQL role restrictions.
Our intended architecture separates:
The unresolved issue is how to establish and maintain these ownership relationships without granting excessive privileges to the routine migration identity.
Questions
1. Supported migration identity
Can hosted Supabase officially support a dedicated, restricted PostgreSQL LOGIN role as the routine migration executor, rather than authenticating as
postgres?Are there differences between using the Supabase CLI, Dashboard SQL Editor, direct connections, and the session pooler?
2. Role creation and membership
What is the supported approach for establishing and maintaining a dedicated NOLOGIN object-owner role when the migration executor is not a superuser?
In particular, which combinations of
CREATEROLE,ADMIN OPTION,SET OPTION, andINHERIT OPTIONare required or supported?3. Function ownership
How should migrations create, update, and transfer ownership of
SECURITY DEFINERfunctions while keeping the routine migration executor separate from the runtime function owner?Can this be achieved without granting the migration executor membership in a privileged runtime or administrative role?
4. Supabase Auth integration
For functions that use
auth.uid()orauth.jwt(), what minimum schema and function privileges must be granted to custom owner and runtime roles?Are there hosted-platform restrictions on maintaining these grants across migrations or platform updates?
5. Official alternative
If the proposed separation cannot be supported reliably on hosted Supabase Free, what migration and ownership model does Supabase recommend?
We are particularly interested in a model that avoids permanent, broadly privileged migration credentials and preserves least privilege throughout the function lifecycle.
Current status
We have completed local PostgreSQL and application-level tests, but these do not establish that the proposed ownership model is supported in a hosted Supabase environment.
We have not applied the proposed security migrations to our hosted database.
We are seeking architectural guidance before proceeding.
Related community discussions:
We would appreciate references to official documentation or a supported implementation pattern.
Thank you for your guidance.
All reactions