Skip to content

Commit 46d69ca

Browse files
committed
test
1 parent 5d47fdb commit 46d69ca

File tree

2 files changed

+394
-395
lines changed

2 files changed

+394
-395
lines changed

ansible/files/admin_api_scripts/pg_upgrade_scripts/common.sh

Lines changed: 390 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,393 @@ CI_start_postgres() {
8383

8484
su postgres -c "$BINDIR/pg_ctl start -o '-c config_file=/etc/postgresql/postgresql.conf' -l /tmp/postgres.log"
8585
}
86+
87+
swap_postgres_and_supabase_admin() {
88+
run_sql <<'EOSQL'
89+
begin;
90+
create role supabase_tmp superuser;
91+
set session authorization supabase_tmp;
92+
93+
do $$
94+
declare
95+
postgres_rolpassword text := (select rolpassword from pg_authid where rolname = 'postgres');
96+
supabase_admin_rolpassword text := (select rolpassword from pg_authid where rolname = 'supabase_admin');
97+
role_settings jsonb[] := (
98+
select coalesce(array_agg(jsonb_build_object('database', d.datname, 'role', a.rolname, 'configs', s.setconfig)), '{}')
99+
from pg_db_role_setting s
100+
left join pg_database d on d.oid = s.setdatabase
101+
join pg_authid a on a.oid = s.setrole
102+
where a.rolname in ('postgres', 'supabase_admin')
103+
);
104+
event_triggers jsonb[] := (select coalesce(array_agg(jsonb_build_object('name', evtname)), '{}') from pg_event_trigger where evtowner = 'postgres'::regrole);
105+
user_mappings jsonb[] := (
106+
select coalesce(array_agg(jsonb_build_object('oid', um.oid, 'role', a.rolname, 'server', s.srvname, 'options', um.umoptions)), '{}')
107+
from pg_user_mapping um
108+
join pg_authid a on a.oid = um.umuser
109+
join pg_foreign_server s on s.oid = um.umserver
110+
where a.rolname in ('postgres', 'supabase_admin')
111+
);
112+
-- Objects can have initial privileges either by having those privileges set
113+
-- when the system is initialized (by initdb) or when the object is created
114+
-- during a CREATE EXTENSION and the extension script sets initial
115+
-- privileges using the GRANT system. (https://www.postgresql.org/docs/current/catalog-pg-init-privs.html)
116+
-- We only care about swapping init_privs for extensions.
117+
init_privs jsonb[] := (
118+
select coalesce(array_agg(jsonb_build_object('objoid', objoid, 'classoid', classoid, 'initprivs', initprivs::text)), '{}')
119+
from pg_init_privs
120+
where privtype = 'e'
121+
);
122+
default_acls jsonb[] := (
123+
select coalesce(array_agg(jsonb_build_object('oid', d.oid, 'role', a.rolname, 'schema', n.nspname, 'objtype', d.defaclobjtype, 'acl', defaclacl::text)), '{}')
124+
from pg_default_acl d
125+
join pg_authid a on a.oid = d.defaclrole
126+
left join pg_namespace n on n.oid = d.defaclnamespace
127+
);
128+
schemas jsonb[] := (
129+
select coalesce(array_agg(jsonb_build_object('oid', n.oid, 'owner', a.rolname, 'acl', nspacl::text)), '{}')
130+
from pg_namespace n
131+
join pg_authid a on a.oid = n.nspowner
132+
where true
133+
and n.nspname != 'information_schema'
134+
and not starts_with(n.nspname, 'pg_')
135+
);
136+
types jsonb[] := (
137+
select coalesce(array_agg(jsonb_build_object('oid', t.oid, 'owner', a.rolname, 'acl', t.typacl::text)), '{}')
138+
from pg_type t
139+
join pg_namespace n on n.oid = t.typnamespace
140+
join pg_authid a on a.oid = t.typowner
141+
where true
142+
and n.nspname != 'information_schema'
143+
and not starts_with(n.nspname, 'pg_')
144+
and (
145+
t.typrelid = 0
146+
or (
147+
select
148+
c.relkind = 'c'
149+
from
150+
pg_class c
151+
where
152+
c.oid = t.typrelid
153+
)
154+
)
155+
and not exists (
156+
select
157+
from
158+
pg_type el
159+
where
160+
el.oid = t.typelem
161+
and el.typarray = t.oid
162+
)
163+
);
164+
functions jsonb[] := (
165+
select coalesce(array_agg(jsonb_build_object('oid', p.oid, 'owner', a.rolname, 'acl', p.proacl::text)), '{}')
166+
from pg_proc p
167+
join pg_namespace n on n.oid = p.pronamespace
168+
join pg_authid a on a.oid = p.proowner
169+
where true
170+
and n.nspname != 'information_schema'
171+
and not starts_with(n.nspname, 'pg_')
172+
);
173+
relations jsonb[] := (
174+
select coalesce(array_agg(jsonb_build_object('oid', c.oid, 'owner', a.rolname, 'acl', c.relacl::text)), '{}')
175+
from pg_class c
176+
join pg_namespace n on n.oid = c.relnamespace
177+
join pg_authid a on a.oid = c.relowner
178+
where true
179+
and n.nspname != 'information_schema'
180+
and not starts_with(n.nspname, 'pg_')
181+
and c.relkind not in ('c', 'i')
182+
);
183+
rec record;
184+
obj jsonb;
185+
begin
186+
set local search_path = '';
187+
188+
alter role postgres rename to supabase_admin_;
189+
alter role supabase_admin rename to postgres;
190+
alter role supabase_admin_ rename to supabase_admin;
191+
192+
-- role grants
193+
for rec in
194+
select * from pg_auth_members
195+
loop
196+
execute(format('revoke %I from %I;', rec.roleid::regrole, rec.member::regrole));
197+
execute(format(
198+
'grant %I to %I %s granted by %I;',
199+
case
200+
when rec.roleid = 'postgres'::regrole then 'supabase_admin'
201+
when rec.roleid = 'supabase_admin'::regrole then 'postgres'
202+
else rec.roleid::regrole
203+
end,
204+
case
205+
when rec.member = 'postgres'::regrole then 'supabase_admin'
206+
when rec.member = 'supabase_admin'::regrole then 'postgres'
207+
else rec.member::regrole
208+
end,
209+
case
210+
when rec.admin_option then 'with admin option'
211+
else ''
212+
end,
213+
case
214+
when rec.grantor = 'postgres'::regrole then 'supabase_admin'
215+
when rec.grantor = 'supabase_admin'::regrole then 'postgres'
216+
else rec.grantor::regrole
217+
end
218+
));
219+
end loop;
220+
221+
-- role passwords
222+
execute(format('alter role postgres password %L;', postgres_rolpassword));
223+
execute(format('alter role supabase_admin password %L;', supabase_admin_rolpassword));
224+
225+
-- role settings
226+
foreach obj in array role_settings
227+
loop
228+
execute(format('alter role %I %s reset all',
229+
case when obj->>'role' = 'postgres' then 'supabase_admin' else 'postgres' end,
230+
case when obj->>'database' is null then '' else format('in database %I', obj->>'database') end
231+
));
232+
end loop;
233+
foreach obj in array role_settings
234+
loop
235+
for rec in
236+
select split_part(value, '=', 1) as key, substr(value, strpos(value, '=') + 1) as value
237+
from jsonb_array_elements_text(obj->'configs')
238+
loop
239+
execute(format('alter role %I %s set %I to %s',
240+
obj->>'role',
241+
case when obj->>'database' is null then '' else format('in database %I', obj->>'database') end,
242+
rec.key,
243+
rec.value
244+
));
245+
end loop;
246+
end loop;
247+
248+
reassign owned by postgres to supabase_admin;
249+
250+
-- databases
251+
for rec in
252+
select * from pg_database where datname not in ('template0')
253+
loop
254+
execute(format('alter database %I owner to postgres;', rec.datname));
255+
end loop;
256+
257+
-- event triggers
258+
foreach obj in array event_triggers
259+
loop
260+
execute(format('alter event trigger %I owner to postgres;', obj->>'name'));
261+
end loop;
262+
263+
-- publications
264+
for rec in
265+
select * from pg_publication
266+
loop
267+
execute(format('alter publication %I owner to postgres;', rec.pubname));
268+
end loop;
269+
270+
-- FDWs
271+
for rec in
272+
select * from pg_foreign_data_wrapper
273+
loop
274+
execute(format('alter foreign data wrapper %I owner to postgres;', rec.fdwname));
275+
end loop;
276+
277+
-- foreign servers
278+
for rec in
279+
select * from pg_foreign_server
280+
loop
281+
execute(format('alter server %I owner to postgres;', rec.srvname));
282+
end loop;
283+
284+
-- user mappings
285+
foreach obj in array user_mappings
286+
loop
287+
execute(format('drop user mapping for %I server %I', case when obj->>'role' = 'postgres' then 'supabase_admin' else 'postgres' end, obj->>'server'));
288+
end loop;
289+
foreach obj in array user_mappings
290+
loop
291+
execute(format('create user mapping for %I server %I', obj->>'role', obj->>'server'));
292+
for rec in
293+
select split_part(value, '=', 1) as key, substr(value, strpos(value, '=') + 1) as value
294+
from jsonb_array_elements_text(obj->'options')
295+
loop
296+
execute(format('alter user mapping for %I server %I options (%I %L)', obj->>'role', obj->>'server', rec.key, rec.value));
297+
end loop;
298+
end loop;
299+
300+
-- init privs
301+
foreach obj in array init_privs
302+
loop
303+
-- We need to modify system catalog directly here because there's no ALTER INIT PRIVILEGES.
304+
update pg_init_privs set initprivs = (obj->>'initprivs')::aclitem[] where objoid = (obj->>'objoid')::oid and classoid = (obj->>'classoid')::oid;
305+
end loop;
306+
307+
-- default acls
308+
foreach obj in array default_acls
309+
loop
310+
for rec in
311+
select grantor, grantee, privilege_type, is_grantable
312+
from aclexplode((obj->>'acl')::aclitem[])
313+
loop
314+
if obj->>'role' in ('postgres', 'supabase_admin') or rec.grantee::regrole in ('postgres', 'supabase_admin') then
315+
execute(format('alter default privileges for role %I %s revoke %s on %s from %I'
316+
, case when obj->>'role' = 'postgres' then 'supabase_admin'
317+
when obj->>'role' = 'supabase_admin' then 'postgres'
318+
else obj->>'role'
319+
end
320+
, case when obj->>'schema' is null then ''
321+
else format('in schema %I', (obj->>'schema')::regnamespace)
322+
end
323+
, rec.privilege_type
324+
, case when obj->>'objtype' = 'r' then 'tables'
325+
when obj->>'objtype' = 'S' then 'sequences'
326+
when obj->>'objtype' = 'f' then 'functions'
327+
when obj->>'objtype' = 'T' then 'types'
328+
when obj->>'objtype' = 'n' then 'schemas'
329+
end
330+
, case when rec.grantee = 'postgres'::regrole then 'supabase_admin'
331+
when rec.grantee = 'supabase_admin'::regrole then 'postgres'
332+
else rec.grantee::regrole
333+
end
334+
));
335+
end if;
336+
end loop;
337+
end loop;
338+
339+
foreach obj in array default_acls
340+
loop
341+
for rec in
342+
select grantor, grantee, privilege_type, is_grantable
343+
from aclexplode((obj->>'acl')::aclitem[])
344+
loop
345+
if obj->>'role' in ('postgres', 'supabase_admin') or rec.grantee::regrole in ('postgres', 'supabase_admin') then
346+
execute(format('alter default privileges for role %I %s grant %s on %s to %I %s'
347+
, obj->>'role'
348+
, case when obj->>'schema' is null then ''
349+
else format('in schema %I', (obj->>'schema')::regnamespace)
350+
end
351+
, rec.privilege_type
352+
, case when obj->>'objtype' = 'r' then 'tables'
353+
when obj->>'objtype' = 'S' then 'sequences'
354+
when obj->>'objtype' = 'f' then 'functions'
355+
when obj->>'objtype' = 'T' then 'types'
356+
when obj->>'objtype' = 'n' then 'schemas'
357+
end
358+
, rec.grantee::regrole
359+
, case when rec.is_grantable then 'with grant option' else '' end
360+
));
361+
end if;
362+
end loop;
363+
end loop;
364+
365+
-- schemas
366+
foreach obj in array schemas
367+
loop
368+
if obj->>'owner' = 'postgres' then
369+
execute(format('alter schema %s owner to postgres;', (obj->>'oid')::regnamespace));
370+
end if;
371+
for rec in
372+
select grantor, grantee, privilege_type, is_grantable
373+
from aclexplode((obj->>'acl')::aclitem[])
374+
where grantee::regrole in ('postgres', 'supabase_admin')
375+
loop
376+
execute(format('revoke %s on schema %s from %I', rec.privilege_type, (obj->>'oid')::regnamespace, case when rec.grantee = 'postgres'::regrole then 'supabase_admin' else 'postgres' end));
377+
end loop;
378+
end loop;
379+
foreach obj in array schemas
380+
loop
381+
for rec in
382+
select grantor, grantee, privilege_type, is_grantable
383+
from aclexplode((obj->>'acl')::aclitem[])
384+
where grantee::regrole in ('postgres', 'supabase_admin')
385+
loop
386+
execute(format('grant %s on schema %s to %I %s', rec.privilege_type, (obj->>'oid')::regnamespace, rec.grantee::regrole, case when rec.is_grantable then 'with grant option' else '' end));
387+
end loop;
388+
end loop;
389+
390+
-- types
391+
foreach obj in array types
392+
loop
393+
if obj->>'owner' = 'postgres' then
394+
execute(format('alter type %s owner to postgres;', (obj->>'oid')::regtype));
395+
end if;
396+
for rec in
397+
select grantor, grantee, privilege_type, is_grantable
398+
from aclexplode((obj->>'acl')::aclitem[])
399+
where grantee::regrole in ('postgres', 'supabase_admin')
400+
loop
401+
execute(format('revoke %s on type %s from %I', rec.privilege_type, (obj->>'oid')::regtype, case when rec.grantee = 'postgres'::regrole then 'supabase_admin' else 'postgres' end));
402+
end loop;
403+
end loop;
404+
foreach obj in array types
405+
loop
406+
for rec in
407+
select grantor, grantee, privilege_type, is_grantable
408+
from aclexplode((obj->>'acl')::aclitem[])
409+
where grantee::regrole in ('postgres', 'supabase_admin')
410+
loop
411+
execute(format('grant %s on type %s to %I %s', rec.privilege_type, (obj->>'oid')::regtype, rec.grantee::regrole, case when rec.is_grantable then 'with grant option' else '' end));
412+
end loop;
413+
end loop;
414+
415+
-- functions
416+
foreach obj in array functions
417+
loop
418+
if obj->>'owner' = 'postgres' then
419+
execute(format('alter routine %s(%s) owner to postgres;', (obj->>'oid')::regproc, pg_get_function_identity_arguments((obj->>'oid')::regproc)));
420+
end if;
421+
for rec in
422+
select grantor, grantee, privilege_type, is_grantable
423+
from aclexplode((obj->>'acl')::aclitem[])
424+
where grantee::regrole in ('postgres', 'supabase_admin')
425+
loop
426+
execute(format('revoke %s on function %s(%s) from %I', rec.privilege_type, (obj->>'oid')::regproc, pg_get_function_identity_arguments((obj->>'oid')::regproc), case when rec.grantee = 'postgres'::regrole then 'supabase_admin' else 'postgres' end));
427+
end loop;
428+
end loop;
429+
foreach obj in array functions
430+
loop
431+
for rec in
432+
select grantor, grantee, privilege_type, is_grantable
433+
from aclexplode((obj->>'acl')::aclitem[])
434+
where grantee::regrole in ('postgres', 'supabase_admin')
435+
loop
436+
execute(format('grant %s on function %s(%s) to %I %s', rec.privilege_type, (obj->>'oid')::regproc, pg_get_function_identity_arguments((obj->>'oid')::regproc), rec.grantee::regrole, case when rec.is_grantable then 'with grant option' else '' end));
437+
end loop;
438+
end loop;
439+
440+
-- relations
441+
foreach obj in array relations
442+
loop
443+
-- obj->>'oid' (text) needs to be casted to oid first for some reason
444+
445+
if obj->>'owner' = 'postgres' then
446+
execute(format('alter table %s owner to postgres;', (obj->>'oid')::oid::regclass));
447+
end if;
448+
for rec in
449+
select grantor, grantee, privilege_type, is_grantable
450+
from aclexplode((obj->>'acl')::aclitem[])
451+
where grantee::regrole in ('postgres', 'supabase_admin')
452+
loop
453+
execute(format('revoke %s on table %s from %I', rec.privilege_type, (obj->>'oid')::oid::regclass, case when rec.grantee = 'postgres'::regrole then 'supabase_admin' else 'postgres' end));
454+
end loop;
455+
end loop;
456+
foreach obj in array relations
457+
loop
458+
-- obj->>'oid' (text) needs to be casted to oid first for some reason
459+
460+
for rec in
461+
select grantor, grantee, privilege_type, is_grantable
462+
from aclexplode((obj->>'acl')::aclitem[])
463+
where grantee::regrole in ('postgres', 'supabase_admin')
464+
loop
465+
execute(format('grant %s on table %s to %I %s', rec.privilege_type, (obj->>'oid')::oid::regclass, rec.grantee::regrole, case when rec.is_grantable then 'with grant option' else '' end));
466+
end loop;
467+
end loop;
468+
end
469+
$$;
470+
471+
set session authorization supabase_admin;
472+
drop role supabase_tmp;
473+
commit;
474+
EOSQL
475+
}

0 commit comments

Comments
 (0)