From c00b81a56b73b23eda94fc2b926fcf0a31a9dc92 Mon Sep 17 00:00:00 2001 From: akshaydeo Date: Mon, 5 Jan 2026 09:20:17 +0530 Subject: [PATCH] adds env resolution for loadingConfigFromFile --- framework/vectorstore/store.go | 33 +++++++++++++++++++++ transports/bifrost-http/lib/config.go | 41 ++++++++++++--------------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/framework/vectorstore/store.go b/framework/vectorstore/store.go index c36063701..09fbf2a0a 100644 --- a/framework/vectorstore/store.go +++ b/framework/vectorstore/store.go @@ -5,8 +5,10 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/maximhq/bifrost/core/schemas" + "github.com/maximhq/bifrost/framework/envutils" ) type VectorStoreType string @@ -123,18 +125,49 @@ func (c *Config) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(temp.Config, &weaviateConfig); err != nil { return fmt.Errorf("failed to unmarshal weaviate config: %w", err) } + // Process env. values for sensitive fields + if weaviateConfig.APIKey != "" && strings.HasPrefix(weaviateConfig.APIKey, "env.") { + apiKey, err := envutils.ProcessEnvValue(weaviateConfig.APIKey) + if err != nil { + return fmt.Errorf("failed to process env value for weaviate api_key: %w", err) + } + weaviateConfig.APIKey = apiKey + } c.Config = weaviateConfig case VectorStoreTypeRedis: var redisConfig RedisConfig if err := json.Unmarshal(temp.Config, &redisConfig); err != nil { return fmt.Errorf("failed to unmarshal redis config: %w", err) } + // Process env. values for sensitive fields + if redisConfig.Username != "" && strings.HasPrefix(redisConfig.Username, "env.") { + username, err := envutils.ProcessEnvValue(redisConfig.Username) + if err != nil { + return fmt.Errorf("failed to process env value for redis username: %w", err) + } + redisConfig.Username = username + } + if redisConfig.Password != "" && strings.HasPrefix(redisConfig.Password, "env.") { + password, err := envutils.ProcessEnvValue(redisConfig.Password) + if err != nil { + return fmt.Errorf("failed to process env value for redis password: %w", err) + } + redisConfig.Password = password + } c.Config = redisConfig case VectorStoreTypeQdrant: var qdrantConfig QdrantConfig if err := json.Unmarshal(temp.Config, &qdrantConfig); err != nil { return fmt.Errorf("failed to unmarshal qdrant config: %w", err) } + // Process env. values for sensitive fields + if qdrantConfig.APIKey != "" && strings.HasPrefix(qdrantConfig.APIKey, "env.") { + apiKey, err := envutils.ProcessEnvValue(qdrantConfig.APIKey) + if err != nil { + return fmt.Errorf("failed to process env value for qdrant api_key: %w", err) + } + qdrantConfig.APIKey = apiKey + } c.Config = qdrantConfig default: return fmt.Errorf("unknown vector store type: %s", temp.Type) diff --git a/transports/bifrost-http/lib/config.go b/transports/bifrost-http/lib/config.go index 44c3cbf3b..1e31c2ab2 100644 --- a/transports/bifrost-http/lib/config.go +++ b/transports/bifrost-http/lib/config.go @@ -937,38 +937,15 @@ func mergeMCPConfig(ctx context.Context, config *Config, configData *ConfigData, // loadGovernanceConfigFromFile loads and merges governance config from file func loadGovernanceConfigFromFile(ctx context.Context, config *Config, configData *ConfigData) { - logger.Debug("loadGovernanceConfigFromFile called") var governanceConfig *configstore.GovernanceConfig var err error - // Debug: Check what's in configData.Governance - if configData.Governance != nil { - logger.Debug("configData.Governance is present: %d budgets, %d rate_limits, %d virtual_keys", - len(configData.Governance.Budgets), - len(configData.Governance.RateLimits), - len(configData.Governance.VirtualKeys)) - for i, vk := range configData.Governance.VirtualKeys { - logger.Debug(" VK[%d]: id=%s, name=%s, provider_configs=%d", - i, vk.ID, vk.Name, vk.Value, len(vk.ProviderConfigs)) - } - } else { - logger.Debug("configData.Governance is nil") - } - if config.ConfigStore != nil { logger.Debug("getting governance config from store") governanceConfig, err = config.ConfigStore.GetGovernanceConfig(ctx) if err != nil { logger.Warn("failed to get governance config from store: %v", err) } - if governanceConfig != nil { - logger.Debug("governance config from store: %d budgets, %d rate_limits, %d virtual_keys", - len(governanceConfig.Budgets), - len(governanceConfig.RateLimits), - len(governanceConfig.VirtualKeys)) - } else { - logger.Debug("governance config from store is nil") - } } else { logger.Debug("config.ConfigStore is nil, skipping store lookup") } @@ -1149,6 +1126,24 @@ func mergeGovernanceConfig(ctx context.Context, config *Config, configData *Conf } if !found { configData.Governance.VirtualKeys[i].ConfigHash = fileVKHash + // if the virtual key value is env.VIRTUAL_KEY_VALUE, then we will need to resolve the environment variable + // Process environment variable for virtual key value + processedValue, envVar, err := config.processEnvValue(configData.Governance.VirtualKeys[i].Value) + if err != nil { + logger.Warn("failed to process env var for virtual key %s: %v", configData.Governance.VirtualKeys[i].ID, err) + continue + } + configData.Governance.VirtualKeys[i].Value = processedValue + // Track environment variable if used + if envVar != "" { + config.EnvKeys[envVar] = append(config.EnvKeys[envVar], configstore.EnvKeyInfo{ + EnvVar: envVar, + Provider: "", + KeyType: "virtual_key", + ConfigPath: fmt.Sprintf("governance.virtual_keys[%s].value", configData.Governance.VirtualKeys[i].ID), + KeyID: "", + }) + } virtualKeysToAdd = append(virtualKeysToAdd, configData.Governance.VirtualKeys[i]) } }