diff --git a/core/config/model_config.go b/core/config/model_config.go index 533da24ec..9c38f178d 100644 --- a/core/config/model_config.go +++ b/core/config/model_config.go @@ -303,19 +303,21 @@ const ( ) // ResolveAPIKey returns the upstream key from api_key_env or api_key_file, or -// "" when neither is set. The cloud-proxy backend applies the same rules. +// "" when neither is set. Mirrored (not imported, to keep backends independent +// of core's package layout) by resolveAPIKey in backend/go/cloud-proxy/proxy.go +// — keep the two in sync, empty-value handling included. func (p ProxyConfig) ResolveAPIKey() (string, error) { switch { case p.APIKeyEnv != "": - v, ok := os.LookupEnv(p.APIKeyEnv) - if !ok { - return "", fmt.Errorf("proxy api_key_env %q is not set", p.APIKeyEnv) + v := os.Getenv(p.APIKeyEnv) + if v == "" { + return "", fmt.Errorf("proxy api_key_env %q is unset", p.APIKeyEnv) } return v, nil case p.APIKeyFile != "": b, err := os.ReadFile(p.APIKeyFile) if err != nil { - return "", fmt.Errorf("proxy api_key_file: %w", err) + return "", fmt.Errorf("proxy api_key_file %q: %w", p.APIKeyFile, err) } return strings.TrimSpace(string(b)), nil } diff --git a/core/config/model_config_failover_test.go b/core/config/model_config_failover_test.go index fe34c5c66..9e82868e9 100644 --- a/core/config/model_config_failover_test.go +++ b/core/config/model_config_failover_test.go @@ -78,6 +78,11 @@ var _ = Describe("ProxyConfig.ResolveAPIKey", func() { _, err := ProxyConfig{APIKeyEnv: "FAILOVER_TEST_UNSET_KEY"}.ResolveAPIKey() Expect(err).To(HaveOccurred()) }) + It("fails on a set-but-empty env var", func() { + GinkgoT().Setenv("FAILOVER_TEST_EMPTY_KEY", "") + _, err := ProxyConfig{APIKeyEnv: "FAILOVER_TEST_EMPTY_KEY"}.ResolveAPIKey() + Expect(err).To(HaveOccurred()) + }) It("reads and trims the key file", func() { f := filepath.Join(GinkgoT().TempDir(), "key") Expect(os.WriteFile(f, []byte(" k2\n"), 0o600)).To(Succeed())