first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,242 @@
package configstore
import (
"encoding/json"
"strings"
"testing"
"github.com/maximhq/bifrost/core/schemas"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestProviderConfig_Redacted_AutoMasksEnvBackedFields verifies that env-backed
// values in any provider config field are automatically redacted in the JSON output
// of a Redacted() ProviderConfig — even fields that don't have explicit Redacted()
// calls (like Azure APIVersion). This is the defense-in-depth guarantee provided
// by EnvVar.MarshalJSON.
func TestProviderConfig_Redacted_AutoMasksEnvBackedFields(t *testing.T) {
t.Setenv("MY_AZURE_API_VERSION_SECRET", "2024-10-21-preview-secret")
apiVersion := schemas.NewEnvVar("env.MY_AZURE_API_VERSION_SECRET")
require.True(t, apiVersion.IsFromEnv(), "setup: APIVersion should be FromEnv")
require.Equal(t, "2024-10-21-preview-secret", apiVersion.GetValue(),
"setup: APIVersion should be resolved")
config := ProviderConfig{
Keys: []schemas.Key{{
ID: "k1",
Name: "test",
Value: schemas.EnvVar{Val: ""},
AzureKeyConfig: &schemas.AzureKeyConfig{
Endpoint: *schemas.NewEnvVar("https://foo.openai.azure.com"),
APIVersion: apiVersion,
},
}},
}
redacted := config.Redacted()
require.NotNil(t, redacted)
require.Len(t, redacted.Keys, 1)
require.NotNil(t, redacted.Keys[0].AzureKeyConfig)
require.NotNil(t, redacted.Keys[0].AzureKeyConfig.APIVersion)
// Marshal the APIVersion field as it would be sent to the UI.
data, err := json.Marshal(redacted.Keys[0].AzureKeyConfig.APIVersion)
require.NoError(t, err)
var out struct {
Value string `json:"value"`
EnvVar string `json:"env_var"`
FromEnv bool `json:"from_env"`
}
require.NoError(t, json.Unmarshal(data, &out))
assert.NotContains(t, out.Value, "preview-secret",
"resolved env value leaked through APIVersion JSON output: %q", out.Value)
assert.Equal(t, "env.MY_AZURE_API_VERSION_SECRET", out.EnvVar,
"env var reference must be preserved so the UI can show it")
assert.True(t, out.FromEnv, "from_env flag must be preserved")
}
// TestProviderConfig_Redacted_DoesNotMaskPlainNonSecretFields verifies that the
// auto-redaction does NOT touch plain (non-env-backed) values. A user-typed
// api_version like "2024-10-21" must show as-is in the UI.
func TestProviderConfig_Redacted_DoesNotMaskPlainNonSecretFields(t *testing.T) {
config := ProviderConfig{
Keys: []schemas.Key{{
ID: "k1",
Name: "test",
Value: schemas.EnvVar{Val: ""},
AzureKeyConfig: &schemas.AzureKeyConfig{
Endpoint: *schemas.NewEnvVar("https://foo.openai.azure.com"),
APIVersion: schemas.NewEnvVar("2024-10-21"),
},
}},
}
redacted := config.Redacted()
require.NotNil(t, redacted)
require.Len(t, redacted.Keys, 1)
require.NotNil(t, redacted.Keys[0].AzureKeyConfig)
require.NotNil(t, redacted.Keys[0].AzureKeyConfig.APIVersion)
data, err := json.Marshal(redacted.Keys[0].AzureKeyConfig.APIVersion)
require.NoError(t, err)
var out struct {
Value string `json:"value"`
FromEnv bool `json:"from_env"`
}
require.NoError(t, json.Unmarshal(data, &out))
assert.Equal(t, "2024-10-21", out.Value,
"plain APIVersion was incorrectly redacted")
assert.False(t, out.FromEnv)
}
// TestProviderConfig_Redacted_PreservesEnvVarReferenceForVertex verifies that
// env-backed Vertex fields appear in the redacted output with the env reference
// intact and the resolved value masked. This is the user-facing fix for the
// "I see resolved env values in the UI" bug.
func TestProviderConfig_Redacted_PreservesEnvVarReferenceForVertex(t *testing.T) {
t.Setenv("MY_VERTEX_PROJECT_ID_SECRET", "super-secret-project-12345")
projectID := schemas.NewEnvVar("env.MY_VERTEX_PROJECT_ID_SECRET")
require.Equal(t, "super-secret-project-12345", projectID.GetValue())
config := ProviderConfig{
Keys: []schemas.Key{{
ID: "k1",
Name: "test",
Value: schemas.EnvVar{Val: ""},
VertexKeyConfig: &schemas.VertexKeyConfig{
ProjectID: *projectID,
Region: *schemas.NewEnvVar("us-central1"),
},
}},
}
redacted := config.Redacted()
data, err := json.Marshal(redacted.Keys[0].VertexKeyConfig.ProjectID)
require.NoError(t, err)
var out struct {
Value string `json:"value"`
EnvVar string `json:"env_var"`
FromEnv bool `json:"from_env"`
}
require.NoError(t, json.Unmarshal(data, &out))
assert.NotContains(t, out.Value, "super-secret-project",
"resolved Vertex ProjectID env value leaked: %q", out.Value)
assert.Equal(t, "env.MY_VERTEX_PROJECT_ID_SECRET", out.EnvVar)
assert.True(t, out.FromEnv)
}
// TestProviderConfig_Redacted_DoesNotMutateOriginal ensures Redacted() and the
// subsequent JSON marshaling do not mutate the original config in memory. The
// inference path reads from the in-memory config and calls GetValue() to build
// outgoing LLM requests; if Redacted() or MarshalJSON were to mutate state, every
// inference request after a UI fetch would silently start using masked values.
func TestProviderConfig_Redacted_DoesNotMutateOriginal(t *testing.T) {
t.Setenv("MY_REAL_KEY", "sk-real-secret-1234567890abcdef")
keyValue := schemas.NewEnvVar("env.MY_REAL_KEY")
require.Equal(t, "sk-real-secret-1234567890abcdef", keyValue.GetValue())
config := ProviderConfig{
Keys: []schemas.Key{{
ID: "k1",
Name: "test",
Value: *keyValue,
}},
}
redacted := config.Redacted()
_, err := json.Marshal(redacted)
require.NoError(t, err)
// Original must still hold the resolved value.
assert.Equal(t, "sk-real-secret-1234567890abcdef", config.Keys[0].Value.GetValue(),
"Redacted() or MarshalJSON mutated the original key Value")
}
// TestProviderConfig_Redacted_FullJSONHasNoLeakedEnvSecrets is a high-level smoke
// test: build a config containing env-backed values across multiple provider types
// and assert that no resolved secret string appears anywhere in the marshaled
// redacted JSON.
func TestProviderConfig_Redacted_FullJSONHasNoLeakedEnvSecrets(t *testing.T) {
t.Setenv("LEAK_TEST_AZURE_ENDPOINT", "https://leaked-azure.example.com")
t.Setenv("LEAK_TEST_AZURE_APIVER", "leaked-api-version-string")
t.Setenv("LEAK_TEST_VERTEX_PROJECT", "leaked-vertex-project-id")
t.Setenv("LEAK_TEST_BEDROCK_ACCESS", "AKIAIOSFODNN7LEAKED1")
t.Setenv("LEAK_TEST_OPENAI_KEY", "sk-leaked-openai-key-1234567890")
config := ProviderConfig{
Keys: []schemas.Key{
{
ID: "openai-k",
Name: "openai",
Value: *schemas.NewEnvVar("env.LEAK_TEST_OPENAI_KEY"),
},
{
ID: "azure-k",
Name: "azure",
Value: schemas.EnvVar{Val: ""},
AzureKeyConfig: &schemas.AzureKeyConfig{
Endpoint: *schemas.NewEnvVar("env.LEAK_TEST_AZURE_ENDPOINT"),
APIVersion: schemas.NewEnvVar("env.LEAK_TEST_AZURE_APIVER"),
},
},
{
ID: "vertex-k",
Name: "vertex",
Value: schemas.EnvVar{Val: ""},
VertexKeyConfig: &schemas.VertexKeyConfig{
ProjectID: *schemas.NewEnvVar("env.LEAK_TEST_VERTEX_PROJECT"),
Region: *schemas.NewEnvVar("us-central1"),
},
},
{
ID: "bedrock-k",
Name: "bedrock",
Value: schemas.EnvVar{Val: ""},
BedrockKeyConfig: &schemas.BedrockKeyConfig{
AccessKey: *schemas.NewEnvVar("env.LEAK_TEST_BEDROCK_ACCESS"),
SecretKey: schemas.EnvVar{Val: ""},
},
},
},
}
redacted := config.Redacted()
data, err := json.Marshal(redacted)
require.NoError(t, err)
jsonStr := string(data)
leakedSecrets := []string{
"https://leaked-azure.example.com",
"leaked-api-version-string",
"leaked-vertex-project-id",
"AKIAIOSFODNN7LEAKED1",
"sk-leaked-openai-key-1234567890",
}
for _, secret := range leakedSecrets {
assert.False(t, strings.Contains(jsonStr, secret),
"resolved env secret %q leaked into redacted JSON output", secret)
}
// And the env var references must be present so the UI can render them.
expectedRefs := []string{
"env.LEAK_TEST_OPENAI_KEY",
"env.LEAK_TEST_AZURE_ENDPOINT",
"env.LEAK_TEST_AZURE_APIVER",
"env.LEAK_TEST_VERTEX_PROJECT",
"env.LEAK_TEST_BEDROCK_ACCESS",
}
for _, ref := range expectedRefs {
assert.True(t, strings.Contains(jsonStr, ref),
"env var reference %q missing from redacted JSON output", ref)
}
}