Skip to content

Commit b1aec76

Browse files
dotkasPeterSchafer
andauthored
fix: [CLI-841] redacting extension endpoint of instrumentation payload (#328)
Co-authored-by: Peter Schäfer <[email protected]>
1 parent 6527e99 commit b1aec76

File tree

3 files changed

+216
-66
lines changed

3 files changed

+216
-66
lines changed

pkg/analytics/instrumentation_collector.go

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package analytics
22

33
import (
4+
"encoding/json"
45
"errors"
56
"fmt"
7+
"os/user"
68
"time"
79

10+
"github.com/rs/zerolog"
11+
812
"github.com/snyk/error-catalog-golang-public/snyk_errors"
913

1014
api "github.com/snyk/go-application-framework/internal/api/clients"
@@ -62,6 +66,18 @@ type instrumentationCollectorImpl struct {
6266
extension map[string]interface{}
6367
}
6468

69+
type serializeOptions struct {
70+
logger *zerolog.Logger
71+
}
72+
73+
type serializeOptionFunc func(*serializeOptions)
74+
75+
func WithLogger(logger *zerolog.Logger) serializeOptionFunc {
76+
return func(o *serializeOptions) {
77+
o.logger = logger
78+
}
79+
}
80+
6581
func (ic *instrumentationCollectorImpl) SetUserAgent(ua networking.UserAgentInfo) {
6682
ic.userAgent = ua
6783
}
@@ -121,25 +137,75 @@ func (ic *instrumentationCollectorImpl) AddExtension(key string, value interface
121137
ic.extension[key] = value
122138
}
123139

124-
func GetV2InstrumentationObject(collector InstrumentationCollector) (*api.AnalyticsRequestBody, error) {
140+
func GetV2InstrumentationObject(collector InstrumentationCollector, opt ...serializeOptionFunc) (*api.AnalyticsRequestBody, error) {
125141
t, ok := collector.(*instrumentationCollectorImpl)
126-
if ok {
127-
return t.GetV2InstrumentationObject(), nil
142+
if !ok {
143+
return nil, fmt.Errorf("failed to convert collector")
144+
}
145+
146+
logger := zerolog.Nop()
147+
options := serializeOptions{
148+
logger: &logger,
128149
}
129-
return nil, fmt.Errorf("failed to convert collector")
150+
for _, o := range opt {
151+
o(&options)
152+
}
153+
154+
return t.getV2InstrumentationObject(options.logger), nil
130155
}
131156

132-
func (ic *instrumentationCollectorImpl) GetV2InstrumentationObject() *api.AnalyticsRequestBody {
157+
func (ic *instrumentationCollectorImpl) getV2InstrumentationObject(logger *zerolog.Logger) *api.AnalyticsRequestBody {
133158
a := ic.getV2Attributes()
134159

135160
d := api.AnalyticsData{
136161
Type: ic.instrumentationType,
137162
Attributes: a,
138163
}
139164

140-
return &api.AnalyticsRequestBody{
165+
return ic.sanitizeExtensionData(logger, d)
166+
}
167+
168+
// Since the `extension` attribute in the analytics payload is a value any
169+
// product line potentially can contribute to, we utilize the same sanitation logic
170+
// already in place for the legacy v1 analytics, to ensure the same level of PII protection.
171+
func (ic *instrumentationCollectorImpl) sanitizeExtensionData(logger *zerolog.Logger, d api.AnalyticsData) *api.AnalyticsRequestBody {
172+
extension, err := json.Marshal(d.Attributes.Interaction.Extension)
173+
result := &api.AnalyticsRequestBody{
141174
Data: d,
142175
}
176+
result.Data.Attributes.Interaction.Extension = nil
177+
178+
if err != nil {
179+
logger.Printf("failed to marshal extension, removing extension object from analytics payload: %v", err)
180+
return result
181+
}
182+
183+
var sanitized []byte
184+
sanitized, err = SanitizeValuesByKey(sensitiveFieldNames, sanitizeReplacementString, extension)
185+
if err != nil {
186+
logger.Printf("failed to sanitize extension, removing object from analytics payload as sanitzation was not possible: %v", err)
187+
return result
188+
}
189+
190+
u, err := user.Current()
191+
if err != nil {
192+
logger.Printf("failed to find user information while sanitizing extension payload, removing object from analytics payload as sanitzation was not possible: %v", err)
193+
return result
194+
}
195+
196+
sanitized, err = SanitizeUsername(u.Username, u.HomeDir, sanitizeReplacementString, sanitized)
197+
if err != nil {
198+
logger.Printf("failed to sanitize user information in extension payload, removing object from analytics payload as sanitzation was not possible: %v", err)
199+
return result
200+
}
201+
202+
err = json.Unmarshal(sanitized, &result.Data.Attributes.Interaction.Extension)
203+
if err != nil {
204+
logger.Printf("failed to unmarshal sanitized extension object:: %v", err)
205+
return result
206+
}
207+
208+
return result
143209
}
144210

145211
func (ic *instrumentationCollectorImpl) getV2Attributes() api.AnalyticsAttributes {

0 commit comments

Comments
 (0)