@@ -32,6 +32,45 @@ function execute_extension_upgrade_patches {
3232 fi
3333}
3434
35+ function execute_wrappers_patch {
36+ # If upgrading to pgsodium-less Vault, Wrappers need to be updated so that
37+ # foreign servers use `vault.secrets.id` instead of `vault.secrets.key_id`
38+ UPDATE_WRAPPERS_SERVER_OPTIONS_QUERY=$( cat << EOF
39+ DO \$\$
40+ DECLARE
41+ server_rec RECORD;
42+ option_rec RECORD;
43+ vault_secrets RECORD;
44+ BEGIN
45+ IF EXISTS (SELECT FROM pg_available_extension_versions WHERE name = 'wrappers' AND version = '0.4.6')
46+ AND EXISTS (SELECT FROM pg_extension WHERE extname = 'wrappers')
47+ THEN
48+ FOR server_rec IN
49+ SELECT srvname, srvoptions
50+ FROM pg_foreign_server
51+ LOOP
52+ FOR option_rec IN
53+ SELECT split_part(srvoption, '=', 1) AS option_name, split_part(srvoption, '=', 2) AS option_value
54+ FROM UNNEST(server_rec.srvoptions) AS srvoption
55+ LOOP
56+ IF EXISTS (SELECT FROM vault.secrets WHERE option_rec.option_value IN (id::text, key_id::text)) THEN
57+ EXECUTE format(
58+ 'ALTER SERVER %I OPTIONS (SET %I %L)',
59+ server_rec.srvname,
60+ option_rec.option_name,
61+ (SELECT id FROM vault.secrets WHERE option_rec.option_value IN (id::text, key_id::text))
62+ );
63+ END IF;
64+ END LOOP;
65+ END LOOP;
66+ END IF;
67+ END;
68+ \$\$ ;
69+ EOF
70+ )
71+ run_sql -c " $UPDATE_WRAPPERS_SERVER_OPTIONS_QUERY "
72+ }
73+
3574function execute_patches {
3675 # Patch pg_net grants
3776 PG_NET_ENABLED=$( run_sql -A -t -c " select count(*) > 0 from pg_extension where extname = 'pg_net';" )
@@ -152,81 +191,42 @@ EOF
152191 run_sql -c " update pg_extension set extowner = 'postgres'::regrole where extname = 'pgmq';"
153192 fi
154193
155- # If upgrading to pgsodium-less Vault, Wrappers need to be updated so that
156- # foreign servers use `vault.secrets.id` instead of `vault.secrets.key_id`
157- UPDATE_WRAPPERS_SERVER_OPTIONS_QUERY=$( cat << EOF
158- DO \$\$
159- DECLARE
160- server_rec RECORD;
161- option_rec RECORD;
162- vault_secrets RECORD;
163- BEGIN
164- IF EXISTS (SELECT FROM pg_available_extension_versions WHERE name = 'wrappers' AND version = '0.4.6')
165- AND EXISTS (SELECT FROM pg_extension WHERE extname = 'wrappers')
166- THEN
167- FOR server_rec IN
168- SELECT srvname, srvoptions
169- FROM pg_foreign_server
170- LOOP
171- FOR option_rec IN
172- SELECT split_part(srvoption, '=', 1) AS option_name, split_part(srvoption, '=', 2) AS option_value
173- FROM UNNEST(server_rec.srvoptions) AS srvoption
174- LOOP
175- IF EXISTS (SELECT FROM vault.secrets WHERE option_rec.option_value IN (id::text, key_id::text)) THEN
176- RAISE WARNING '%', format(
177- 'ALTER SERVER %I OPTIONS (SET %I %L)',
178- server_rec.srvname,
179- option_rec.option_name,
180- (SELECT id FROM vault.secrets WHERE option_rec.option_value IN (id::text, key_id::text))
181- );
182- END IF;
183- END LOOP;
184- END LOOP;
185- END IF;
186- CREATE SCHEMA sentinel;
187- END;
188- \$\$ ;
194+ # Patch to handle upgrading to pgsodium-less Vault
195+ REENCRYPT_VAULT_SECRETS_QUERY=$( cat << EOF
196+ DO \$\$
197+ BEGIN
198+ IF EXISTS (SELECT FROM pg_available_extension_versions WHERE name = 'supabase_vault' AND version = '0.3.0')
199+ AND EXISTS (SELECT FROM pg_extension WHERE extname = 'supabase_vault')
200+ THEN
201+ IF (SELECT extversion FROM pg_extension WHERE extname = 'supabase_vault') != '0.2.8' THEN
202+ GRANT USAGE ON SCHEMA vault TO postgres WITH GRANT OPTION;
203+ GRANT SELECT, DELETE ON vault.secrets, vault.decrypted_secrets TO postgres WITH GRANT OPTION;
204+ GRANT EXECUTE ON FUNCTION vault.create_secret, vault.update_secret, vault._crypto_aead_det_decrypt TO postgres WITH GRANT OPTION;
205+ END IF;
206+ -- Do an explicit IF EXISTS check to avoid referencing pgsodium objects if the project already migrated away from using pgsodium.
207+ IF EXISTS (SELECT FROM vault.secrets WHERE key_id IS NOT NULL) THEN
208+ UPDATE vault.secrets s
209+ SET
210+ secret = encode(
211+ vault._crypto_aead_det_encrypt(
212+ message := pgsodium.crypto_aead_det_decrypt(decode(s.secret, 'base64'), convert_to(s.id || s.description || s.created_at || s.updated_at, 'utf8'), s.key_id, s.nonce),
213+ additional := convert_to(s.id::text, 'utf8'),
214+ key_id := 0,
215+ context := 'pgsodium'::bytea,
216+ nonce := s.nonce
217+ ),
218+ 'base64'
219+ ),
220+ key_id = NULL
221+ WHERE
222+ key_id IS NOT NULL;
223+ END IF;
224+ END IF;
225+ END
226+ \$\$ ;
189227EOF
190228 )
191- run_sql -c " $UPDATE_WRAPPERS_SERVER_OPTIONS_QUERY "
192- run_sql -c " select * from vault.secrets"
193-
194- # # Patch to handle upgrading to pgsodium-less Vault
195- # REENCRYPT_VAULT_SECRETS_QUERY=$(cat <<EOF
196- # DO \$\$
197- # BEGIN
198- # IF EXISTS (SELECT FROM pg_available_extension_versions WHERE name = 'supabase_vault' AND version = '0.3.0')
199- # AND EXISTS (SELECT FROM pg_extension WHERE extname = 'supabase_vault')
200- # THEN
201- # IF (SELECT extversion FROM pg_extension WHERE extname = 'supabase_vault') != '0.2.8' THEN
202- # GRANT USAGE ON SCHEMA vault TO postgres WITH GRANT OPTION;
203- # GRANT SELECT, DELETE ON vault.secrets, vault.decrypted_secrets TO postgres WITH GRANT OPTION;
204- # GRANT EXECUTE ON FUNCTION vault.create_secret, vault.update_secret, vault._crypto_aead_det_decrypt TO postgres WITH GRANT OPTION;
205- # END IF;
206- # -- Do an explicit IF EXISTS check to avoid referencing pgsodium objects if the project already migrated away from using pgsodium.
207- # IF EXISTS (SELECT FROM vault.secrets WHERE key_id IS NOT NULL) THEN
208- # UPDATE vault.secrets s
209- # SET
210- # secret = encode(
211- # vault._crypto_aead_det_encrypt(
212- # message := pgsodium.crypto_aead_det_decrypt(decode(s.secret, 'base64'), convert_to(s.id || s.description || s.created_at || s.updated_at, 'utf8'), s.key_id, s.nonce),
213- # additional := convert_to(s.id::text, 'utf8'),
214- # key_id := 0,
215- # context := 'pgsodium'::bytea,
216- # nonce := s.nonce
217- # ),
218- # 'base64'
219- # ),
220- # key_id = NULL
221- # WHERE
222- # key_id IS NOT NULL;
223- # END IF;
224- # END IF;
225- # END
226- # \$\$;
227- # EOF
228- # )
229- # run_sql -c "$REENCRYPT_VAULT_SECRETS_QUERY"
229+ run_sql -c " $REENCRYPT_VAULT_SECRETS_QUERY "
230230
231231 run_sql -c " grant pg_read_all_data, pg_signal_backend to postgres"
232232}
@@ -259,12 +259,15 @@ function complete_pg_upgrade {
259259
260260 execute_extension_upgrade_patches || true
261261
262+ # For this to work we need `vault.secrets` from the old project to be
263+ # preserved, but `run_generated_sql` includes `ALTER EXTENSION
264+ # supabase_vault UPDATE` which modifies that. So we need to run it
265+ # beforehand.
266+ echo " 3.1. Patch Wrappers server options"
267+ execute_wrappers_patch
268+
262269 echo " 4. Running generated SQL files"
263- echo " before"
264- retry 3 print_vault_secrets
265270 retry 3 run_generated_sql
266- echo " after"
267- retry 3 print_vault_secrets
268271
269272 echo " 4.1. Applying patches"
270273 execute_patches || true
@@ -303,8 +306,6 @@ function run_generated_sql {
303306 if [ -d /data/sql ]; then
304307 for FILE in /data/sql/* .sql; do
305308 if [ -f " $FILE " ]; then
306- echo " executing $FILE "
307- cat " $FILE "
308309 run_sql -f " $FILE " || true
309310 fi
310311 done
0 commit comments