Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POA-2004] Don't capture payloads of success requests #37

Merged
merged 6 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion trace/backend_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func (c *BackendCollector) queueUpload(w *witnessWithInfo) {
}
}

if !c.sendWitnessPayloads {
if !c.sendWitnessPayloads || !hasErrorResponses(w.witness.GetMethod()) {
// Obfuscate the original value so type inference engine can use it on the
// backend without revealing the actual value.
obfuscate(w.witness.GetMethod())
Expand Down
152 changes: 152 additions & 0 deletions trace/backend_collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,155 @@ func TestFlushExit(t *testing.T) {
b.periodicFlush()
// Test should exit immediately
}

func TestOnlyObfuscateNonErrorResponses(t *testing.T) {
ctrl := gomock.NewController(t)
mockClient := mockrest.NewMockLearnClient(ctrl)
defer ctrl.Finish()

var rec witnessRecorder
mockClient.
EXPECT().
AsyncReportsUpload(gomock.Any(), gomock.Any(), gomock.Any()).
Do(rec.recordAsyncReportsUpload).
AnyTimes().
Return(nil)

streamID := uuid.New()
req := akinet.ParsedNetworkTraffic{
Content: akinet.HTTPRequest{
StreamID: streamID,
Seq: 1203,
Method: "POST",
URL: &url.URL{
Path: "/v1/doggos",
},
Host: "example.com",
Header: map[string][]string{
"Content-Type": {"application/json"},
},
Body: memview.New([]byte(`{"name": "prince", "number": 6119717375543385000}`)),
},
}

resp := akinet.ParsedNetworkTraffic{
Content: akinet.HTTPResponse{
StreamID: streamID,
Seq: 1203,
StatusCode: 200,
Header: map[string][]string{
"Content-Type": {"application/json"},
},
Body: memview.New([]byte(`{"homes": ["burbank, ca", "jeuno, ak", "versailles"]}`)),
},
}

errStreamID := uuid.New()
errReq := akinet.ParsedNetworkTraffic{
Content: akinet.HTTPRequest{
StreamID: errStreamID,
Seq: 1204,
Method: "POST",
URL: &url.URL{
Path: "/v1/doggos",
},
Host: "example.com",
Header: map[string][]string{
"Content-Type": {"application/json"},
},
Body: memview.New([]byte(`{"name": "error", "number": 202410081550}`)),
},
}

errResp := akinet.ParsedNetworkTraffic{
Content: akinet.HTTPResponse{
StreamID: errStreamID,
Seq: 1204,
StatusCode: 404,
Header: map[string][]string{
"Content-Type": {"application/json"},
},
Body: memview.New([]byte(`{"homes": ["error", "happened", "here"]}`)),
},
}

col := NewBackendCollector(fakeSvc, fakeLrn, mockClient, optionals.None[int](), NewPacketCounter(), true, nil)
assert.NoError(t, col.Process(req))
assert.NoError(t, col.Process(resp))
assert.NoError(t, col.Process(errReq))
assert.NoError(t, col.Process(errResp))
assert.NoError(t, col.Close())

expectedWitnesses := []*pb.Witness{
{
Method: &pb.Method{
Id: &pb.MethodID{
ApiType: pb.ApiType_HTTP_REST,
},
Args: map[string]*pb.Data{
"nxnOc5Qy3D4=": newTestBodySpecFromStruct(0, pb.HTTPBody_JSON, "application/json", map[string]*pb.Data{
"name": dataFromPrimitive(spec_util.NewPrimitiveString("")),
"number": dataFromPrimitive(spec_util.NewPrimitiveInt64(0)),
}),
},
Responses: map[string]*pb.Data{
"AyBUQkT0SHU=": newTestBodySpecFromStruct(200, pb.HTTPBody_JSON, "application/json", map[string]*pb.Data{
"homes": dataFromList(
dataFromPrimitive(spec_util.NewPrimitiveString("")),
dataFromPrimitive(spec_util.NewPrimitiveString("")),
dataFromPrimitive(spec_util.NewPrimitiveString("")),
),
}),
},
Meta: &pb.MethodMeta{
Meta: &pb.MethodMeta_Http{
Http: &pb.HTTPMethodMeta{
Method: "POST",
PathTemplate: "/v1/doggos",
Host: "example.com",
Obfuscation: pb.HTTPMethodMeta_ZERO_VALUE,
},
},
},
},
},
{
Method: &pb.Method{
Id: &pb.MethodID{
ApiType: pb.ApiType_HTTP_REST,
},
Args: map[string]*pb.Data{
"MWeG2T99uHI=": newTestBodySpecFromStruct(0, pb.HTTPBody_JSON, "application/json", map[string]*pb.Data{
"name": dataFromPrimitive(spec_util.NewPrimitiveString("error")),
"number": dataFromPrimitive(spec_util.NewPrimitiveInt64(202410081550)),
}),
},
Responses: map[string]*pb.Data{
"T7Jfr4mf1Zs=": newTestBodySpecFromStruct(404, pb.HTTPBody_JSON, "application/json", map[string]*pb.Data{
"homes": dataFromList(
dataFromPrimitive(spec_util.NewPrimitiveString("error")),
dataFromPrimitive(spec_util.NewPrimitiveString("happened")),
dataFromPrimitive(spec_util.NewPrimitiveString("here")),
),
}),
},
Meta: &pb.MethodMeta{
Meta: &pb.MethodMeta_Http{
Http: &pb.HTTPMethodMeta{
Method: "POST",
PathTemplate: "/v1/doggos",
Host: "example.com",
Obfuscation: pb.HTTPMethodMeta_NONE,
},
},
},
},
},
}

for i := range expectedWitnesses {
expected := proto.MarshalTextString(expectedWitnesses[i])
actual := proto.MarshalTextString(rec.witnesses[i])
assert.Equal(t, expected, actual)
}
}
20 changes: 20 additions & 0 deletions trace/util.go
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
package trace

import pb "github.com/akitasoftware/akita-ir/go/api_spec"

// Determines whether a given method has error (4xx or 5xx) response codes. Returns true if the method has at least one response and all response codes are 4xx or 5xx.
// Here method will only have single response object because in agent each witness stores single request-response pair.
func hasErrorResponses(method *pb.Method) bool {
mudit-postman marked this conversation as resolved.
Show resolved Hide resolved
responses := method.GetResponses()
if len(responses) == 0 {
return false
}

for _, response := range responses {
responseCode := response.Meta.GetHttp().GetResponseCode()
if responseCode < 400 {
mudit-postman marked this conversation as resolved.
Show resolved Hide resolved
return false
}
}

return true
}