Skip to content

Commit

Permalink
feat: Add ClientOptions.SendDefaultPii (#485)
Browse files Browse the repository at this point in the history
  • Loading branch information
cleptric committed Nov 2, 2022
1 parent 5301f85 commit 3bb8296
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,8 +1,11 @@
# Changelog

## Unreleased

- fix: Scope values should not override Event values (#446)
- feat: Extend User inteface by adding Data, Name and Segment (#483)
- feat: Make maximum amount of spans configurable (#460)
- feat: Add ClientOptions.SendDefaultPii #485

## 0.14.0

Expand Down
3 changes: 3 additions & 0 deletions client.go
Expand Up @@ -134,6 +134,9 @@ type ClientOptions struct {
// and if applicable, caught errors type and value.
// If the match is found, then a whole event will be dropped.
IgnoreErrors []string
// If this flag is enabled, certain personally identifiable information (PII) is added by active integrations.
// By default, no such data is sent.
SendDefaultPii bool
// BeforeSend is called before error events are sent to Sentry.
// Use it to mutate the event or return nil to discard the event.
// See EventProcessor if you need to mutate transactions.
Expand Down
1 change: 1 addition & 0 deletions fasthttp/sentryfasthttp_test.go
Expand Up @@ -142,6 +142,7 @@ func TestIntegration(t *testing.T) {

eventsCh := make(chan *sentry.Event, len(tests))
err := sentry.Init(sentry.ClientOptions{
SendDefaultPii: true,
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
eventsCh <- event
return event
Expand Down
1 change: 1 addition & 0 deletions http/sentryhttp_test.go
Expand Up @@ -156,6 +156,7 @@ func TestIntegration(t *testing.T) {

eventsCh := make(chan *sentry.Event, len(tests))
err := sentry.Init(sentry.ClientOptions{
SendDefaultPii: true,
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
eventsCh <- event
return event
Expand Down
51 changes: 37 additions & 14 deletions interfaces.go
Expand Up @@ -28,6 +28,15 @@ const (
LevelFatal Level = "fatal"
)

func getSensitiveHeaders() map[string]bool {
return map[string]bool{
"Authorization": true,
"Cookie": true,
"X-Forwarded-For": true,
"X-Real-Ip": true,
}
}

// SdkInfo contains all metadata about about the SDK being used.
type SdkInfo struct {
Name string `json:"name,omitempty"`
Expand Down Expand Up @@ -156,23 +165,37 @@ func NewRequest(r *http.Request) *Request {
}
url := fmt.Sprintf("%s://%s%s", protocol, r.Host, r.URL.Path)

// We read only the first Cookie header because of the specification:
// https://tools.ietf.org/html/rfc6265#section-5.4
// When the user agent generates an HTTP request, the user agent MUST NOT
// attach more than one Cookie header field.
cookies := r.Header.Get("Cookie")

headers := make(map[string]string, len(r.Header))
for k, v := range r.Header {
headers[k] = strings.Join(v, ",")
}
headers["Host"] = r.Host

var cookies string
var env map[string]string
if addr, port, err := net.SplitHostPort(r.RemoteAddr); err == nil {
env = map[string]string{"REMOTE_ADDR": addr, "REMOTE_PORT": port}
headers := map[string]string{}

if client := CurrentHub().Client(); client != nil {
if client.Options().SendDefaultPii {
// We read only the first Cookie header because of the specification:
// https://tools.ietf.org/html/rfc6265#section-5.4
// When the user agent generates an HTTP request, the user agent MUST NOT
// attach more than one Cookie header field.
cookies = r.Header.Get("Cookie")

for k, v := range r.Header {
headers[k] = strings.Join(v, ",")
}

if addr, port, err := net.SplitHostPort(r.RemoteAddr); err == nil {
env = map[string]string{"REMOTE_ADDR": addr, "REMOTE_PORT": port}
}
}
} else {
sensitiveHeaders := getSensitiveHeaders()
for k, v := range r.Header {
if _, ok := sensitiveHeaders[k]; !ok {
headers[k] = strings.Join(v, ",")
}
}
}

headers["Host"] = r.Host

return &Request{
URL: url,
Method: r.Method,
Expand Down
49 changes: 46 additions & 3 deletions interfaces_test.go
Expand Up @@ -66,16 +66,34 @@ func TestUserMarshalJson(t *testing.T) {
}

func TestNewRequest(t *testing.T) {
currentHub.BindClient(&Client{
options: ClientOptions{
SendDefaultPii: true,
},
})
// Unbind the client afterwards, to not affect other tests
defer currentHub.stackTop().SetClient(nil)

const payload = `{"test_data": true}`
got := NewRequest(httptest.NewRequest("POST", "/test/?q=sentry", strings.NewReader(payload)))
r := httptest.NewRequest("POST", "/test/?q=sentry", strings.NewReader(payload))
r.Header.Add("Authorization", "Bearer 1234567890")
r.Header.Add("Cookie", "foo=bar")
r.Header.Add("X-Forwarded-For", "127.0.0.1")
r.Header.Add("X-Real-Ip", "127.0.0.1")

got := NewRequest(r)
want := &Request{
URL: "http://example.com/test/",
Method: "POST",
Data: "",
QueryString: "q=sentry",
Cookies: "",
Cookies: "foo=bar",
Headers: map[string]string{
"Host": "example.com",
"Authorization": "Bearer 1234567890",
"Cookie": "foo=bar",
"Host": "example.com",
"X-Forwarded-For": "127.0.0.1",
"X-Real-Ip": "127.0.0.1",
},
Env: map[string]string{
"REMOTE_ADDR": "192.0.2.1",
Expand All @@ -87,6 +105,31 @@ func TestNewRequest(t *testing.T) {
}
}

func TestNewRequestWithNoPii(t *testing.T) {
const payload = `{"test_data": true}`
r := httptest.NewRequest("POST", "/test/?q=sentry", strings.NewReader(payload))
r.Header.Add("Authorization", "Bearer 1234567890")
r.Header.Add("Cookie", "foo=bar")
r.Header.Add("X-Forwarded-For", "127.0.0.1")
r.Header.Add("X-Real-Ip", "127.0.0.1")

got := NewRequest(r)
want := &Request{
URL: "http://example.com/test/",
Method: "POST",
Data: "",
QueryString: "q=sentry",
Cookies: "",
Headers: map[string]string{
"Host": "example.com",
},
Env: nil,
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("Request mismatch (-want +got):\n%s", diff)
}
}

func TestEventMarshalJSON(t *testing.T) {
event := NewEvent()
event.Spans = []*Span{{
Expand Down

0 comments on commit 3bb8296

Please sign in to comment.