Skip to content

Commit 722c814

Browse files
authored
feat: update vault secrets from config (#3080)
* feat: update vault secrets from config * chore: create or update vault secrets * chore: move vault to pkg
1 parent 5017dcb commit 722c814

File tree

8 files changed

+92
-24
lines changed

8 files changed

+92
-24
lines changed

internal/db/push/push.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/supabase/cli/internal/utils"
1515
"github.com/supabase/cli/internal/utils/flags"
1616
"github.com/supabase/cli/pkg/migration"
17+
"github.com/supabase/cli/pkg/vault"
1718
)
1819

1920
func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles, includeSeed bool, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
@@ -82,6 +83,9 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
8283
} else if !shouldPush {
8384
return errors.New(context.Canceled)
8485
}
86+
if err := vault.UpsertVaultSecrets(ctx, utils.Config.Db.Vault, conn); err != nil {
87+
return err
88+
}
8589
if err := migration.ApplyMigrations(ctx, pending, conn, afero.NewIOFS(fsys)); err != nil {
8690
return err
8791
}

internal/db/reset/reset.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ import (
2323
"github.com/supabase/cli/internal/db/start"
2424
"github.com/supabase/cli/internal/gen/keys"
2525
"github.com/supabase/cli/internal/migration/apply"
26-
"github.com/supabase/cli/internal/migration/list"
2726
"github.com/supabase/cli/internal/migration/repair"
2827
"github.com/supabase/cli/internal/seed/buckets"
2928
"github.com/supabase/cli/internal/utils"
3029
"github.com/supabase/cli/pkg/migration"
30+
"github.com/supabase/cli/pkg/vault"
3131
)
3232

3333
func Run(ctx context.Context, version string, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
@@ -242,22 +242,10 @@ func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys
242242
if err := migration.DropUserSchemas(ctx, conn); err != nil {
243243
return err
244244
}
245-
migrations, err := list.LoadPartialMigrations(version, fsys)
246-
if err != nil {
247-
return err
248-
}
249-
if err := migration.ApplyMigrations(ctx, migrations, conn, afero.NewIOFS(fsys)); err != nil {
245+
if err := vault.UpsertVaultSecrets(ctx, utils.Config.Db.Vault, conn); err != nil {
250246
return err
251247
}
252-
if !utils.Config.Db.Seed.Enabled {
253-
// Skip because --no-seed flag is set
254-
return nil
255-
}
256-
seeds, err := migration.GetPendingSeeds(ctx, utils.Config.Db.Seed.SqlPaths, conn, afero.NewIOFS(fsys))
257-
if err != nil {
258-
return err
259-
}
260-
return migration.SeedData(ctx, seeds, conn, afero.NewIOFS(fsys))
248+
return apply.MigrateAndSeed(ctx, version, conn, fsys)
261249
}
262250

263251
func LikeEscapeSchema(schemas []string) (result []string) {

internal/db/start/start.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/supabase/cli/internal/utils"
2626
"github.com/supabase/cli/internal/utils/flags"
2727
"github.com/supabase/cli/pkg/migration"
28+
"github.com/supabase/cli/pkg/vault"
2829
)
2930

3031
var (
@@ -372,6 +373,10 @@ func SetupDatabase(ctx context.Context, conn *pgx.Conn, host string, w io.Writer
372373
if err := initSchema(ctx, conn, host, w); err != nil {
373374
return err
374375
}
376+
// Create vault secrets first so roles.sql can reference them
377+
if err := vault.UpsertVaultSecrets(ctx, utils.Config.Db.Vault, conn); err != nil {
378+
return err
379+
}
375380
err := migration.SeedGlobals(ctx, []string{utils.CustomRolesPath}, conn, afero.NewIOFS(fsys))
376381
if errors.Is(err, os.ErrNotExist) {
377382
return nil

internal/migration/up/up.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/spf13/afero"
1212
"github.com/supabase/cli/internal/utils"
1313
"github.com/supabase/cli/pkg/migration"
14+
"github.com/supabase/cli/pkg/vault"
1415
)
1516

1617
func Run(ctx context.Context, includeAll bool, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
@@ -23,6 +24,9 @@ func Run(ctx context.Context, includeAll bool, config pgconn.Config, fsys afero.
2324
if err != nil {
2425
return err
2526
}
27+
if err := vault.UpsertVaultSecrets(ctx, utils.Config.Db.Vault, conn); err != nil {
28+
return err
29+
}
2630
return migration.ApplyMigrations(ctx, pending, conn, afero.NewIOFS(fsys))
2731
}
2832

pkg/config/db.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,16 @@ type (
5151
}
5252

5353
db struct {
54-
Image string `toml:"-"`
55-
Port uint16 `toml:"port"`
56-
ShadowPort uint16 `toml:"shadow_port"`
57-
MajorVersion uint `toml:"major_version"`
58-
Password string `toml:"-"`
59-
RootKey string `toml:"-" mapstructure:"root_key"`
60-
Pooler pooler `toml:"pooler"`
61-
Seed seed `toml:"seed"`
62-
Settings settings `toml:"settings"`
54+
Image string `toml:"-"`
55+
Port uint16 `toml:"port"`
56+
ShadowPort uint16 `toml:"shadow_port"`
57+
MajorVersion uint `toml:"major_version"`
58+
Password string `toml:"-"`
59+
RootKey string `toml:"-" mapstructure:"root_key"`
60+
Pooler pooler `toml:"pooler"`
61+
Seed seed `toml:"seed"`
62+
Settings settings `toml:"settings"`
63+
Vault map[string]Secret `toml:"vault"`
6364
}
6465

6566
seed struct {

pkg/config/templates/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ default_pool_size = 20
4242
# Maximum number of client connections allowed.
4343
max_client_conn = 100
4444

45+
# [db.vault]
46+
# secret_key = "env(SECRET_VALUE)"
47+
4548
[db.seed]
4649
# If enabled, seeds the database after migrations during a db reset.
4750
enabled = true

pkg/config/testdata/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ default_pool_size = 20
4242
# Maximum number of client connections allowed.
4343
max_client_conn = 100
4444

45+
[db.vault]
46+
test_key = "test_value"
47+
4548
[db.seed]
4649
# If enabled, seeds the database after migrations during a db reset.
4750
enabled = true

pkg/vault/batch.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package vault
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/go-errors/errors"
9+
"github.com/jackc/pgx/v4"
10+
"github.com/supabase/cli/pkg/config"
11+
"github.com/supabase/cli/pkg/pgxv5"
12+
)
13+
14+
const (
15+
CREATE_VAULT_KV = "SELECT vault.create_secret($1, $2)"
16+
READ_VAULT_KV = "SELECT id, name FROM vault.secrets WHERE name = ANY($1)"
17+
UPDATE_VAULT_KV = "SELECT vault.update_secret($1, $2)"
18+
)
19+
20+
type VaultTable struct {
21+
Id string
22+
Name string
23+
}
24+
25+
func UpsertVaultSecrets(ctx context.Context, secrets map[string]config.Secret, conn *pgx.Conn) error {
26+
var keys []string
27+
toInsert := map[string]string{}
28+
for k, v := range secrets {
29+
if len(v.SHA256) > 0 {
30+
keys = append(keys, k)
31+
toInsert[k] = v.Value
32+
}
33+
}
34+
if len(keys) == 0 {
35+
return nil
36+
}
37+
fmt.Fprintln(os.Stderr, "Updating vault secrets...")
38+
rows, err := conn.Query(ctx, READ_VAULT_KV, keys)
39+
if err != nil {
40+
return errors.Errorf("failed to read vault: %w", err)
41+
}
42+
toUpdate, err := pgxv5.CollectRows[VaultTable](rows)
43+
if err != nil {
44+
return err
45+
}
46+
batch := pgx.Batch{}
47+
for _, r := range toUpdate {
48+
secret := secrets[r.Name]
49+
batch.Queue(UPDATE_VAULT_KV, r.Id, secret.Value)
50+
delete(toInsert, r.Name)
51+
}
52+
// Remaining secrets should be created
53+
for k, v := range toInsert {
54+
batch.Queue(CREATE_VAULT_KV, v, k)
55+
}
56+
if err := conn.SendBatch(ctx, &batch).Close(); err != nil {
57+
return errors.Errorf("failed to update vault: %w", err)
58+
}
59+
return nil
60+
}

0 commit comments

Comments
 (0)