Skip to content

Commit a6642bc

Browse files
Redact app configuration keys
1 parent f278b60 commit a6642bc

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

v2/internal/testcommon/vcr/redact.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package vcr
88
import (
99
"net/http"
1010
"regexp"
11+
"strings"
1112

1213
"github.com/google/uuid"
1314

@@ -141,6 +142,7 @@ func (r *Redactor) HideRecordingData(s string) string {
141142
s = hideKubeConfigs(s)
142143
s = hideKeys(s)
143144
s = hideCustomKeys(s)
145+
s = hideAppConfigurationKeySecrets(s)
144146

145147
return s
146148
}
@@ -213,3 +215,27 @@ func (r *Redactor) HideURLData(s string) string {
213215

214216
return s
215217
}
218+
219+
var appConfigKeySecretMatcher = regexp.MustCompile(`Secret=([A-Za-z0-9]+)`)
220+
221+
// hideAppConfigurationKeySecrets hides App Configuration key secrets
222+
// We can detect the secret in the connection string where it shows up as Secret=REDACTED
223+
// but also need to replace the bare value elsewhere in the body of the string.
224+
func hideAppConfigurationKeySecrets(s string) string {
225+
// Get all the matches first
226+
matches := appConfigKeySecretMatcher.FindAllStringSubmatch(s, -1)
227+
if matches == nil {
228+
return s
229+
}
230+
231+
// Replace each match
232+
for _, match := range matches {
233+
if len(match) > 1 {
234+
secretValue := match[1]
235+
s = strings.ReplaceAll(s, secretValue, "{KEY}")
236+
}
237+
}
238+
239+
return s
240+
241+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright (c) Microsoft Corporation.
3+
Licensed under the MIT license.
4+
*/
5+
6+
package vcr
7+
8+
import (
9+
"testing"
10+
11+
. "github.com/onsi/gomega"
12+
)
13+
14+
func Test_hideAppConfigurationKeySecrets(t *testing.T) {
15+
t.Parallel()
16+
17+
cases := map[string]struct {
18+
input string
19+
expected string
20+
}{
21+
"Empty string": {
22+
input: "",
23+
expected: "",
24+
},
25+
"No secrets": {
26+
input: `{"someKey":"someValue"}`,
27+
expected: `{"someKey":"someValue"}`,
28+
},
29+
"Connection string": {
30+
input: `"Endpoint=https://asotest-confstore-fsrajl.azconfig.io;Id=GmDj;Secret=SECRETVALUEFROMAZURE"`,
31+
expected: `"Endpoint=https://asotest-confstore-fsrajl.azconfig.io;Id=GmDj;Secret={KEY}"`,
32+
},
33+
"Configuration Key": {
34+
input: `{"id":"GmDj","name":"Primary","value":"SECRETVALUEFROMAZURE","connectionString":"Endpoint=https://asotest-confstore-fsrajl.azconfig.io;Id=GmDj;Secret=SECRETVALUEFROMAZURE","lastModified":"2025-11-19T01:22:31+00:00","readOnly":false}`,
35+
expected: `{"id":"GmDj","name":"Primary","value":"{KEY}","connectionString":"Endpoint=https://asotest-confstore-fsrajl.azconfig.io;Id=GmDj;Secret={KEY}","lastModified":"2025-11-19T01:22:31+00:00","readOnly":false}`,
36+
},
37+
}
38+
39+
for name, c := range cases {
40+
t.Run(name, func(t *testing.T) {
41+
t.Parallel()
42+
g := NewGomegaWithT(t)
43+
44+
actual := hideAppConfigurationKeySecrets(c.input)
45+
46+
g.Expect(actual).To(Equal(c.expected))
47+
})
48+
}
49+
}

0 commit comments

Comments
 (0)