From e0ee3c5b3d30b48cc6305c54d604d0df7e5b5e33 Mon Sep 17 00:00:00 2001 From: Chris Gwilliams <517923+encima@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:26:04 +0300 Subject: [PATCH 1/9] add migration with admin option for permissions for postgres to administer roles beyond pg16 --- ...53_grant_with_admin_to_postgres_16_and_above.sql | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql diff --git a/migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql b/migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql new file mode 100644 index 000000000..38bd9c87e --- /dev/null +++ b/migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql @@ -0,0 +1,13 @@ +-- migrate:up +DO $$ +DECLARE + major_version INT; +BEGIN + SELECT current_setting('server_version_num')::INT / 10000 INTO major_version; + + IF major_version >= 16 THEN + GRANT anon, authenticated, service_role TO postgres WITH ADMIN OPTION; + END IF; +END $$; + +-- migrate:down From 62bffe1c4865f8fa5a19623d759d18467eee2c3c Mon Sep 17 00:00:00 2001 From: Paul Cioanca Date: Thu, 5 Jun 2025 20:04:00 +0300 Subject: [PATCH 2/9] chore: bump AMIs --- ansible/vars.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ansible/vars.yml b/ansible/vars.yml index 1a5fe00d3..c72c962f7 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -9,9 +9,9 @@ postgres_major: # Full version strings for each major version postgres_release: - postgresorioledb-17: "17.0.1.090-orioledb" - postgres17: "17.4.1.040" - postgres15: "15.8.1.097" + postgresorioledb-17: "17.0.1.091-orioledb" + postgres17: "17.4.1.041" + postgres15: "15.8.1.098" # Non Postgres Extensions pgbouncer_release: "1.19.0" From 9bdc6e3c3585b522bd2f369f221f45a94683f051 Mon Sep 17 00:00:00 2001 From: Paul Cioanca Date: Thu, 5 Jun 2025 20:07:50 +0300 Subject: [PATCH 3/9] chore: update snapshot --- nix/tests/expected/roles.out | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/tests/expected/roles.out b/nix/tests/expected/roles.out index 2d2d5060e..23be83bf6 100644 --- a/nix/tests/expected/roles.out +++ b/nix/tests/expected/roles.out @@ -117,13 +117,13 @@ order by pgsodium_keyholder | pgsodium_keyiduser | f pgsodium_keymaker | pgsodium_keyholder | f pgsodium_keymaker | pgsodium_keyiduser | f - postgres | anon | f - postgres | authenticated | f + postgres | anon | t + postgres | authenticated | t postgres | pg_monitor | f postgres | pg_read_all_data | f postgres | pg_signal_backend | f postgres | pgtle_admin | f - postgres | service_role | f + postgres | service_role | t supabase_read_only_user | pg_read_all_data | f supabase_storage_admin | authenticator | f (18 rows) From 7115a63a3ef7f532b4c23e442aa7582313a3a8d0 Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Thu, 5 Jun 2025 19:27:29 +0200 Subject: [PATCH 4/9] Add separate tests output for Postgres 15 and 17 --- nix/tests/expected/roles.out | 6 +- nix/tests/expected/roles_1.out | 560 +++++++++++++++++++++++++++++++++ 2 files changed, 563 insertions(+), 3 deletions(-) create mode 100644 nix/tests/expected/roles_1.out diff --git a/nix/tests/expected/roles.out b/nix/tests/expected/roles.out index 23be83bf6..2d2d5060e 100644 --- a/nix/tests/expected/roles.out +++ b/nix/tests/expected/roles.out @@ -117,13 +117,13 @@ order by pgsodium_keyholder | pgsodium_keyiduser | f pgsodium_keymaker | pgsodium_keyholder | f pgsodium_keymaker | pgsodium_keyiduser | f - postgres | anon | t - postgres | authenticated | t + postgres | anon | f + postgres | authenticated | f postgres | pg_monitor | f postgres | pg_read_all_data | f postgres | pg_signal_backend | f postgres | pgtle_admin | f - postgres | service_role | t + postgres | service_role | f supabase_read_only_user | pg_read_all_data | f supabase_storage_admin | authenticator | f (18 rows) diff --git a/nix/tests/expected/roles_1.out b/nix/tests/expected/roles_1.out new file mode 100644 index 000000000..23be83bf6 --- /dev/null +++ b/nix/tests/expected/roles_1.out @@ -0,0 +1,560 @@ +-- Some predefined roles don't exist in earlier versions of Postgres, so we +-- exclude them in this test file. They're tested in version-specific test files +-- (z__roles.sql). +-- +-- Currently those roles are: +-- pg_create_subscription, pg_maintain, pg_use_reserved_connections +-- all roles and attributes +select + rolname, + rolcreaterole , + rolcanlogin , + rolsuper , + rolinherit , + rolcreatedb , + rolreplication , + rolconnlimit , + rolbypassrls , + rolvaliduntil +from pg_roles r +where rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +order by rolname; + rolname | rolcreaterole | rolcanlogin | rolsuper | rolinherit | rolcreatedb | rolreplication | rolconnlimit | rolbypassrls | rolvaliduntil +----------------------------+---------------+-------------+----------+------------+-------------+----------------+--------------+--------------+--------------- + anon | f | f | f | t | f | f | -1 | f | + authenticated | f | f | f | t | f | f | -1 | f | + authenticator | f | t | f | f | f | f | -1 | f | + dashboard_user | t | f | f | t | t | t | -1 | f | + pg_checkpoint | f | f | f | t | f | f | -1 | f | + pg_database_owner | f | f | f | t | f | f | -1 | f | + pg_execute_server_program | f | f | f | t | f | f | -1 | f | + pg_monitor | f | f | f | t | f | f | -1 | f | + pg_read_all_data | f | f | f | t | f | f | -1 | f | + pg_read_all_settings | f | f | f | t | f | f | -1 | f | + pg_read_all_stats | f | f | f | t | f | f | -1 | f | + pg_read_server_files | f | f | f | t | f | f | -1 | f | + pg_signal_backend | f | f | f | t | f | f | -1 | f | + pg_stat_scan_tables | f | f | f | t | f | f | -1 | f | + pg_write_all_data | f | f | f | t | f | f | -1 | f | + pg_write_server_files | f | f | f | t | f | f | -1 | f | + pgbouncer | f | t | f | t | f | f | -1 | f | + pgsodium_keyholder | f | f | f | t | f | f | -1 | f | + pgsodium_keyiduser | f | f | f | t | f | f | -1 | f | + pgsodium_keymaker | f | f | f | t | f | f | -1 | f | + pgtle_admin | f | f | f | t | f | f | -1 | f | + postgres | t | t | f | t | t | t | -1 | t | + service_role | f | f | f | t | f | f | -1 | t | + supabase_admin | t | t | t | t | t | t | -1 | t | + supabase_auth_admin | t | t | f | f | f | f | -1 | f | + supabase_functions_admin | t | t | f | f | f | f | -1 | f | + supabase_read_only_user | f | t | f | t | f | f | -1 | t | + supabase_replication_admin | f | t | f | t | f | t | -1 | f | + supabase_storage_admin | t | t | f | f | f | f | -1 | f | +(29 rows) + +select + rolname, + rolconfig +from pg_roles r +where rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +order by rolname; + rolname | rolconfig +----------------------------+--------------------------------------------------------------------------------- + anon | {statement_timeout=3s} + authenticated | {statement_timeout=8s} + authenticator | {session_preload_libraries=safeupdate,statement_timeout=8s,lock_timeout=8s} + dashboard_user | + pg_checkpoint | + pg_database_owner | + pg_execute_server_program | + pg_monitor | + pg_read_all_data | + pg_read_all_settings | + pg_read_all_stats | + pg_read_server_files | + pg_signal_backend | + pg_stat_scan_tables | + pg_write_all_data | + pg_write_server_files | + pgbouncer | + pgsodium_keyholder | + pgsodium_keyiduser | + pgsodium_keymaker | + pgtle_admin | + postgres | {"search_path=\"\\$user\", public, extensions"} + service_role | + supabase_admin | {"search_path=\"$user\", public, auth, extensions",log_statement=none} + supabase_auth_admin | {search_path=auth,idle_in_transaction_session_timeout=60000,log_statement=none} + supabase_functions_admin | + supabase_read_only_user | + supabase_replication_admin | + supabase_storage_admin | {search_path=storage,log_statement=none} +(29 rows) + +-- all role memberships +select + r.rolname as member, + g.rolname as "member_of (can become)", + m.admin_option +from + pg_roles r +left join + pg_auth_members m on r.oid = m.member +left join + pg_roles g on m.roleid = g.oid +where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +order by + r.rolname, g.rolname; + member | member_of (can become) | admin_option +-------------------------+------------------------+-------------- + authenticator | anon | f + authenticator | authenticated | f + authenticator | service_role | f + pg_monitor | pg_read_all_settings | f + pg_monitor | pg_read_all_stats | f + pg_monitor | pg_stat_scan_tables | f + pgsodium_keyholder | pgsodium_keyiduser | f + pgsodium_keymaker | pgsodium_keyholder | f + pgsodium_keymaker | pgsodium_keyiduser | f + postgres | anon | t + postgres | authenticated | t + postgres | pg_monitor | f + postgres | pg_read_all_data | f + postgres | pg_signal_backend | f + postgres | pgtle_admin | f + postgres | service_role | t + supabase_read_only_user | pg_read_all_data | f + supabase_storage_admin | authenticator | f +(18 rows) + +-- Check all privileges of the roles on the schemas +select schema_name, privilege_type, grantee, default_for +from ( + -- ALTER DEFAULT privileges on schemas + select + n.nspname as schema_name, + a.privilege_type, + r.rolname as grantee, + d.defaclrole::regrole as default_for, + case when n.nspname = 'public' then 0 else 1 end as schema_order + from + pg_default_acl d + join + pg_namespace n on d.defaclnamespace = n.oid + cross join lateral aclexplode(d.defaclacl) as a + join + pg_roles r on a.grantee = r.oid + where + -- PG17+, handled in version-specific test files + a.privilege_type != 'MAINTAIN' + union all + -- explicit grant usage and create on the schemas + select + n.nspname as schema_name, + a.privilege_type, + r.rolname as grantee, + n.nspowner::regrole as default_for, + case when n.nspname = 'public' then 0 else 1 end as schema_order + from + pg_namespace n + cross join lateral aclexplode(n.nspacl) as a + join + pg_roles r on a.grantee = r.oid + where + a.privilege_type in ('CREATE', 'USAGE') +) sub +order by schema_order, schema_name, privilege_type, grantee, default_for; + schema_name | privilege_type | grantee | default_for +--------------------+----------------+--------------------------+--------------------- + public | CREATE | pg_database_owner | pg_database_owner + public | DELETE | anon | supabase_admin + public | DELETE | anon | postgres + public | DELETE | authenticated | supabase_admin + public | DELETE | authenticated | postgres + public | DELETE | postgres | supabase_admin + public | DELETE | postgres | postgres + public | DELETE | service_role | supabase_admin + public | DELETE | service_role | postgres + public | EXECUTE | anon | supabase_admin + public | EXECUTE | anon | postgres + public | EXECUTE | authenticated | supabase_admin + public | EXECUTE | authenticated | postgres + public | EXECUTE | postgres | supabase_admin + public | EXECUTE | postgres | postgres + public | EXECUTE | service_role | supabase_admin + public | EXECUTE | service_role | postgres + public | INSERT | anon | supabase_admin + public | INSERT | anon | postgres + public | INSERT | authenticated | supabase_admin + public | INSERT | authenticated | postgres + public | INSERT | postgres | supabase_admin + public | INSERT | postgres | postgres + public | INSERT | service_role | supabase_admin + public | INSERT | service_role | postgres + public | REFERENCES | anon | supabase_admin + public | REFERENCES | anon | postgres + public | REFERENCES | authenticated | supabase_admin + public | REFERENCES | authenticated | postgres + public | REFERENCES | postgres | supabase_admin + public | REFERENCES | postgres | postgres + public | REFERENCES | service_role | supabase_admin + public | REFERENCES | service_role | postgres + public | SELECT | anon | supabase_admin + public | SELECT | anon | supabase_admin + public | SELECT | anon | postgres + public | SELECT | anon | postgres + public | SELECT | authenticated | supabase_admin + public | SELECT | authenticated | supabase_admin + public | SELECT | authenticated | postgres + public | SELECT | authenticated | postgres + public | SELECT | postgres | supabase_admin + public | SELECT | postgres | supabase_admin + public | SELECT | postgres | postgres + public | SELECT | postgres | postgres + public | SELECT | service_role | supabase_admin + public | SELECT | service_role | supabase_admin + public | SELECT | service_role | postgres + public | SELECT | service_role | postgres + public | TRIGGER | anon | supabase_admin + public | TRIGGER | anon | postgres + public | TRIGGER | authenticated | supabase_admin + public | TRIGGER | authenticated | postgres + public | TRIGGER | postgres | supabase_admin + public | TRIGGER | postgres | postgres + public | TRIGGER | service_role | supabase_admin + public | TRIGGER | service_role | postgres + public | TRUNCATE | anon | supabase_admin + public | TRUNCATE | anon | postgres + public | TRUNCATE | authenticated | supabase_admin + public | TRUNCATE | authenticated | postgres + public | TRUNCATE | postgres | supabase_admin + public | TRUNCATE | postgres | postgres + public | TRUNCATE | service_role | supabase_admin + public | TRUNCATE | service_role | postgres + public | UPDATE | anon | supabase_admin + public | UPDATE | anon | supabase_admin + public | UPDATE | anon | postgres + public | UPDATE | anon | postgres + public | UPDATE | authenticated | supabase_admin + public | UPDATE | authenticated | supabase_admin + public | UPDATE | authenticated | postgres + public | UPDATE | authenticated | postgres + public | UPDATE | postgres | supabase_admin + public | UPDATE | postgres | supabase_admin + public | UPDATE | postgres | postgres + public | UPDATE | postgres | postgres + public | UPDATE | service_role | supabase_admin + public | UPDATE | service_role | supabase_admin + public | UPDATE | service_role | postgres + public | UPDATE | service_role | postgres + public | USAGE | anon | supabase_admin + public | USAGE | anon | pg_database_owner + public | USAGE | anon | postgres + public | USAGE | authenticated | supabase_admin + public | USAGE | authenticated | pg_database_owner + public | USAGE | authenticated | postgres + public | USAGE | pg_database_owner | pg_database_owner + public | USAGE | postgres | supabase_admin + public | USAGE | postgres | pg_database_owner + public | USAGE | postgres | postgres + public | USAGE | service_role | supabase_admin + public | USAGE | service_role | pg_database_owner + public | USAGE | service_role | postgres + auth | CREATE | dashboard_user | supabase_admin + auth | CREATE | supabase_admin | supabase_admin + auth | CREATE | supabase_auth_admin | supabase_admin + auth | DELETE | dashboard_user | supabase_auth_admin + auth | DELETE | postgres | supabase_auth_admin + auth | EXECUTE | dashboard_user | supabase_auth_admin + auth | EXECUTE | postgres | supabase_auth_admin + auth | INSERT | dashboard_user | supabase_auth_admin + auth | INSERT | postgres | supabase_auth_admin + auth | REFERENCES | dashboard_user | supabase_auth_admin + auth | REFERENCES | postgres | supabase_auth_admin + auth | SELECT | dashboard_user | supabase_auth_admin + auth | SELECT | dashboard_user | supabase_auth_admin + auth | SELECT | postgres | supabase_auth_admin + auth | SELECT | postgres | supabase_auth_admin + auth | TRIGGER | dashboard_user | supabase_auth_admin + auth | TRIGGER | postgres | supabase_auth_admin + auth | TRUNCATE | dashboard_user | supabase_auth_admin + auth | TRUNCATE | postgres | supabase_auth_admin + auth | UPDATE | dashboard_user | supabase_auth_admin + auth | UPDATE | dashboard_user | supabase_auth_admin + auth | UPDATE | postgres | supabase_auth_admin + auth | UPDATE | postgres | supabase_auth_admin + auth | USAGE | anon | supabase_admin + auth | USAGE | authenticated | supabase_admin + auth | USAGE | dashboard_user | supabase_admin + auth | USAGE | dashboard_user | supabase_auth_admin + auth | USAGE | postgres | supabase_admin + auth | USAGE | postgres | supabase_auth_admin + auth | USAGE | service_role | supabase_admin + auth | USAGE | supabase_admin | supabase_admin + auth | USAGE | supabase_auth_admin | supabase_admin + extensions | CREATE | dashboard_user | postgres + extensions | CREATE | postgres | postgres + extensions | DELETE | postgres | supabase_admin + extensions | EXECUTE | postgres | supabase_admin + extensions | INSERT | postgres | supabase_admin + extensions | REFERENCES | postgres | supabase_admin + extensions | SELECT | postgres | supabase_admin + extensions | SELECT | postgres | supabase_admin + extensions | TRIGGER | postgres | supabase_admin + extensions | TRUNCATE | postgres | supabase_admin + extensions | UPDATE | postgres | supabase_admin + extensions | UPDATE | postgres | supabase_admin + extensions | USAGE | anon | postgres + extensions | USAGE | authenticated | postgres + extensions | USAGE | dashboard_user | postgres + extensions | USAGE | postgres | supabase_admin + extensions | USAGE | postgres | postgres + extensions | USAGE | service_role | postgres + graphql | CREATE | supabase_admin | supabase_admin + graphql | DELETE | anon | supabase_admin + graphql | DELETE | authenticated | supabase_admin + graphql | DELETE | postgres | supabase_admin + graphql | DELETE | service_role | supabase_admin + graphql | EXECUTE | anon | supabase_admin + graphql | EXECUTE | authenticated | supabase_admin + graphql | EXECUTE | postgres | supabase_admin + graphql | EXECUTE | service_role | supabase_admin + graphql | INSERT | anon | supabase_admin + graphql | INSERT | authenticated | supabase_admin + graphql | INSERT | postgres | supabase_admin + graphql | INSERT | service_role | supabase_admin + graphql | REFERENCES | anon | supabase_admin + graphql | REFERENCES | authenticated | supabase_admin + graphql | REFERENCES | postgres | supabase_admin + graphql | REFERENCES | service_role | supabase_admin + graphql | SELECT | anon | supabase_admin + graphql | SELECT | anon | supabase_admin + graphql | SELECT | authenticated | supabase_admin + graphql | SELECT | authenticated | supabase_admin + graphql | SELECT | postgres | supabase_admin + graphql | SELECT | postgres | supabase_admin + graphql | SELECT | service_role | supabase_admin + graphql | SELECT | service_role | supabase_admin + graphql | TRIGGER | anon | supabase_admin + graphql | TRIGGER | authenticated | supabase_admin + graphql | TRIGGER | postgres | supabase_admin + graphql | TRIGGER | service_role | supabase_admin + graphql | TRUNCATE | anon | supabase_admin + graphql | TRUNCATE | authenticated | supabase_admin + graphql | TRUNCATE | postgres | supabase_admin + graphql | TRUNCATE | service_role | supabase_admin + graphql | UPDATE | anon | supabase_admin + graphql | UPDATE | anon | supabase_admin + graphql | UPDATE | authenticated | supabase_admin + graphql | UPDATE | authenticated | supabase_admin + graphql | UPDATE | postgres | supabase_admin + graphql | UPDATE | postgres | supabase_admin + graphql | UPDATE | service_role | supabase_admin + graphql | UPDATE | service_role | supabase_admin + graphql | USAGE | anon | supabase_admin + graphql | USAGE | anon | supabase_admin + graphql | USAGE | authenticated | supabase_admin + graphql | USAGE | authenticated | supabase_admin + graphql | USAGE | postgres | supabase_admin + graphql | USAGE | postgres | supabase_admin + graphql | USAGE | service_role | supabase_admin + graphql | USAGE | service_role | supabase_admin + graphql | USAGE | supabase_admin | supabase_admin + graphql_public | CREATE | supabase_admin | supabase_admin + graphql_public | DELETE | anon | supabase_admin + graphql_public | DELETE | authenticated | supabase_admin + graphql_public | DELETE | postgres | supabase_admin + graphql_public | DELETE | service_role | supabase_admin + graphql_public | EXECUTE | anon | supabase_admin + graphql_public | EXECUTE | authenticated | supabase_admin + graphql_public | EXECUTE | postgres | supabase_admin + graphql_public | EXECUTE | service_role | supabase_admin + graphql_public | INSERT | anon | supabase_admin + graphql_public | INSERT | authenticated | supabase_admin + graphql_public | INSERT | postgres | supabase_admin + graphql_public | INSERT | service_role | supabase_admin + graphql_public | REFERENCES | anon | supabase_admin + graphql_public | REFERENCES | authenticated | supabase_admin + graphql_public | REFERENCES | postgres | supabase_admin + graphql_public | REFERENCES | service_role | supabase_admin + graphql_public | SELECT | anon | supabase_admin + graphql_public | SELECT | anon | supabase_admin + graphql_public | SELECT | authenticated | supabase_admin + graphql_public | SELECT | authenticated | supabase_admin + graphql_public | SELECT | postgres | supabase_admin + graphql_public | SELECT | postgres | supabase_admin + graphql_public | SELECT | service_role | supabase_admin + graphql_public | SELECT | service_role | supabase_admin + graphql_public | TRIGGER | anon | supabase_admin + graphql_public | TRIGGER | authenticated | supabase_admin + graphql_public | TRIGGER | postgres | supabase_admin + graphql_public | TRIGGER | service_role | supabase_admin + graphql_public | TRUNCATE | anon | supabase_admin + graphql_public | TRUNCATE | authenticated | supabase_admin + graphql_public | TRUNCATE | postgres | supabase_admin + graphql_public | TRUNCATE | service_role | supabase_admin + graphql_public | UPDATE | anon | supabase_admin + graphql_public | UPDATE | anon | supabase_admin + graphql_public | UPDATE | authenticated | supabase_admin + graphql_public | UPDATE | authenticated | supabase_admin + graphql_public | UPDATE | postgres | supabase_admin + graphql_public | UPDATE | postgres | supabase_admin + graphql_public | UPDATE | service_role | supabase_admin + graphql_public | UPDATE | service_role | supabase_admin + graphql_public | USAGE | anon | supabase_admin + graphql_public | USAGE | anon | supabase_admin + graphql_public | USAGE | authenticated | supabase_admin + graphql_public | USAGE | authenticated | supabase_admin + graphql_public | USAGE | postgres | supabase_admin + graphql_public | USAGE | postgres | supabase_admin + graphql_public | USAGE | service_role | supabase_admin + graphql_public | USAGE | service_role | supabase_admin + graphql_public | USAGE | supabase_admin | supabase_admin + information_schema | CREATE | supabase_admin | supabase_admin + information_schema | USAGE | supabase_admin | supabase_admin + net | CREATE | supabase_admin | supabase_admin + net | USAGE | anon | supabase_admin + net | USAGE | authenticated | supabase_admin + net | USAGE | postgres | supabase_admin + net | USAGE | service_role | supabase_admin + net | USAGE | supabase_admin | supabase_admin + net | USAGE | supabase_functions_admin | supabase_admin + pg_catalog | CREATE | supabase_admin | supabase_admin + pg_catalog | USAGE | supabase_admin | supabase_admin + pgmq | CREATE | supabase_admin | supabase_admin + pgmq | SELECT | pg_monitor | supabase_admin + pgmq | SELECT | pg_monitor | supabase_admin + pgmq | USAGE | pg_monitor | supabase_admin + pgmq | USAGE | supabase_admin | supabase_admin + pgsodium | CREATE | supabase_admin | supabase_admin + pgsodium | DELETE | pgsodium_keyholder | supabase_admin + pgsodium | INSERT | pgsodium_keyholder | supabase_admin + pgsodium | REFERENCES | pgsodium_keyholder | supabase_admin + pgsodium | SELECT | pgsodium_keyholder | supabase_admin + pgsodium | SELECT | pgsodium_keyholder | supabase_admin + pgsodium | TRIGGER | pgsodium_keyholder | supabase_admin + pgsodium | TRUNCATE | pgsodium_keyholder | supabase_admin + pgsodium | UPDATE | pgsodium_keyholder | supabase_admin + pgsodium | UPDATE | pgsodium_keyholder | supabase_admin + pgsodium | USAGE | pgsodium_keyholder | supabase_admin + pgsodium | USAGE | supabase_admin | supabase_admin + pgsodium_masks | CREATE | supabase_admin | supabase_admin + pgsodium_masks | DELETE | pgsodium_keyiduser | supabase_admin + pgsodium_masks | EXECUTE | pgsodium_keyiduser | supabase_admin + pgsodium_masks | INSERT | pgsodium_keyiduser | supabase_admin + pgsodium_masks | REFERENCES | pgsodium_keyiduser | supabase_admin + pgsodium_masks | SELECT | pgsodium_keyiduser | supabase_admin + pgsodium_masks | SELECT | pgsodium_keyiduser | supabase_admin + pgsodium_masks | TRIGGER | pgsodium_keyiduser | supabase_admin + pgsodium_masks | TRUNCATE | pgsodium_keyiduser | supabase_admin + pgsodium_masks | UPDATE | pgsodium_keyiduser | supabase_admin + pgsodium_masks | UPDATE | pgsodium_keyiduser | supabase_admin + pgsodium_masks | USAGE | pgsodium_keyiduser | supabase_admin + pgsodium_masks | USAGE | pgsodium_keyiduser | supabase_admin + pgsodium_masks | USAGE | supabase_admin | supabase_admin + pgtle | CREATE | pgtle_admin | supabase_admin + pgtle | CREATE | supabase_admin | supabase_admin + pgtle | USAGE | pgtle_admin | supabase_admin + pgtle | USAGE | supabase_admin | supabase_admin + realtime | CREATE | supabase_admin | supabase_admin + realtime | DELETE | dashboard_user | supabase_admin + realtime | DELETE | postgres | supabase_admin + realtime | EXECUTE | dashboard_user | supabase_admin + realtime | EXECUTE | postgres | supabase_admin + realtime | INSERT | dashboard_user | supabase_admin + realtime | INSERT | postgres | supabase_admin + realtime | REFERENCES | dashboard_user | supabase_admin + realtime | REFERENCES | postgres | supabase_admin + realtime | SELECT | dashboard_user | supabase_admin + realtime | SELECT | dashboard_user | supabase_admin + realtime | SELECT | postgres | supabase_admin + realtime | SELECT | postgres | supabase_admin + realtime | TRIGGER | dashboard_user | supabase_admin + realtime | TRIGGER | postgres | supabase_admin + realtime | TRUNCATE | dashboard_user | supabase_admin + realtime | TRUNCATE | postgres | supabase_admin + realtime | UPDATE | dashboard_user | supabase_admin + realtime | UPDATE | dashboard_user | supabase_admin + realtime | UPDATE | postgres | supabase_admin + realtime | UPDATE | postgres | supabase_admin + realtime | USAGE | dashboard_user | supabase_admin + realtime | USAGE | postgres | supabase_admin + realtime | USAGE | postgres | supabase_admin + realtime | USAGE | supabase_admin | supabase_admin + repack | CREATE | postgres | supabase_admin + repack | CREATE | supabase_admin | supabase_admin + repack | DELETE | postgres | supabase_admin + repack | INSERT | postgres | supabase_admin + repack | REFERENCES | postgres | supabase_admin + repack | SELECT | postgres | supabase_admin + repack | SELECT | postgres | supabase_admin + repack | TRIGGER | postgres | supabase_admin + repack | TRUNCATE | postgres | supabase_admin + repack | UPDATE | postgres | supabase_admin + repack | UPDATE | postgres | supabase_admin + repack | USAGE | postgres | supabase_admin + repack | USAGE | postgres | supabase_admin + repack | USAGE | supabase_admin | supabase_admin + storage | CREATE | dashboard_user | supabase_admin + storage | CREATE | supabase_admin | supabase_admin + storage | CREATE | supabase_storage_admin | supabase_admin + storage | DELETE | anon | postgres + storage | DELETE | authenticated | postgres + storage | DELETE | postgres | postgres + storage | DELETE | service_role | postgres + storage | EXECUTE | anon | postgres + storage | EXECUTE | authenticated | postgres + storage | EXECUTE | postgres | postgres + storage | EXECUTE | service_role | postgres + storage | INSERT | anon | postgres + storage | INSERT | authenticated | postgres + storage | INSERT | postgres | postgres + storage | INSERT | service_role | postgres + storage | REFERENCES | anon | postgres + storage | REFERENCES | authenticated | postgres + storage | REFERENCES | postgres | postgres + storage | REFERENCES | service_role | postgres + storage | SELECT | anon | postgres + storage | SELECT | anon | postgres + storage | SELECT | authenticated | postgres + storage | SELECT | authenticated | postgres + storage | SELECT | postgres | postgres + storage | SELECT | postgres | postgres + storage | SELECT | service_role | postgres + storage | SELECT | service_role | postgres + storage | TRIGGER | anon | postgres + storage | TRIGGER | authenticated | postgres + storage | TRIGGER | postgres | postgres + storage | TRIGGER | service_role | postgres + storage | TRUNCATE | anon | postgres + storage | TRUNCATE | authenticated | postgres + storage | TRUNCATE | postgres | postgres + storage | TRUNCATE | service_role | postgres + storage | UPDATE | anon | postgres + storage | UPDATE | anon | postgres + storage | UPDATE | authenticated | postgres + storage | UPDATE | authenticated | postgres + storage | UPDATE | postgres | postgres + storage | UPDATE | postgres | postgres + storage | UPDATE | service_role | postgres + storage | UPDATE | service_role | postgres + storage | USAGE | anon | supabase_admin + storage | USAGE | anon | postgres + storage | USAGE | authenticated | supabase_admin + storage | USAGE | authenticated | postgres + storage | USAGE | dashboard_user | supabase_admin + storage | USAGE | postgres | supabase_admin + storage | USAGE | postgres | postgres + storage | USAGE | service_role | supabase_admin + storage | USAGE | service_role | postgres + storage | USAGE | supabase_admin | supabase_admin + storage | USAGE | supabase_storage_admin | supabase_admin + topology | CREATE | supabase_admin | supabase_admin + topology | USAGE | supabase_admin | supabase_admin + vault | CREATE | supabase_admin | supabase_admin + vault | USAGE | postgres | supabase_admin + vault | USAGE | service_role | supabase_admin + vault | USAGE | supabase_admin | supabase_admin +(389 rows) + From d8733a3e94889ce598123e70dc643b2b1c5c0368 Mon Sep 17 00:00:00 2001 From: Paul Cioanca Date: Thu, 5 Jun 2025 20:32:47 +0300 Subject: [PATCH 5/9] chore: update snapshots; multiversion boogaloo --- nix/tests/expected/roles.out | 37 ------------------------------- nix/tests/expected/z_15_roles.out | 37 +++++++++++++++++++++++++++++++ nix/tests/expected/z_17_roles.out | 37 +++++++++++++++++++++++++++++++ nix/tests/sql/roles.sql | 16 ------------- nix/tests/sql/z_15.roles.sql | 15 +++++++++++++ nix/tests/sql/z_17_roles.sql | 16 +++++++++++++ 6 files changed, 105 insertions(+), 53 deletions(-) create mode 100644 nix/tests/expected/z_15_roles.out create mode 100644 nix/tests/sql/z_15.roles.sql diff --git a/nix/tests/expected/roles.out b/nix/tests/expected/roles.out index 2d2d5060e..aef247b35 100644 --- a/nix/tests/expected/roles.out +++ b/nix/tests/expected/roles.out @@ -91,43 +91,6 @@ order by rolname; supabase_storage_admin | {search_path=storage,log_statement=none} (29 rows) --- all role memberships -select - r.rolname as member, - g.rolname as "member_of (can become)", - m.admin_option -from - pg_roles r -left join - pg_auth_members m on r.oid = m.member -left join - pg_roles g on m.roleid = g.oid -where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -order by - r.rolname, g.rolname; - member | member_of (can become) | admin_option --------------------------+------------------------+-------------- - authenticator | anon | f - authenticator | authenticated | f - authenticator | service_role | f - pg_monitor | pg_read_all_settings | f - pg_monitor | pg_read_all_stats | f - pg_monitor | pg_stat_scan_tables | f - pgsodium_keyholder | pgsodium_keyiduser | f - pgsodium_keymaker | pgsodium_keyholder | f - pgsodium_keymaker | pgsodium_keyiduser | f - postgres | anon | f - postgres | authenticated | f - postgres | pg_monitor | f - postgres | pg_read_all_data | f - postgres | pg_signal_backend | f - postgres | pgtle_admin | f - postgres | service_role | f - supabase_read_only_user | pg_read_all_data | f - supabase_storage_admin | authenticator | f -(18 rows) - -- Check all privileges of the roles on the schemas select schema_name, privilege_type, grantee, default_for from ( diff --git a/nix/tests/expected/z_15_roles.out b/nix/tests/expected/z_15_roles.out new file mode 100644 index 000000000..ab107f415 --- /dev/null +++ b/nix/tests/expected/z_15_roles.out @@ -0,0 +1,37 @@ + +-- all role memberships +select + r.rolname as member, + g.rolname as "member_of (can become)", + m.admin_option +from + pg_roles r +left join + pg_auth_members m on r.oid = m.member +left join + pg_roles g on m.roleid = g.oid +where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +order by + r.rolname, g.rolname; + member | member_of (can become) | admin_option +-------------------------+------------------------+-------------- + authenticator | anon | f + authenticator | authenticated | f + authenticator | service_role | f + pg_monitor | pg_read_all_settings | f + pg_monitor | pg_read_all_stats | f + pg_monitor | pg_stat_scan_tables | f + pgsodium_keyholder | pgsodium_keyiduser | f + pgsodium_keymaker | pgsodium_keyholder | f + pgsodium_keymaker | pgsodium_keyiduser | f + postgres | anon | f + postgres | authenticated | f + postgres | pg_monitor | f + postgres | pg_read_all_data | f + postgres | pg_signal_backend | f + postgres | pgtle_admin | f + postgres | service_role | f + supabase_read_only_user | pg_read_all_data | f + supabase_storage_admin | authenticator | f +(18 rows) \ No newline at end of file diff --git a/nix/tests/expected/z_17_roles.out b/nix/tests/expected/z_17_roles.out index a90a6677d..0bf18f918 100644 --- a/nix/tests/expected/z_17_roles.out +++ b/nix/tests/expected/z_17_roles.out @@ -109,3 +109,40 @@ order by schema_order, schema_name, privilege_type, grantee, default_for; storage | MAINTAIN | service_role | postgres (28 rows) +-- version specific role memberships +select + r.rolname as member, + g.rolname as "member_of (can become)", + m.admin_option +from + pg_roles r +left join + pg_auth_members m on r.oid = m.member +left join + pg_roles g on m.roleid = g.oid +where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +order by + r.rolname, g.rolname; + member | member_of (can become) | admin_option +-------------------------+------------------------+-------------- + authenticator | anon | f + authenticator | authenticated | f + authenticator | service_role | f + pg_monitor | pg_read_all_settings | f + pg_monitor | pg_read_all_stats | f + pg_monitor | pg_stat_scan_tables | f + pgsodium_keyholder | pgsodium_keyiduser | f + pgsodium_keymaker | pgsodium_keyholder | f + pgsodium_keymaker | pgsodium_keyiduser | f + postgres | anon | t + postgres | authenticated | t + postgres | pg_monitor | f + postgres | pg_read_all_data | f + postgres | pg_signal_backend | f + postgres | pgtle_admin | f + postgres | service_role | t + supabase_read_only_user | pg_read_all_data | f + supabase_storage_admin | authenticator | f +(18 rows) + diff --git a/nix/tests/sql/roles.sql b/nix/tests/sql/roles.sql index 7a582a366..34fd5db7e 100644 --- a/nix/tests/sql/roles.sql +++ b/nix/tests/sql/roles.sql @@ -28,22 +28,6 @@ from pg_roles r where rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') order by rolname; --- all role memberships -select - r.rolname as member, - g.rolname as "member_of (can become)", - m.admin_option -from - pg_roles r -left join - pg_auth_members m on r.oid = m.member -left join - pg_roles g on m.roleid = g.oid -where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -order by - r.rolname, g.rolname; - -- Check all privileges of the roles on the schemas select schema_name, privilege_type, grantee, default_for from ( diff --git a/nix/tests/sql/z_15.roles.sql b/nix/tests/sql/z_15.roles.sql new file mode 100644 index 000000000..721709ec0 --- /dev/null +++ b/nix/tests/sql/z_15.roles.sql @@ -0,0 +1,15 @@ +-- all role memberships +select + r.rolname as member, + g.rolname as "member_of (can become)", + m.admin_option +from + pg_roles r +left join + pg_auth_members m on r.oid = m.member +left join + pg_roles g on m.roleid = g.oid +where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +order by + r.rolname, g.rolname; diff --git a/nix/tests/sql/z_17_roles.sql b/nix/tests/sql/z_17_roles.sql index ef17fcb77..b95abc9be 100644 --- a/nix/tests/sql/z_17_roles.sql +++ b/nix/tests/sql/z_17_roles.sql @@ -58,3 +58,19 @@ from ( a.privilege_type = 'MAINTAIN' ) sub order by schema_order, schema_name, privilege_type, grantee, default_for; + +-- version specific role memberships +select + r.rolname as member, + g.rolname as "member_of (can become)", + m.admin_option +from + pg_roles r +left join + pg_auth_members m on r.oid = m.member +left join + pg_roles g on m.roleid = g.oid +where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') +order by + r.rolname, g.rolname; From 2e54f132388ce6616331d983c01150d1fef6d822 Mon Sep 17 00:00:00 2001 From: Paul Cioanca Date: Thu, 5 Jun 2025 20:34:40 +0300 Subject: [PATCH 6/9] chore: remove additional roles file --- nix/tests/expected/roles_1.out | 560 --------------------------------- 1 file changed, 560 deletions(-) delete mode 100644 nix/tests/expected/roles_1.out diff --git a/nix/tests/expected/roles_1.out b/nix/tests/expected/roles_1.out deleted file mode 100644 index 23be83bf6..000000000 --- a/nix/tests/expected/roles_1.out +++ /dev/null @@ -1,560 +0,0 @@ --- Some predefined roles don't exist in earlier versions of Postgres, so we --- exclude them in this test file. They're tested in version-specific test files --- (z__roles.sql). --- --- Currently those roles are: --- pg_create_subscription, pg_maintain, pg_use_reserved_connections --- all roles and attributes -select - rolname, - rolcreaterole , - rolcanlogin , - rolsuper , - rolinherit , - rolcreatedb , - rolreplication , - rolconnlimit , - rolbypassrls , - rolvaliduntil -from pg_roles r -where rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -order by rolname; - rolname | rolcreaterole | rolcanlogin | rolsuper | rolinherit | rolcreatedb | rolreplication | rolconnlimit | rolbypassrls | rolvaliduntil -----------------------------+---------------+-------------+----------+------------+-------------+----------------+--------------+--------------+--------------- - anon | f | f | f | t | f | f | -1 | f | - authenticated | f | f | f | t | f | f | -1 | f | - authenticator | f | t | f | f | f | f | -1 | f | - dashboard_user | t | f | f | t | t | t | -1 | f | - pg_checkpoint | f | f | f | t | f | f | -1 | f | - pg_database_owner | f | f | f | t | f | f | -1 | f | - pg_execute_server_program | f | f | f | t | f | f | -1 | f | - pg_monitor | f | f | f | t | f | f | -1 | f | - pg_read_all_data | f | f | f | t | f | f | -1 | f | - pg_read_all_settings | f | f | f | t | f | f | -1 | f | - pg_read_all_stats | f | f | f | t | f | f | -1 | f | - pg_read_server_files | f | f | f | t | f | f | -1 | f | - pg_signal_backend | f | f | f | t | f | f | -1 | f | - pg_stat_scan_tables | f | f | f | t | f | f | -1 | f | - pg_write_all_data | f | f | f | t | f | f | -1 | f | - pg_write_server_files | f | f | f | t | f | f | -1 | f | - pgbouncer | f | t | f | t | f | f | -1 | f | - pgsodium_keyholder | f | f | f | t | f | f | -1 | f | - pgsodium_keyiduser | f | f | f | t | f | f | -1 | f | - pgsodium_keymaker | f | f | f | t | f | f | -1 | f | - pgtle_admin | f | f | f | t | f | f | -1 | f | - postgres | t | t | f | t | t | t | -1 | t | - service_role | f | f | f | t | f | f | -1 | t | - supabase_admin | t | t | t | t | t | t | -1 | t | - supabase_auth_admin | t | t | f | f | f | f | -1 | f | - supabase_functions_admin | t | t | f | f | f | f | -1 | f | - supabase_read_only_user | f | t | f | t | f | f | -1 | t | - supabase_replication_admin | f | t | f | t | f | t | -1 | f | - supabase_storage_admin | t | t | f | f | f | f | -1 | f | -(29 rows) - -select - rolname, - rolconfig -from pg_roles r -where rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -order by rolname; - rolname | rolconfig -----------------------------+--------------------------------------------------------------------------------- - anon | {statement_timeout=3s} - authenticated | {statement_timeout=8s} - authenticator | {session_preload_libraries=safeupdate,statement_timeout=8s,lock_timeout=8s} - dashboard_user | - pg_checkpoint | - pg_database_owner | - pg_execute_server_program | - pg_monitor | - pg_read_all_data | - pg_read_all_settings | - pg_read_all_stats | - pg_read_server_files | - pg_signal_backend | - pg_stat_scan_tables | - pg_write_all_data | - pg_write_server_files | - pgbouncer | - pgsodium_keyholder | - pgsodium_keyiduser | - pgsodium_keymaker | - pgtle_admin | - postgres | {"search_path=\"\\$user\", public, extensions"} - service_role | - supabase_admin | {"search_path=\"$user\", public, auth, extensions",log_statement=none} - supabase_auth_admin | {search_path=auth,idle_in_transaction_session_timeout=60000,log_statement=none} - supabase_functions_admin | - supabase_read_only_user | - supabase_replication_admin | - supabase_storage_admin | {search_path=storage,log_statement=none} -(29 rows) - --- all role memberships -select - r.rolname as member, - g.rolname as "member_of (can become)", - m.admin_option -from - pg_roles r -left join - pg_auth_members m on r.oid = m.member -left join - pg_roles g on m.roleid = g.oid -where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -order by - r.rolname, g.rolname; - member | member_of (can become) | admin_option --------------------------+------------------------+-------------- - authenticator | anon | f - authenticator | authenticated | f - authenticator | service_role | f - pg_monitor | pg_read_all_settings | f - pg_monitor | pg_read_all_stats | f - pg_monitor | pg_stat_scan_tables | f - pgsodium_keyholder | pgsodium_keyiduser | f - pgsodium_keymaker | pgsodium_keyholder | f - pgsodium_keymaker | pgsodium_keyiduser | f - postgres | anon | t - postgres | authenticated | t - postgres | pg_monitor | f - postgres | pg_read_all_data | f - postgres | pg_signal_backend | f - postgres | pgtle_admin | f - postgres | service_role | t - supabase_read_only_user | pg_read_all_data | f - supabase_storage_admin | authenticator | f -(18 rows) - --- Check all privileges of the roles on the schemas -select schema_name, privilege_type, grantee, default_for -from ( - -- ALTER DEFAULT privileges on schemas - select - n.nspname as schema_name, - a.privilege_type, - r.rolname as grantee, - d.defaclrole::regrole as default_for, - case when n.nspname = 'public' then 0 else 1 end as schema_order - from - pg_default_acl d - join - pg_namespace n on d.defaclnamespace = n.oid - cross join lateral aclexplode(d.defaclacl) as a - join - pg_roles r on a.grantee = r.oid - where - -- PG17+, handled in version-specific test files - a.privilege_type != 'MAINTAIN' - union all - -- explicit grant usage and create on the schemas - select - n.nspname as schema_name, - a.privilege_type, - r.rolname as grantee, - n.nspowner::regrole as default_for, - case when n.nspname = 'public' then 0 else 1 end as schema_order - from - pg_namespace n - cross join lateral aclexplode(n.nspacl) as a - join - pg_roles r on a.grantee = r.oid - where - a.privilege_type in ('CREATE', 'USAGE') -) sub -order by schema_order, schema_name, privilege_type, grantee, default_for; - schema_name | privilege_type | grantee | default_for ---------------------+----------------+--------------------------+--------------------- - public | CREATE | pg_database_owner | pg_database_owner - public | DELETE | anon | supabase_admin - public | DELETE | anon | postgres - public | DELETE | authenticated | supabase_admin - public | DELETE | authenticated | postgres - public | DELETE | postgres | supabase_admin - public | DELETE | postgres | postgres - public | DELETE | service_role | supabase_admin - public | DELETE | service_role | postgres - public | EXECUTE | anon | supabase_admin - public | EXECUTE | anon | postgres - public | EXECUTE | authenticated | supabase_admin - public | EXECUTE | authenticated | postgres - public | EXECUTE | postgres | supabase_admin - public | EXECUTE | postgres | postgres - public | EXECUTE | service_role | supabase_admin - public | EXECUTE | service_role | postgres - public | INSERT | anon | supabase_admin - public | INSERT | anon | postgres - public | INSERT | authenticated | supabase_admin - public | INSERT | authenticated | postgres - public | INSERT | postgres | supabase_admin - public | INSERT | postgres | postgres - public | INSERT | service_role | supabase_admin - public | INSERT | service_role | postgres - public | REFERENCES | anon | supabase_admin - public | REFERENCES | anon | postgres - public | REFERENCES | authenticated | supabase_admin - public | REFERENCES | authenticated | postgres - public | REFERENCES | postgres | supabase_admin - public | REFERENCES | postgres | postgres - public | REFERENCES | service_role | supabase_admin - public | REFERENCES | service_role | postgres - public | SELECT | anon | supabase_admin - public | SELECT | anon | supabase_admin - public | SELECT | anon | postgres - public | SELECT | anon | postgres - public | SELECT | authenticated | supabase_admin - public | SELECT | authenticated | supabase_admin - public | SELECT | authenticated | postgres - public | SELECT | authenticated | postgres - public | SELECT | postgres | supabase_admin - public | SELECT | postgres | supabase_admin - public | SELECT | postgres | postgres - public | SELECT | postgres | postgres - public | SELECT | service_role | supabase_admin - public | SELECT | service_role | supabase_admin - public | SELECT | service_role | postgres - public | SELECT | service_role | postgres - public | TRIGGER | anon | supabase_admin - public | TRIGGER | anon | postgres - public | TRIGGER | authenticated | supabase_admin - public | TRIGGER | authenticated | postgres - public | TRIGGER | postgres | supabase_admin - public | TRIGGER | postgres | postgres - public | TRIGGER | service_role | supabase_admin - public | TRIGGER | service_role | postgres - public | TRUNCATE | anon | supabase_admin - public | TRUNCATE | anon | postgres - public | TRUNCATE | authenticated | supabase_admin - public | TRUNCATE | authenticated | postgres - public | TRUNCATE | postgres | supabase_admin - public | TRUNCATE | postgres | postgres - public | TRUNCATE | service_role | supabase_admin - public | TRUNCATE | service_role | postgres - public | UPDATE | anon | supabase_admin - public | UPDATE | anon | supabase_admin - public | UPDATE | anon | postgres - public | UPDATE | anon | postgres - public | UPDATE | authenticated | supabase_admin - public | UPDATE | authenticated | supabase_admin - public | UPDATE | authenticated | postgres - public | UPDATE | authenticated | postgres - public | UPDATE | postgres | supabase_admin - public | UPDATE | postgres | supabase_admin - public | UPDATE | postgres | postgres - public | UPDATE | postgres | postgres - public | UPDATE | service_role | supabase_admin - public | UPDATE | service_role | supabase_admin - public | UPDATE | service_role | postgres - public | UPDATE | service_role | postgres - public | USAGE | anon | supabase_admin - public | USAGE | anon | pg_database_owner - public | USAGE | anon | postgres - public | USAGE | authenticated | supabase_admin - public | USAGE | authenticated | pg_database_owner - public | USAGE | authenticated | postgres - public | USAGE | pg_database_owner | pg_database_owner - public | USAGE | postgres | supabase_admin - public | USAGE | postgres | pg_database_owner - public | USAGE | postgres | postgres - public | USAGE | service_role | supabase_admin - public | USAGE | service_role | pg_database_owner - public | USAGE | service_role | postgres - auth | CREATE | dashboard_user | supabase_admin - auth | CREATE | supabase_admin | supabase_admin - auth | CREATE | supabase_auth_admin | supabase_admin - auth | DELETE | dashboard_user | supabase_auth_admin - auth | DELETE | postgres | supabase_auth_admin - auth | EXECUTE | dashboard_user | supabase_auth_admin - auth | EXECUTE | postgres | supabase_auth_admin - auth | INSERT | dashboard_user | supabase_auth_admin - auth | INSERT | postgres | supabase_auth_admin - auth | REFERENCES | dashboard_user | supabase_auth_admin - auth | REFERENCES | postgres | supabase_auth_admin - auth | SELECT | dashboard_user | supabase_auth_admin - auth | SELECT | dashboard_user | supabase_auth_admin - auth | SELECT | postgres | supabase_auth_admin - auth | SELECT | postgres | supabase_auth_admin - auth | TRIGGER | dashboard_user | supabase_auth_admin - auth | TRIGGER | postgres | supabase_auth_admin - auth | TRUNCATE | dashboard_user | supabase_auth_admin - auth | TRUNCATE | postgres | supabase_auth_admin - auth | UPDATE | dashboard_user | supabase_auth_admin - auth | UPDATE | dashboard_user | supabase_auth_admin - auth | UPDATE | postgres | supabase_auth_admin - auth | UPDATE | postgres | supabase_auth_admin - auth | USAGE | anon | supabase_admin - auth | USAGE | authenticated | supabase_admin - auth | USAGE | dashboard_user | supabase_admin - auth | USAGE | dashboard_user | supabase_auth_admin - auth | USAGE | postgres | supabase_admin - auth | USAGE | postgres | supabase_auth_admin - auth | USAGE | service_role | supabase_admin - auth | USAGE | supabase_admin | supabase_admin - auth | USAGE | supabase_auth_admin | supabase_admin - extensions | CREATE | dashboard_user | postgres - extensions | CREATE | postgres | postgres - extensions | DELETE | postgres | supabase_admin - extensions | EXECUTE | postgres | supabase_admin - extensions | INSERT | postgres | supabase_admin - extensions | REFERENCES | postgres | supabase_admin - extensions | SELECT | postgres | supabase_admin - extensions | SELECT | postgres | supabase_admin - extensions | TRIGGER | postgres | supabase_admin - extensions | TRUNCATE | postgres | supabase_admin - extensions | UPDATE | postgres | supabase_admin - extensions | UPDATE | postgres | supabase_admin - extensions | USAGE | anon | postgres - extensions | USAGE | authenticated | postgres - extensions | USAGE | dashboard_user | postgres - extensions | USAGE | postgres | supabase_admin - extensions | USAGE | postgres | postgres - extensions | USAGE | service_role | postgres - graphql | CREATE | supabase_admin | supabase_admin - graphql | DELETE | anon | supabase_admin - graphql | DELETE | authenticated | supabase_admin - graphql | DELETE | postgres | supabase_admin - graphql | DELETE | service_role | supabase_admin - graphql | EXECUTE | anon | supabase_admin - graphql | EXECUTE | authenticated | supabase_admin - graphql | EXECUTE | postgres | supabase_admin - graphql | EXECUTE | service_role | supabase_admin - graphql | INSERT | anon | supabase_admin - graphql | INSERT | authenticated | supabase_admin - graphql | INSERT | postgres | supabase_admin - graphql | INSERT | service_role | supabase_admin - graphql | REFERENCES | anon | supabase_admin - graphql | REFERENCES | authenticated | supabase_admin - graphql | REFERENCES | postgres | supabase_admin - graphql | REFERENCES | service_role | supabase_admin - graphql | SELECT | anon | supabase_admin - graphql | SELECT | anon | supabase_admin - graphql | SELECT | authenticated | supabase_admin - graphql | SELECT | authenticated | supabase_admin - graphql | SELECT | postgres | supabase_admin - graphql | SELECT | postgres | supabase_admin - graphql | SELECT | service_role | supabase_admin - graphql | SELECT | service_role | supabase_admin - graphql | TRIGGER | anon | supabase_admin - graphql | TRIGGER | authenticated | supabase_admin - graphql | TRIGGER | postgres | supabase_admin - graphql | TRIGGER | service_role | supabase_admin - graphql | TRUNCATE | anon | supabase_admin - graphql | TRUNCATE | authenticated | supabase_admin - graphql | TRUNCATE | postgres | supabase_admin - graphql | TRUNCATE | service_role | supabase_admin - graphql | UPDATE | anon | supabase_admin - graphql | UPDATE | anon | supabase_admin - graphql | UPDATE | authenticated | supabase_admin - graphql | UPDATE | authenticated | supabase_admin - graphql | UPDATE | postgres | supabase_admin - graphql | UPDATE | postgres | supabase_admin - graphql | UPDATE | service_role | supabase_admin - graphql | UPDATE | service_role | supabase_admin - graphql | USAGE | anon | supabase_admin - graphql | USAGE | anon | supabase_admin - graphql | USAGE | authenticated | supabase_admin - graphql | USAGE | authenticated | supabase_admin - graphql | USAGE | postgres | supabase_admin - graphql | USAGE | postgres | supabase_admin - graphql | USAGE | service_role | supabase_admin - graphql | USAGE | service_role | supabase_admin - graphql | USAGE | supabase_admin | supabase_admin - graphql_public | CREATE | supabase_admin | supabase_admin - graphql_public | DELETE | anon | supabase_admin - graphql_public | DELETE | authenticated | supabase_admin - graphql_public | DELETE | postgres | supabase_admin - graphql_public | DELETE | service_role | supabase_admin - graphql_public | EXECUTE | anon | supabase_admin - graphql_public | EXECUTE | authenticated | supabase_admin - graphql_public | EXECUTE | postgres | supabase_admin - graphql_public | EXECUTE | service_role | supabase_admin - graphql_public | INSERT | anon | supabase_admin - graphql_public | INSERT | authenticated | supabase_admin - graphql_public | INSERT | postgres | supabase_admin - graphql_public | INSERT | service_role | supabase_admin - graphql_public | REFERENCES | anon | supabase_admin - graphql_public | REFERENCES | authenticated | supabase_admin - graphql_public | REFERENCES | postgres | supabase_admin - graphql_public | REFERENCES | service_role | supabase_admin - graphql_public | SELECT | anon | supabase_admin - graphql_public | SELECT | anon | supabase_admin - graphql_public | SELECT | authenticated | supabase_admin - graphql_public | SELECT | authenticated | supabase_admin - graphql_public | SELECT | postgres | supabase_admin - graphql_public | SELECT | postgres | supabase_admin - graphql_public | SELECT | service_role | supabase_admin - graphql_public | SELECT | service_role | supabase_admin - graphql_public | TRIGGER | anon | supabase_admin - graphql_public | TRIGGER | authenticated | supabase_admin - graphql_public | TRIGGER | postgres | supabase_admin - graphql_public | TRIGGER | service_role | supabase_admin - graphql_public | TRUNCATE | anon | supabase_admin - graphql_public | TRUNCATE | authenticated | supabase_admin - graphql_public | TRUNCATE | postgres | supabase_admin - graphql_public | TRUNCATE | service_role | supabase_admin - graphql_public | UPDATE | anon | supabase_admin - graphql_public | UPDATE | anon | supabase_admin - graphql_public | UPDATE | authenticated | supabase_admin - graphql_public | UPDATE | authenticated | supabase_admin - graphql_public | UPDATE | postgres | supabase_admin - graphql_public | UPDATE | postgres | supabase_admin - graphql_public | UPDATE | service_role | supabase_admin - graphql_public | UPDATE | service_role | supabase_admin - graphql_public | USAGE | anon | supabase_admin - graphql_public | USAGE | anon | supabase_admin - graphql_public | USAGE | authenticated | supabase_admin - graphql_public | USAGE | authenticated | supabase_admin - graphql_public | USAGE | postgres | supabase_admin - graphql_public | USAGE | postgres | supabase_admin - graphql_public | USAGE | service_role | supabase_admin - graphql_public | USAGE | service_role | supabase_admin - graphql_public | USAGE | supabase_admin | supabase_admin - information_schema | CREATE | supabase_admin | supabase_admin - information_schema | USAGE | supabase_admin | supabase_admin - net | CREATE | supabase_admin | supabase_admin - net | USAGE | anon | supabase_admin - net | USAGE | authenticated | supabase_admin - net | USAGE | postgres | supabase_admin - net | USAGE | service_role | supabase_admin - net | USAGE | supabase_admin | supabase_admin - net | USAGE | supabase_functions_admin | supabase_admin - pg_catalog | CREATE | supabase_admin | supabase_admin - pg_catalog | USAGE | supabase_admin | supabase_admin - pgmq | CREATE | supabase_admin | supabase_admin - pgmq | SELECT | pg_monitor | supabase_admin - pgmq | SELECT | pg_monitor | supabase_admin - pgmq | USAGE | pg_monitor | supabase_admin - pgmq | USAGE | supabase_admin | supabase_admin - pgsodium | CREATE | supabase_admin | supabase_admin - pgsodium | DELETE | pgsodium_keyholder | supabase_admin - pgsodium | INSERT | pgsodium_keyholder | supabase_admin - pgsodium | REFERENCES | pgsodium_keyholder | supabase_admin - pgsodium | SELECT | pgsodium_keyholder | supabase_admin - pgsodium | SELECT | pgsodium_keyholder | supabase_admin - pgsodium | TRIGGER | pgsodium_keyholder | supabase_admin - pgsodium | TRUNCATE | pgsodium_keyholder | supabase_admin - pgsodium | UPDATE | pgsodium_keyholder | supabase_admin - pgsodium | UPDATE | pgsodium_keyholder | supabase_admin - pgsodium | USAGE | pgsodium_keyholder | supabase_admin - pgsodium | USAGE | supabase_admin | supabase_admin - pgsodium_masks | CREATE | supabase_admin | supabase_admin - pgsodium_masks | DELETE | pgsodium_keyiduser | supabase_admin - pgsodium_masks | EXECUTE | pgsodium_keyiduser | supabase_admin - pgsodium_masks | INSERT | pgsodium_keyiduser | supabase_admin - pgsodium_masks | REFERENCES | pgsodium_keyiduser | supabase_admin - pgsodium_masks | SELECT | pgsodium_keyiduser | supabase_admin - pgsodium_masks | SELECT | pgsodium_keyiduser | supabase_admin - pgsodium_masks | TRIGGER | pgsodium_keyiduser | supabase_admin - pgsodium_masks | TRUNCATE | pgsodium_keyiduser | supabase_admin - pgsodium_masks | UPDATE | pgsodium_keyiduser | supabase_admin - pgsodium_masks | UPDATE | pgsodium_keyiduser | supabase_admin - pgsodium_masks | USAGE | pgsodium_keyiduser | supabase_admin - pgsodium_masks | USAGE | pgsodium_keyiduser | supabase_admin - pgsodium_masks | USAGE | supabase_admin | supabase_admin - pgtle | CREATE | pgtle_admin | supabase_admin - pgtle | CREATE | supabase_admin | supabase_admin - pgtle | USAGE | pgtle_admin | supabase_admin - pgtle | USAGE | supabase_admin | supabase_admin - realtime | CREATE | supabase_admin | supabase_admin - realtime | DELETE | dashboard_user | supabase_admin - realtime | DELETE | postgres | supabase_admin - realtime | EXECUTE | dashboard_user | supabase_admin - realtime | EXECUTE | postgres | supabase_admin - realtime | INSERT | dashboard_user | supabase_admin - realtime | INSERT | postgres | supabase_admin - realtime | REFERENCES | dashboard_user | supabase_admin - realtime | REFERENCES | postgres | supabase_admin - realtime | SELECT | dashboard_user | supabase_admin - realtime | SELECT | dashboard_user | supabase_admin - realtime | SELECT | postgres | supabase_admin - realtime | SELECT | postgres | supabase_admin - realtime | TRIGGER | dashboard_user | supabase_admin - realtime | TRIGGER | postgres | supabase_admin - realtime | TRUNCATE | dashboard_user | supabase_admin - realtime | TRUNCATE | postgres | supabase_admin - realtime | UPDATE | dashboard_user | supabase_admin - realtime | UPDATE | dashboard_user | supabase_admin - realtime | UPDATE | postgres | supabase_admin - realtime | UPDATE | postgres | supabase_admin - realtime | USAGE | dashboard_user | supabase_admin - realtime | USAGE | postgres | supabase_admin - realtime | USAGE | postgres | supabase_admin - realtime | USAGE | supabase_admin | supabase_admin - repack | CREATE | postgres | supabase_admin - repack | CREATE | supabase_admin | supabase_admin - repack | DELETE | postgres | supabase_admin - repack | INSERT | postgres | supabase_admin - repack | REFERENCES | postgres | supabase_admin - repack | SELECT | postgres | supabase_admin - repack | SELECT | postgres | supabase_admin - repack | TRIGGER | postgres | supabase_admin - repack | TRUNCATE | postgres | supabase_admin - repack | UPDATE | postgres | supabase_admin - repack | UPDATE | postgres | supabase_admin - repack | USAGE | postgres | supabase_admin - repack | USAGE | postgres | supabase_admin - repack | USAGE | supabase_admin | supabase_admin - storage | CREATE | dashboard_user | supabase_admin - storage | CREATE | supabase_admin | supabase_admin - storage | CREATE | supabase_storage_admin | supabase_admin - storage | DELETE | anon | postgres - storage | DELETE | authenticated | postgres - storage | DELETE | postgres | postgres - storage | DELETE | service_role | postgres - storage | EXECUTE | anon | postgres - storage | EXECUTE | authenticated | postgres - storage | EXECUTE | postgres | postgres - storage | EXECUTE | service_role | postgres - storage | INSERT | anon | postgres - storage | INSERT | authenticated | postgres - storage | INSERT | postgres | postgres - storage | INSERT | service_role | postgres - storage | REFERENCES | anon | postgres - storage | REFERENCES | authenticated | postgres - storage | REFERENCES | postgres | postgres - storage | REFERENCES | service_role | postgres - storage | SELECT | anon | postgres - storage | SELECT | anon | postgres - storage | SELECT | authenticated | postgres - storage | SELECT | authenticated | postgres - storage | SELECT | postgres | postgres - storage | SELECT | postgres | postgres - storage | SELECT | service_role | postgres - storage | SELECT | service_role | postgres - storage | TRIGGER | anon | postgres - storage | TRIGGER | authenticated | postgres - storage | TRIGGER | postgres | postgres - storage | TRIGGER | service_role | postgres - storage | TRUNCATE | anon | postgres - storage | TRUNCATE | authenticated | postgres - storage | TRUNCATE | postgres | postgres - storage | TRUNCATE | service_role | postgres - storage | UPDATE | anon | postgres - storage | UPDATE | anon | postgres - storage | UPDATE | authenticated | postgres - storage | UPDATE | authenticated | postgres - storage | UPDATE | postgres | postgres - storage | UPDATE | postgres | postgres - storage | UPDATE | service_role | postgres - storage | UPDATE | service_role | postgres - storage | USAGE | anon | supabase_admin - storage | USAGE | anon | postgres - storage | USAGE | authenticated | supabase_admin - storage | USAGE | authenticated | postgres - storage | USAGE | dashboard_user | supabase_admin - storage | USAGE | postgres | supabase_admin - storage | USAGE | postgres | postgres - storage | USAGE | service_role | supabase_admin - storage | USAGE | service_role | postgres - storage | USAGE | supabase_admin | supabase_admin - storage | USAGE | supabase_storage_admin | supabase_admin - topology | CREATE | supabase_admin | supabase_admin - topology | USAGE | supabase_admin | supabase_admin - vault | CREATE | supabase_admin | supabase_admin - vault | USAGE | postgres | supabase_admin - vault | USAGE | service_role | supabase_admin - vault | USAGE | supabase_admin | supabase_admin -(389 rows) - From 2ce63b08347a879fbd1ad1bf60c0718e45c3abd2 Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Thu, 5 Jun 2025 19:38:25 +0200 Subject: [PATCH 7/9] fix: add more roles --- ...53_grant_with_admin_to_postgres_16_and_above.sql | 2 +- nix/tests/sql/z_15_roles.sql | 13 +++++++++++++ nix/tests/sql/z_17_roles.sql | 2 -- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 nix/tests/sql/z_15_roles.sql diff --git a/migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql b/migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql index 38bd9c87e..5f2cd574a 100644 --- a/migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql +++ b/migrations/db/migrations/20250605172253_grant_with_admin_to_postgres_16_and_above.sql @@ -6,7 +6,7 @@ BEGIN SELECT current_setting('server_version_num')::INT / 10000 INTO major_version; IF major_version >= 16 THEN - GRANT anon, authenticated, service_role TO postgres WITH ADMIN OPTION; + GRANT anon, authenticated, service_role, authenticator, pg_monitor, pg_read_all_data, pg_signal_backend TO postgres WITH ADMIN OPTION; END IF; END $$; diff --git a/nix/tests/sql/z_15_roles.sql b/nix/tests/sql/z_15_roles.sql new file mode 100644 index 000000000..a1560bce5 --- /dev/null +++ b/nix/tests/sql/z_15_roles.sql @@ -0,0 +1,13 @@ +-- version-specific role memberships +select + r.rolname as member, + g.rolname as "member_of (can become)", + m.admin_option +from + pg_roles r +left join + pg_auth_members m on r.oid = m.member +left join + pg_roles g on m.roleid = g.oid +order by + r.rolname, g.rolname; diff --git a/nix/tests/sql/z_17_roles.sql b/nix/tests/sql/z_17_roles.sql index b95abc9be..70484a28e 100644 --- a/nix/tests/sql/z_17_roles.sql +++ b/nix/tests/sql/z_17_roles.sql @@ -32,8 +32,6 @@ left join pg_auth_members m on r.oid = m.member left join pg_roles g on m.roleid = g.oid -where r.rolname in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -or g.rolname in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') order by r.rolname, g.rolname; From 368bf20f8afddfa8d8bef22a5018061660d0094b Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Thu, 5 Jun 2025 19:41:58 +0200 Subject: [PATCH 8/9] fix: use inner join --- nix/tests/sql/z_15_roles.sql | 2 +- nix/tests/sql/z_17_roles.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nix/tests/sql/z_15_roles.sql b/nix/tests/sql/z_15_roles.sql index a1560bce5..423e48cca 100644 --- a/nix/tests/sql/z_15_roles.sql +++ b/nix/tests/sql/z_15_roles.sql @@ -5,7 +5,7 @@ select m.admin_option from pg_roles r -left join +join pg_auth_members m on r.oid = m.member left join pg_roles g on m.roleid = g.oid diff --git a/nix/tests/sql/z_17_roles.sql b/nix/tests/sql/z_17_roles.sql index 70484a28e..ae14f5718 100644 --- a/nix/tests/sql/z_17_roles.sql +++ b/nix/tests/sql/z_17_roles.sql @@ -28,7 +28,7 @@ select m.admin_option from pg_roles r -left join +join pg_auth_members m on r.oid = m.member left join pg_roles g on m.roleid = g.oid From 50456c374b6df011cfc75ee71094c1f3e4f926b2 Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Thu, 5 Jun 2025 19:44:38 +0200 Subject: [PATCH 9/9] test: update z_*_roles snapshots --- nix/tests/expected/z_15_roles.out | 10 +++---- nix/tests/expected/z_17_roles.out | 43 +++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/nix/tests/expected/z_15_roles.out b/nix/tests/expected/z_15_roles.out index ab107f415..42c2314e8 100644 --- a/nix/tests/expected/z_15_roles.out +++ b/nix/tests/expected/z_15_roles.out @@ -1,17 +1,14 @@ - --- all role memberships +-- version-specific role memberships select r.rolname as member, g.rolname as "member_of (can become)", m.admin_option from pg_roles r -left join +join pg_auth_members m on r.oid = m.member left join pg_roles g on m.roleid = g.oid -where r.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -and g.rolname not in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') order by r.rolname, g.rolname; member | member_of (can become) | admin_option @@ -34,4 +31,5 @@ order by postgres | service_role | f supabase_read_only_user | pg_read_all_data | f supabase_storage_admin | authenticator | f -(18 rows) \ No newline at end of file +(18 rows) + diff --git a/nix/tests/expected/z_17_roles.out b/nix/tests/expected/z_17_roles.out index 0bf18f918..40ce6007d 100644 --- a/nix/tests/expected/z_17_roles.out +++ b/nix/tests/expected/z_17_roles.out @@ -40,21 +40,35 @@ select m.admin_option from pg_roles r -left join +join pg_auth_members m on r.oid = m.member left join pg_roles g on m.roleid = g.oid -where r.rolname in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') -or g.rolname in ('pg_create_subscription', 'pg_maintain', 'pg_use_reserved_connections') order by r.rolname, g.rolname; - member | member_of (can become) | admin_option ------------------------------+------------------------+-------------- - pg_create_subscription | | - pg_maintain | | - pg_use_reserved_connections | | - postgres | pg_create_subscription | f -(4 rows) + member | member_of (can become) | admin_option +-------------------------+------------------------+-------------- + authenticator | anon | f + authenticator | authenticated | f + authenticator | service_role | f + pg_monitor | pg_read_all_settings | f + pg_monitor | pg_read_all_stats | f + pg_monitor | pg_stat_scan_tables | f + pgsodium_keyholder | pgsodium_keyiduser | f + pgsodium_keymaker | pgsodium_keyholder | f + pgsodium_keymaker | pgsodium_keyiduser | f + postgres | anon | t + postgres | authenticated | t + postgres | authenticator | t + postgres | pg_create_subscription | f + postgres | pg_monitor | t + postgres | pg_read_all_data | t + postgres | pg_signal_backend | t + postgres | pgtle_admin | f + postgres | service_role | t + supabase_read_only_user | pg_read_all_data | f + supabase_storage_admin | authenticator | f +(20 rows) -- Check version-specific privileges of the roles on the schemas select schema_name, privilege_type, grantee, default_for @@ -137,12 +151,13 @@ order by pgsodium_keymaker | pgsodium_keyiduser | f postgres | anon | t postgres | authenticated | t - postgres | pg_monitor | f - postgres | pg_read_all_data | f - postgres | pg_signal_backend | f + postgres | authenticator | t + postgres | pg_monitor | t + postgres | pg_read_all_data | t + postgres | pg_signal_backend | t postgres | pgtle_admin | f postgres | service_role | t supabase_read_only_user | pg_read_all_data | f supabase_storage_admin | authenticator | f -(18 rows) +(19 rows)