package config import ( "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestEnvSecretsProvider_GetSecret(t *testing.T) { os.Setenv("TEST_SECRET", "my-secret-value") defer os.Unsetenv("TEST_SECRET") provider := NewEnvSecretsProvider([]string{"TEST_SECRET"}) secret, err := provider.GetSecret("TEST_SECRET") require.NoError(t, err) assert.Equal(t, "my-secret-value", secret) _, err = provider.GetSecret("NONEXISTENT") assert.Error(t, err) assert.Contains(t, err.Error(), "not found") } func TestEnvSecretsProvider_IsSecret(t *testing.T) { provider := NewEnvSecretsProvider([]string{"SECRET_KEY", "ANOTHER_SECRET"}) assert.True(t, provider.IsSecret("SECRET_KEY")) assert.True(t, provider.IsSecret("ANOTHER_SECRET")) assert.False(t, provider.IsSecret("NOT_A_SECRET")) assert.False(t, provider.IsSecret("")) } func TestEnvSecretsProvider_GetSecret_Empty(t *testing.T) { // S'assurer que la variable n'existe pas os.Unsetenv("MISSING_SECRET") defer os.Unsetenv("MISSING_SECRET") provider := NewEnvSecretsProvider([]string{"MISSING_SECRET"}) _, err := provider.GetSecret("MISSING_SECRET") assert.Error(t, err) assert.Contains(t, err.Error(), "not found") } func TestMaskSecret(t *testing.T) { tests := []struct { name string secret string expected string }{ {"long secret", "my-super-secret-key-12345", "my-s****2345"}, // length 23, 4 prefix, 4 suffix {"short secret", "short", "****"}, // length 5, <= 8 {"empty secret", "", ""}, // length 0, empty {"very short", "ab", "****"}, // length 2, <= 8 {"exactly 8 chars", "12345678", "****"}, // length 8, <= 8 {"9 chars", "123456789", "1234****6789"}, // length 9, 4 prefix, 4 suffix {"exactly 10 chars", "1234567890", "1234****7890"}, // length 10, 4 prefix, 4 suffix {"very long secret", "this-is-a-very-long-secret-key-that-needs-masking", "this****king"}, // length 45, 4 prefix, 4 suffix } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := MaskSecret(tt.secret) assert.Equal(t, tt.expected, result) }) } } func TestMaskConfigValue(t *testing.T) { provider := NewEnvSecretsProvider([]string{"JWT_SECRET", "DB_PASSWORD"}) tests := []struct { name string key string value string provider SecretsProvider expectedMasked bool }{ { name: "secret key should be masked", key: "JWT_SECRET", value: "my-secret-key-12345", provider: provider, expectedMasked: true, }, { name: "non-secret key should not be masked", key: "APP_PORT", value: "8080", provider: provider, expectedMasked: false, }, { name: "nil provider should not mask", key: "JWT_SECRET", value: "my-secret-key-12345", provider: nil, expectedMasked: false, }, { name: "empty value should remain empty", key: "JWT_SECRET", value: "", provider: provider, expectedMasked: false, // MaskSecret retourne "" pour empty, donc pas de changement visible }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := MaskConfigValue(tt.key, tt.value, tt.provider) if tt.expectedMasked { assert.NotEqual(t, tt.value, result, "Value should be masked") if tt.value != "" { assert.Contains(t, result, "****") } } else { assert.Equal(t, tt.value, result, "Value should not be masked") } }) } } func TestDefaultSecretKeys(t *testing.T) { keys := DefaultSecretKeys() assert.NotEmpty(t, keys) // Vérifier que les clés communes sont présentes expectedKeys := []string{ "JWT_SECRET", "DB_PASSWORD", "REDIS_PASSWORD", "AWS_SECRET_ACCESS_KEY", "STRIPE_SECRET_KEY", } for _, expectedKey := range expectedKeys { assert.Contains(t, keys, expectedKey, "DefaultSecretKeys should contain %s", expectedKey) } // Vérifier qu'il n'y a pas de doublons seen := make(map[string]bool) for _, key := range keys { assert.False(t, seen[key], "Duplicate key found: %s", key) seen[key] = true } } func TestNewEnvSecretsProvider(t *testing.T) { keys := []string{"KEY1", "KEY2", "KEY3"} provider := NewEnvSecretsProvider(keys) assert.NotNil(t, provider) assert.True(t, provider.IsSecret("KEY1")) assert.True(t, provider.IsSecret("KEY2")) assert.True(t, provider.IsSecret("KEY3")) assert.False(t, provider.IsSecret("KEY4")) } func TestEnvSecretsProvider_EmptyKeys(t *testing.T) { provider := NewEnvSecretsProvider([]string{}) assert.NotNil(t, provider) assert.False(t, provider.IsSecret("ANY_KEY")) _, err := provider.GetSecret("ANY_KEY") assert.Error(t, err) } func TestMaskSecret_BoundaryCases(t *testing.T) { // Test cas limites tests := []struct { name string secret string expected string }{ {"nil equivalent (empty)", "", ""}, {"1 char", "a", "****"}, {"4 chars", "abcd", "****"}, {"5 chars", "abcde", "****"}, {"8 chars", "12345678", "****"}, {"9 chars (threshold)", "123456789", "1234****6789"}, // Adjusted expected {"exactly 10 chars", "1234567890", "1234****7890"}, // Adjusted expected } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := MaskSecret(tt.secret) assert.Equal(t, tt.expected, result) }) } } func TestEnvSecretsProvider_MultipleSecrets(t *testing.T) { os.Setenv("SECRET1", "value1") os.Setenv("SECRET2", "value2") os.Setenv("SECRET3", "value3") defer func() { os.Unsetenv("SECRET1") os.Unsetenv("SECRET2") os.Unsetenv("SECRET3") }() provider := NewEnvSecretsProvider([]string{"SECRET1", "SECRET2", "SECRET3"}) secret1, err := provider.GetSecret("SECRET1") require.NoError(t, err) assert.Equal(t, "value1", secret1) secret2, err := provider.GetSecret("SECRET2") require.NoError(t, err) assert.Equal(t, "value2", secret2) secret3, err := provider.GetSecret("SECRET3") require.NoError(t, err) assert.Equal(t, "value3", secret3) } func TestMaskConfigValue_AllCases(t *testing.T) { provider := NewEnvSecretsProvider([]string{"SECRET_KEY"}) // Test avec différents types de valeurs testCases := []struct { key string value string expected string }{ {"SECRET_KEY", "long-secret-value-12345", "long****2345"}, // Adjusted expected {"SECRET_KEY", "short", "****"}, {"SECRET_KEY", "", ""}, {"PUBLIC_KEY", "public-value", "public-value"}, // Ne devrait pas être masqué } for _, tc := range testCases { t.Run(tc.key+"_"+tc.value, func(t *testing.T) { result := MaskConfigValue(tc.key, tc.value, provider) assert.Equal(t, tc.expected, result) }) } }