From 8bb93cfd86a60e6068b1724d23625f70c707588a Mon Sep 17 00:00:00 2001 From: Ryan Kazokas Date: Fri, 17 Mar 2023 13:38:50 -0400 Subject: [PATCH 1/8] Adds code to pull from env --- internal/utils/misc.go | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/internal/utils/misc.go b/internal/utils/misc.go index 544b0faa4..eefb2a003 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "io/fs" + "log" "net/http" "os" "os/exec" @@ -19,6 +20,7 @@ import ( "strings" "time" + "github.com/joho/godotenv" "github.com/spf13/afero" "github.com/supabase/cli/internal/utils/credentials" ) @@ -73,7 +75,20 @@ func ShortContainerImageName(imageName string) string { return matches[1] } -const ( +func getEnvValueOrDefault(key string, defaultValue string) string { + err := godotenv.Load(".env") + if err != nil { + log.Println("Error loading .env file. Values will be defaulted") + return defaultValue + } + var value = os.Getenv(key) + if value != "" { + return value + } + return defaultValue +} + +var ( // https://dba.stackexchange.com/a/11895 // Args: dbname TerminateDbSqlFmt = ` @@ -82,10 +97,10 @@ SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '%[1]s'; DO 'BEGIN WHILE ( SELECT COUNT(*) FROM pg_replication_slots WHERE database = ''%[1]s'' ) > 0 LOOP END LOOP; END';` - AnonKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0" - ServiceRoleKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU" - JWTSecret = "super-secret-jwt-token-with-at-least-32-characters-long" + AnonKey = getEnvValueOrDefault("ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") + ServiceRoleKey = getEnvValueOrDefault("SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") AccessTokenKey = "access-token" + JWTSecret = getEnvValueOrDefault("JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") ) var ( From 529ed20f79a3b1a2c82844754775a44089ef3581 Mon Sep 17 00:00:00 2001 From: Ryan Kazokas Date: Mon, 20 Mar 2023 20:32:58 -0400 Subject: [PATCH 2/8] Loads .env in main to support using in working directory and adding supabase prefix --- cmd/root.go | 10 +++++++++- internal/utils/misc.go | 13 +++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index d07db1dcb..6b63852b2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,9 +3,11 @@ package cmd import ( "errors" "fmt" + "log" "os" "strings" + "github.com/joho/godotenv" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -55,7 +57,13 @@ var ( return err } } - return os.Chdir(workdir) + changeDirectoryError := os.Chdir(workdir) + + err := godotenv.Load(".env") + if err != nil { + log.Println("Error loading .env file. Values will be defaulted") + } + return changeDirectoryError }, } ) diff --git a/internal/utils/misc.go b/internal/utils/misc.go index 0e29f59cb..844e68b9c 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -10,7 +10,6 @@ import ( "fmt" "io" "io/fs" - "log" "net/http" "os" "os/exec" @@ -20,7 +19,6 @@ import ( "strings" "time" - "github.com/joho/godotenv" "github.com/spf13/afero" "github.com/supabase/cli/internal/utils/credentials" ) @@ -76,11 +74,6 @@ func ShortContainerImageName(imageName string) string { } func getEnvValueOrDefault(key string, defaultValue string) string { - err := godotenv.Load(".env") - if err != nil { - log.Println("Error loading .env file. Values will be defaulted") - return defaultValue - } var value = os.Getenv(key) if value != "" { return value @@ -97,10 +90,10 @@ SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '%[1]s'; DO 'BEGIN WHILE ( SELECT COUNT(*) FROM pg_replication_slots WHERE database = ''%[1]s'' ) > 0 LOOP END LOOP; END';` - AnonKey = getEnvValueOrDefault("ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") - ServiceRoleKey = getEnvValueOrDefault("SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") + AnonKey = getEnvValueOrDefault("SUPABASE_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") + ServiceRoleKey = getEnvValueOrDefault("SUPABASE_SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") AccessTokenKey = "access-token" - JWTSecret = getEnvValueOrDefault("JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") + JWTSecret = getEnvValueOrDefault("SUPABASE_JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") ) var ( From 1e57832e91d6f2c57a60fb405fb659b15617d723 Mon Sep 17 00:00:00 2001 From: Ryan Kazokas Date: Mon, 20 Mar 2023 21:38:02 -0400 Subject: [PATCH 3/8] Changes env look up to use viper --- cmd/root.go | 9 ++------- internal/utils/misc.go | 29 ++++++++++++++++++----------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 6b63852b2..5b6f91834 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,11 +3,9 @@ package cmd import ( "errors" "fmt" - "log" "os" "strings" - "github.com/joho/godotenv" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -58,11 +56,8 @@ var ( } } changeDirectoryError := os.Chdir(workdir) - - err := godotenv.Load(".env") - if err != nil { - log.Println("Error loading .env file. Values will be defaulted") - } + envFile := fmt.Sprintf("%s/.env", workdir) + utils.LoadEnvVars(envFile) return changeDirectoryError }, } diff --git a/internal/utils/misc.go b/internal/utils/misc.go index 844e68b9c..916ca4a55 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -20,6 +20,7 @@ import ( "time" "github.com/spf13/afero" + "github.com/spf13/viper" "github.com/supabase/cli/internal/utils/credentials" ) @@ -73,14 +74,6 @@ func ShortContainerImageName(imageName string) string { return matches[1] } -func getEnvValueOrDefault(key string, defaultValue string) string { - var value = os.Getenv(key) - if value != "" { - return value - } - return defaultValue -} - var ( // https://dba.stackexchange.com/a/11895 // Args: dbname @@ -90,12 +83,26 @@ SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '%[1]s'; DO 'BEGIN WHILE ( SELECT COUNT(*) FROM pg_replication_slots WHERE database = ''%[1]s'' ) > 0 LOOP END LOOP; END';` - AnonKey = getEnvValueOrDefault("SUPABASE_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") - ServiceRoleKey = getEnvValueOrDefault("SUPABASE_SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") + AnonKey = "" + ServiceRoleKey = "" AccessTokenKey = "access-token" - JWTSecret = getEnvValueOrDefault("SUPABASE_JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") + JWTSecret = "" ) +func LoadEnvVars(envFile string) { + viper.SetConfigFile(envFile) + viper.ReadInConfig() + viper.SetDefault("SUPABASE_JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") + viper.SetDefault("SUPABASE_SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") + viper.SetDefault("SUPABASE_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") + var configJwt = viper.GetString("SUPABASE_JWT_SECRET") + var anonKey = viper.GetString("SUPABASE_ANON_KEY") + var serviceKey = viper.GetString("SUPABASE_SERVICE_ROLE_KEY") + JWTSecret = configJwt + AnonKey = anonKey + ServiceRoleKey = serviceKey +} + var ( CmdSuggestion string From 709303d955821ac5425fc550e202aa6343d64afa Mon Sep 17 00:00:00 2001 From: Ryan Kazokas Date: Mon, 20 Mar 2023 21:39:06 -0400 Subject: [PATCH 4/8] Updates prefixes --- internal/utils/misc.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/utils/misc.go b/internal/utils/misc.go index 916ca4a55..b6daedca0 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -92,9 +92,9 @@ DO 'BEGIN WHILE ( func LoadEnvVars(envFile string) { viper.SetConfigFile(envFile) viper.ReadInConfig() - viper.SetDefault("SUPABASE_JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") - viper.SetDefault("SUPABASE_SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") - viper.SetDefault("SUPABASE_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") + viper.SetDefault("SUPABASE_AUTH_JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") + viper.SetDefault("SUPABASE_AUTH_SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") + viper.SetDefault("SUPABASE_AUTH_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") var configJwt = viper.GetString("SUPABASE_JWT_SECRET") var anonKey = viper.GetString("SUPABASE_ANON_KEY") var serviceKey = viper.GetString("SUPABASE_SERVICE_ROLE_KEY") From a1e067d82588618eb60d7e5e671c87d6598a46c2 Mon Sep 17 00:00:00 2001 From: Ryan Kazokas Date: Mon, 20 Mar 2023 21:48:07 -0400 Subject: [PATCH 5/8] Fix env var key lookups --- internal/utils/misc.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/utils/misc.go b/internal/utils/misc.go index b6daedca0..8be74dc92 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -95,9 +95,9 @@ func LoadEnvVars(envFile string) { viper.SetDefault("SUPABASE_AUTH_JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") viper.SetDefault("SUPABASE_AUTH_SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") viper.SetDefault("SUPABASE_AUTH_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") - var configJwt = viper.GetString("SUPABASE_JWT_SECRET") - var anonKey = viper.GetString("SUPABASE_ANON_KEY") - var serviceKey = viper.GetString("SUPABASE_SERVICE_ROLE_KEY") + var configJwt = viper.GetString("SUPABASE_AUTH_JWT_SECRET") + var anonKey = viper.GetString("SUPABASE_AUTH_ANON_KEY") + var serviceKey = viper.GetString("SUPABASE_AUTH_SERVICE_ROLE_KEY") JWTSecret = configJwt AnonKey = anonKey ServiceRoleKey = serviceKey From db207843a6d5edb47dc1d5a2c64b642cd59bde5a Mon Sep 17 00:00:00 2001 From: Qiao Han Date: Tue, 21 Mar 2023 12:02:28 +0800 Subject: [PATCH 6/8] wip --- cmd/root.go | 18 ++++++++++++++---- internal/functions/serve/serve.go | 12 ++++++------ internal/start/start.go | 20 ++++++++++---------- internal/status/status.go | 8 ++++---- internal/utils/config.go | 13 +++++++++++++ internal/utils/misc.go | 20 +------------------- 6 files changed, 48 insertions(+), 43 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 5b6f91834..c41f49550 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -48,6 +48,7 @@ var ( } else { utils.CmdSuggestion = "Try rerunning the command with --debug to troubleshoot the error." } + // Set workdir workdir := viper.GetString("WORKDIR") if workdir == "" { var err error @@ -55,10 +56,19 @@ var ( return err } } - changeDirectoryError := os.Chdir(workdir) - envFile := fmt.Sprintf("%s/.env", workdir) - utils.LoadEnvVars(envFile) - return changeDirectoryError + if err := os.Chdir(workdir); err != nil { + return err + } + // Load secrets + f, err := os.Open(".env") + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil + } + return err + } + defer f.Close() + return viper.Unmarshal(&utils.Config) }, } ) diff --git a/internal/functions/serve/serve.go b/internal/functions/serve/serve.go index f88bbac3e..1ceee2736 100644 --- a/internal/functions/serve/serve.go +++ b/internal/functions/serve/serve.go @@ -99,7 +99,7 @@ func Run(ctx context.Context, slug string, envFilePath string, noVerifyJWT *bool }) env := []string{ - "JWT_SECRET=" + utils.JWTSecret, + "JWT_SECRET=" + utils.Config.Auth.JwtSecret, "DENO_ORIGIN=http://localhost:8000", } verifyJWTEnv := "VERIFY_JWT=true" @@ -182,8 +182,8 @@ func Run(ctx context.Context, slug string, envFilePath string, noVerifyJWT *bool env := []string{ "SUPABASE_URL=http://" + utils.KongId + ":8000", - "SUPABASE_ANON_KEY=" + utils.AnonKey, - "SUPABASE_SERVICE_ROLE_KEY=" + utils.ServiceRoleKey, + "SUPABASE_ANON_KEY=" + utils.Config.Auth.AnonKey, + "SUPABASE_SERVICE_ROLE_KEY=" + utils.Config.Auth.ServiceRoleKey, "SUPABASE_DB_URL=postgresql://postgres:postgres@localhost:" + strconv.FormatUint(uint64(utils.Config.Db.Port), 10) + "/postgres", } @@ -264,10 +264,10 @@ func runServeAll(ctx context.Context, envFilePath string, noVerifyJWT *bool, imp }) env := []string{ - "JWT_SECRET=" + utils.JWTSecret, + "JWT_SECRET=" + utils.Config.Auth.JwtSecret, "SUPABASE_URL=http://" + utils.KongId + ":8000", - "SUPABASE_ANON_KEY=" + utils.AnonKey, - "SUPABASE_SERVICE_ROLE_KEY=" + utils.ServiceRoleKey, + "SUPABASE_ANON_KEY=" + utils.Config.Auth.AnonKey, + "SUPABASE_SERVICE_ROLE_KEY=" + utils.Config.Auth.ServiceRoleKey, "SUPABASE_DB_URL=postgresql://postgres:postgres@localhost:" + strconv.FormatUint(uint64(utils.Config.Db.Port), 10) + "/postgres", } verifyJWTEnv := "VERIFY_JWT=true" diff --git a/internal/start/start.go b/internal/start/start.go index a28efdb1e..93c143268 100644 --- a/internal/start/start.go +++ b/internal/start/start.go @@ -103,8 +103,8 @@ func run(p utils.Program, ctx context.Context, fsys afero.Fs, excludedContainers var kongConfigBuf bytes.Buffer if err := kongConfigTemplate.Execute(&kongConfigBuf, struct{ ProjectId, AnonKey, ServiceRoleKey string }{ ProjectId: utils.Config.ProjectId, - AnonKey: utils.AnonKey, - ServiceRoleKey: utils.ServiceRoleKey, + AnonKey: utils.Config.Auth.AnonKey, + ServiceRoleKey: utils.Config.Auth.ServiceRoleKey, }); err != nil { return err } @@ -159,7 +159,7 @@ EOF "GOTRUE_JWT_AUD=authenticated", "GOTRUE_JWT_DEFAULT_GROUP_NAME=authenticated", fmt.Sprintf("GOTRUE_JWT_EXP=%v", utils.Config.Auth.JwtExpiry), - "GOTRUE_JWT_SECRET=" + utils.JWTSecret, + "GOTRUE_JWT_SECRET=" + utils.Config.Auth.JwtSecret, fmt.Sprintf("GOTRUE_EXTERNAL_EMAIL_ENABLED=%v", *utils.Config.Auth.Email.EnableSignup), fmt.Sprintf("GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED=%v", *utils.Config.Auth.Email.DoubleConfirmChanges), @@ -268,7 +268,7 @@ EOF "DB_NAME=postgres", "DB_AFTER_CONNECT_QUERY=SET search_path TO _realtime", "DB_ENC_KEY=supabaserealtime", - "API_JWT_SECRET=" + utils.JWTSecret, + "API_JWT_SECRET=" + utils.Config.Auth.JwtSecret, "FLY_ALLOC_ID=abc123", "FLY_APP_NAME=realtime", "SECRET_KEY_BASE=EAx3IQ/wRG1v47ZD4NE4/9RzBI8Jmil3x0yhcW4V2NHBP6c2iPIzwjofi2Ep4HIG", @@ -309,7 +309,7 @@ EOF "PGRST_DB_SCHEMAS=" + strings.Join(utils.Config.Api.Schemas, ","), "PGRST_DB_EXTRA_SEARCH_PATH=" + strings.Join(utils.Config.Api.ExtraSearchPath, ","), "PGRST_DB_ANON_ROLE=anon", - "PGRST_JWT_SECRET=" + utils.JWTSecret, + "PGRST_JWT_SECRET=" + utils.Config.Auth.JwtSecret, }, // PostgREST does not expose a shell for health check }, @@ -330,10 +330,10 @@ EOF container.Config{ Image: utils.StorageImage, Env: []string{ - "ANON_KEY=" + utils.AnonKey, - "SERVICE_KEY=" + utils.ServiceRoleKey, + "ANON_KEY=" + utils.Config.Auth.AnonKey, + "SERVICE_KEY=" + utils.Config.Auth.ServiceRoleKey, "POSTGREST_URL=http://" + utils.RestId + ":3000", - "PGRST_JWT_SECRET=" + utils.JWTSecret, + "PGRST_JWT_SECRET=" + utils.Config.Auth.JwtSecret, "DATABASE_URL=postgresql://supabase_storage_admin:postgres@" + utils.DbId + ":5432/postgres", fmt.Sprintf("FILE_SIZE_LIMIT=%v", utils.Config.Storage.FileSizeLimit), "STORAGE_BACKEND=file", @@ -431,8 +431,8 @@ EOF "SUPABASE_URL=http://" + utils.KongId + ":8000", fmt.Sprintf("SUPABASE_REST_URL=http://localhost:%v/rest/v1/", utils.Config.Api.Port), fmt.Sprintf("SUPABASE_PUBLIC_URL=http://localhost:%v/", utils.Config.Api.Port), - "SUPABASE_ANON_KEY=" + utils.AnonKey, - "SUPABASE_SERVICE_KEY=" + utils.ServiceRoleKey, + "SUPABASE_ANON_KEY=" + utils.Config.Auth.AnonKey, + "SUPABASE_SERVICE_KEY=" + utils.Config.Auth.ServiceRoleKey, }, Healthcheck: &container.HealthConfig{ Test: []string{"CMD", "node", "-e", "require('http').get('http://localhost:3000/api/profile', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"}, diff --git a/internal/status/status.go b/internal/status/status.go index 8ea7bf461..ccf75f500 100644 --- a/internal/status/status.go +++ b/internal/status/status.go @@ -46,9 +46,9 @@ func (c *CustomName) toValues(exclude ...string) map[string]string { values[c.StudioURL] = fmt.Sprintf("http://localhost:%d", utils.Config.Studio.Port) } if !sliceContains(exclude, utils.GotrueId) && !sliceContains(exclude, utils.ShortContainerImageName(utils.GotrueImage)) { - values[c.JWTSecret] = utils.JWTSecret - values[c.AnonKey] = utils.AnonKey - values[c.ServiceRoleKey] = utils.ServiceRoleKey + values[c.JWTSecret] = utils.Config.Auth.JwtSecret + values[c.AnonKey] = utils.Config.Auth.AnonKey + values[c.ServiceRoleKey] = utils.Config.Auth.ServiceRoleKey } if !sliceContains(exclude, utils.InbucketId) && !sliceContains(exclude, utils.ShortContainerImageName(utils.InbucketImage)) { values[c.InbucketURL] = fmt.Sprintf("http://localhost:%d", utils.Config.Inbucket.Port) @@ -138,7 +138,7 @@ func isPostgRESTHealthy(ctx context.Context) bool { if err != nil { return false } - req.Header.Add("apikey", utils.AnonKey) + req.Header.Add("apikey", utils.Config.Auth.AnonKey) resp, err := http.DefaultClient.Do(req) return err == nil && resp.StatusCode == http.StatusOK } diff --git a/internal/utils/config.go b/internal/utils/config.go index ba3a04e1e..762a55058 100644 --- a/internal/utils/config.go +++ b/internal/utils/config.go @@ -124,6 +124,10 @@ type ( EnableSignup *bool `toml:"enable_signup"` Email email `toml:"email"` External map[string]provider + // Custom secrets can be injected from .env file + JwtSecret string `toml:"-"` + AnonKey string `toml:"-"` + ServiceRoleKey string `toml:"-"` } email struct { @@ -236,6 +240,15 @@ func LoadConfigFS(fsys afero.Fs) error { if Config.Auth.JwtExpiry == 0 { Config.Auth.JwtExpiry = 3600 } + if Config.Auth.JwtSecret == "" { + Config.Auth.JwtSecret = "super-secret-jwt-token-with-at-least-32-characters-long" + } + if Config.Auth.AnonKey == "" { + Config.Auth.AnonKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0" + } + if Config.Auth.ServiceRoleKey == "" { + Config.Auth.ServiceRoleKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU" + } if Config.Auth.EnableSignup == nil { x := true Config.Auth.EnableSignup = &x diff --git a/internal/utils/misc.go b/internal/utils/misc.go index 8be74dc92..fe9db8a16 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -20,7 +20,6 @@ import ( "time" "github.com/spf13/afero" - "github.com/spf13/viper" "github.com/supabase/cli/internal/utils/credentials" ) @@ -74,7 +73,7 @@ func ShortContainerImageName(imageName string) string { return matches[1] } -var ( +const ( // https://dba.stackexchange.com/a/11895 // Args: dbname TerminateDbSqlFmt = ` @@ -83,26 +82,9 @@ SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '%[1]s'; DO 'BEGIN WHILE ( SELECT COUNT(*) FROM pg_replication_slots WHERE database = ''%[1]s'' ) > 0 LOOP END LOOP; END';` - AnonKey = "" - ServiceRoleKey = "" AccessTokenKey = "access-token" - JWTSecret = "" ) -func LoadEnvVars(envFile string) { - viper.SetConfigFile(envFile) - viper.ReadInConfig() - viper.SetDefault("SUPABASE_AUTH_JWT_SECRET", "super-secret-jwt-token-with-at-least-32-characters-long") - viper.SetDefault("SUPABASE_AUTH_SERVICE_ROLE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU") - viper.SetDefault("SUPABASE_AUTH_ANON_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0") - var configJwt = viper.GetString("SUPABASE_AUTH_JWT_SECRET") - var anonKey = viper.GetString("SUPABASE_AUTH_ANON_KEY") - var serviceKey = viper.GetString("SUPABASE_AUTH_SERVICE_ROLE_KEY") - JWTSecret = configJwt - AnonKey = anonKey - ServiceRoleKey = serviceKey -} - var ( CmdSuggestion string From cafb147e44afc8740bddf8c039d91a1dab721994 Mon Sep 17 00:00:00 2001 From: Qiao Han Date: Tue, 21 Mar 2023 15:41:53 +0800 Subject: [PATCH 7/8] feat: allow secrets override from .env file --- cmd/root.go | 31 +++++++++++++++++-------------- internal/utils/config.go | 17 +++++++++++++---- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index c41f49550..bfb5d5816 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,9 +3,11 @@ package cmd import ( "errors" "fmt" + "log" "os" "strings" + "github.com/mitchellh/mapstructure" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -56,19 +58,7 @@ var ( return err } } - if err := os.Chdir(workdir); err != nil { - return err - } - // Load secrets - f, err := os.Open(".env") - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return nil - } - return err - } - defer f.Close() - return viper.Unmarshal(&utils.Config) + return os.Chdir(workdir) }, } ) @@ -84,8 +74,21 @@ func Execute() { func init() { cobra.OnInitialize(func() { + // Allow overriding config with automatic env + envKeysMap := map[string]interface{}{} + if dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + Result: &envKeysMap, + IgnoreUntaggedFields: true, + }); err != nil { + log.Fatalln(err) + } else if err := dec.Decode(utils.Config); err != nil { + log.Fatalln(err) + } + if err := viper.MergeConfigMap(envKeysMap); err != nil { + log.Fatalln(err) + } viper.SetEnvPrefix("SUPABASE") - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) viper.AutomaticEnv() }) diff --git a/internal/utils/config.go b/internal/utils/config.go index 762a55058..caae461f3 100644 --- a/internal/utils/config.go +++ b/internal/utils/config.go @@ -11,7 +11,9 @@ import ( "github.com/BurntSushi/toml" "github.com/docker/go-units" + "github.com/joho/godotenv" "github.com/spf13/afero" + "github.com/spf13/viper" ) var ( @@ -84,7 +86,7 @@ type ( Studio studio `toml:"studio"` Inbucket inbucket `toml:"inbucket"` Storage storage `toml:"storage"` - Auth auth `toml:"auth"` + Auth auth `toml:"auth" mapstructure:"auth"` Functions map[string]function `toml:"functions"` // TODO // Scripts scripts @@ -125,9 +127,9 @@ type ( Email email `toml:"email"` External map[string]provider // Custom secrets can be injected from .env file - JwtSecret string `toml:"-"` - AnonKey string `toml:"-"` - ServiceRoleKey string `toml:"-"` + JwtSecret string `toml:"-" mapstructure:"jwt_secret"` + AnonKey string `toml:"-" mapstructure:"anon_key"` + ServiceRoleKey string `toml:"-" mapstructure:"service_role_key"` } email struct { @@ -170,6 +172,13 @@ func LoadConfigFS(fsys afero.Fs) error { } return fmt.Errorf("cannot read config in %s: %w", cwd, err) } + // Load secrets from .env file + if err := godotenv.Load(); err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } + if err := viper.Unmarshal(&Config); err != nil { + return err + } // Process decoded TOML. { From af8bcb78a55bc474e6118e44e6d796569d87adec Mon Sep 17 00:00:00 2001 From: Qiao Han Date: Tue, 21 Mar 2023 15:46:14 +0800 Subject: [PATCH 8/8] chore: add comments to umbrella issue --- cmd/root.go | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index bfb5d5816..4a158c56e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,7 +3,6 @@ package cmd import ( "errors" "fmt" - "log" "os" "strings" @@ -50,7 +49,6 @@ var ( } else { utils.CmdSuggestion = "Try rerunning the command with --debug to troubleshoot the error." } - // Set workdir workdir := viper.GetString("WORKDIR") if workdir == "" { var err error @@ -74,19 +72,16 @@ func Execute() { func init() { cobra.OnInitialize(func() { - // Allow overriding config with automatic env + // Allow overriding config object with automatic env + // Ref: https://github.com/spf13/viper/issues/761 envKeysMap := map[string]interface{}{} - if dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ Result: &envKeysMap, IgnoreUntaggedFields: true, - }); err != nil { - log.Fatalln(err) - } else if err := dec.Decode(utils.Config); err != nil { - log.Fatalln(err) - } - if err := viper.MergeConfigMap(envKeysMap); err != nil { - log.Fatalln(err) - } + }) + cobra.CheckErr(err) + cobra.CheckErr(dec.Decode(utils.Config)) + cobra.CheckErr(viper.MergeConfigMap(envKeysMap)) viper.SetEnvPrefix("SUPABASE") viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) viper.AutomaticEnv()