Skip to content

Commit c5ca73e

Browse files
authored
1 parent 946f6d9 commit c5ca73e

22 files changed

+1289
-175
lines changed

apidump/apidump.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/postmanlabs/postman-insights-agent/apispec"
2424
"github.com/postmanlabs/postman-insights-agent/architecture"
2525
"github.com/postmanlabs/postman-insights-agent/ci"
26+
"github.com/postmanlabs/postman-insights-agent/data_masks"
2627
"github.com/postmanlabs/postman-insights-agent/deployment"
2728
"github.com/postmanlabs/postman-insights-agent/env"
2829
"github.com/postmanlabs/postman-insights-agent/location"
@@ -654,6 +655,11 @@ func (a *apidump) Run() error {
654655
go a.TelemetryWorker(stop)
655656
}
656657

658+
redactor, err := data_masks.NewRedactor(a.backendSvc, a.learnClient)
659+
if err != nil {
660+
return errors.Wrapf(err, "unable to instantiate redactor for %s", a.backendSvc)
661+
}
662+
657663
// Start collecting -- set up one or two collectors per interface, depending on whether filters are in use
658664
numCollectors := 0
659665
for _, filterState := range []filterState{matchedFilter, notMatchedFilter} {
@@ -690,7 +696,17 @@ func (a *apidump) Run() error {
690696
} else {
691697
var backendCollector trace.Collector
692698
if args.Out.AkitaURI != nil {
693-
backendCollector = trace.NewBackendCollector(a.backendSvc, backendLrn, a.learnClient, optionals.Some(a.MaxWitnessSize_bytes), summary, args.ReproMode, args.Plugins)
699+
backendCollector = trace.NewBackendCollector(
700+
a.backendSvc,
701+
backendLrn,
702+
a.learnClient,
703+
redactor,
704+
optionals.Some(a.MaxWitnessSize_bytes),
705+
summary,
706+
args.ReproMode,
707+
args.Plugins,
708+
)
709+
694710
collector = backendCollector
695711
} else {
696712
return errors.Errorf("invalid output location")

trace/obfuscation_config.go renamed to data_masks/redaction_config.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package trace
1+
package data_masks
22

33
import (
44
"embed"
@@ -11,20 +11,20 @@ import (
1111
)
1212

1313
var (
14-
//go:embed obfuscation_config.yaml
15-
obfucationFileFS embed.FS
14+
//go:embed redaction_config.yaml
15+
redactionFileFS embed.FS
1616

1717
onceConfigLoad sync.Once
18-
config obfuscationConfig
18+
config redactionConfig
1919
configErr error = nil
2020
)
2121

22-
type obfuscationConfig struct {
22+
type redactionConfig struct {
2323
SensitiveKeys []string `yaml:"sensitive_keys"`
2424
SensitiveValueRegexes []string `yaml:"sensitive_value_regexes"`
2525
}
2626

27-
func (c *obfuscationConfig) sanitizeConfigData() bool {
27+
func (c *redactionConfig) sanitizeConfigData() bool {
2828

2929
// Convert all the keys to lower case and remove duplicates
3030
keys := sets.NewSet[string]()
@@ -36,9 +36,9 @@ func (c *obfuscationConfig) sanitizeConfigData() bool {
3636
return false
3737
}
3838

39-
func loadConfigFromFile() (*obfuscationConfig, error) {
39+
func loadConfigFromFile() (*redactionConfig, error) {
4040
onceConfigLoad.Do(func() {
41-
data, err := obfucationFileFS.Open("obfuscation_config.yaml")
41+
data, err := redactionFileFS.Open("redaction_config.yaml")
4242
if err != nil {
4343
configErr = errors.Wrap(err, "failed to open config file")
4444
}
File renamed without changes.

data_masks/redaction_test.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package data_masks
2+
3+
import (
4+
"path/filepath"
5+
"regexp"
6+
"testing"
7+
8+
"github.com/akitasoftware/akita-ir/go/api_spec"
9+
"github.com/akitasoftware/akita-libs/akid"
10+
kgxapi "github.com/akitasoftware/akita-libs/api_schema"
11+
"github.com/akitasoftware/akita-libs/test"
12+
"github.com/akitasoftware/go-utils/optionals"
13+
"github.com/golang/mock/gomock"
14+
"github.com/golang/protobuf/proto"
15+
"github.com/google/go-cmp/cmp"
16+
"github.com/google/go-cmp/cmp/cmpopts"
17+
mockrest "github.com/postmanlabs/postman-insights-agent/rest/mock"
18+
"github.com/stretchr/testify/assert"
19+
)
20+
21+
var cmpOptions = []cmp.Option{
22+
cmp.Comparer(proto.Equal),
23+
cmpopts.SortSlices(sortMethod),
24+
cmpopts.SortSlices(sortWitness),
25+
}
26+
27+
func sortMethod(m1, m2 *api_spec.Method) bool {
28+
return proto.MarshalTextString(m1) < proto.MarshalTextString(m2)
29+
}
30+
31+
func sortWitness(m1, m2 *api_spec.Witness) bool {
32+
return proto.MarshalTextString(m1) < proto.MarshalTextString(m2)
33+
}
34+
35+
func TestRedaction(t *testing.T) {
36+
testCases := map[string]struct {
37+
agentConfig optionals.Optional[*kgxapi.FieldRedactionConfig]
38+
inputFile string
39+
expectedFile string
40+
}{
41+
// Expect values with 16-character identifiers to remain unchanged.
42+
"16-character identifier": {
43+
inputFile: "002-witness.pb.txt",
44+
expectedFile: "002-witness.pb.txt",
45+
},
46+
47+
"default redaction rules": {
48+
inputFile: "003-witness.pb.txt",
49+
expectedFile: "003-expected-default-redaction.pb.txt",
50+
},
51+
52+
"agent config: redact by name": {
53+
agentConfig: optionals.Some(&kgxapi.FieldRedactionConfig{
54+
FieldNames: []string{"by-name"},
55+
}),
56+
inputFile: "003-witness.pb.txt",
57+
expectedFile: "003-expected-redact-by-name.pb.txt",
58+
},
59+
60+
"agent config: redact by name regexp": {
61+
agentConfig: optionals.Some(&kgxapi.FieldRedactionConfig{
62+
FieldNameRegexps: []*regexp.Regexp{regexp.MustCompile("nam.*xp$")},
63+
}),
64+
inputFile: "003-witness.pb.txt",
65+
expectedFile: "003-expected-redact-by-name-regexp.pb.txt",
66+
},
67+
68+
"agent config: redact by name and by name regexp": {
69+
agentConfig: optionals.Some(&kgxapi.FieldRedactionConfig{
70+
FieldNames: []string{"by-name"},
71+
FieldNameRegexps: []*regexp.Regexp{regexp.MustCompile("nam.*xp$")},
72+
}),
73+
inputFile: "003-witness.pb.txt",
74+
expectedFile: "003-expected-redact-by-name-and-by-name-regexp.pb.txt",
75+
},
76+
}
77+
78+
for testName, testCase := range testCases {
79+
func() {
80+
ctrl := gomock.NewController(t)
81+
mockClient := mockrest.NewMockLearnClient(ctrl)
82+
defer ctrl.Finish()
83+
84+
agentConfig := kgxapi.NewServiceAgentConfig()
85+
if fieldsToRedact, exists := testCase.agentConfig.Get(); exists {
86+
agentConfig.FieldsToRedact = fieldsToRedact
87+
}
88+
89+
mockClient.
90+
EXPECT().
91+
GetDynamicAgentConfigForService(gomock.Any(), gomock.Any()).
92+
AnyTimes().
93+
Return(agentConfig, nil)
94+
95+
o, err := NewRedactor(akid.GenerateServiceID(), mockClient)
96+
assert.NoError(t, err)
97+
98+
testWitness := test.LoadWitnessFromFileOrDie(filepath.Join("testdata", testCase.inputFile))
99+
expectedWitness := test.LoadWitnessFromFileOrDie(filepath.Join("testdata", testCase.expectedFile))
100+
101+
o.RedactSensitiveData(testWitness.Method)
102+
103+
if diff := cmp.Diff(expectedWitness, testWitness, cmpOptions...); diff != "" {
104+
t.Errorf("found unexpected diff in test case %q:\n%s", testName, diff)
105+
}
106+
}()
107+
}
108+
}
109+
110+
func BenchmarkRedaction(b *testing.B) {
111+
ctrl := gomock.NewController(b)
112+
mockClient := mockrest.NewMockLearnClient(ctrl)
113+
defer ctrl.Finish()
114+
115+
mockClient.
116+
EXPECT().
117+
GetDynamicAgentConfigForService(gomock.Any(), gomock.Any()).
118+
AnyTimes().
119+
Return(kgxapi.NewServiceAgentConfig(), nil)
120+
121+
o, err := NewRedactor(akid.GenerateServiceID(), mockClient)
122+
assert.NoError(b, err)
123+
124+
testWitness := test.LoadWitnessFromFileOrDie(filepath.Join("testdata", "001-witness.pb.txt"))
125+
126+
b.ResetTimer()
127+
128+
for i := 0; i < b.N; i++ {
129+
o.RedactSensitiveData(testWitness.Method)
130+
}
131+
}

0 commit comments

Comments
 (0)