Skip to content

Commit

Permalink
internal/appsec: fix derivatives serdes on simple types (#2905)
Browse files Browse the repository at this point in the history
Signed-off-by: Eliott Bouhana <[email protected]>
  • Loading branch information
eliottness authored Oct 2, 2024
1 parent 438d47d commit ef90025
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 19 deletions.
35 changes: 23 additions & 12 deletions internal/appsec/emitter/trace/service_entry_span.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ type (

// ServiceEntrySpanTagsBulk is a bulk event that is used to send tags to a service entry span
ServiceEntrySpanTagsBulk struct {
Tags []JSONServiceEntrySpanTag
JSONTags []JSONServiceEntrySpanTag
Tags []JSONServiceEntrySpanTag
SerializableTags []JSONServiceEntrySpanTag
}
)

Expand All @@ -55,19 +55,30 @@ func (op *ServiceEntrySpanOperation) SetTag(key string, value any) {
op.tags[key] = value
}

// SetJSONTag adds the key/value pair to the tags to add to the service entry span. Value will be serialized as JSON.
func (op *ServiceEntrySpanOperation) SetJSONTag(key string, value any) {
// SetSerializableTag adds the key/value pair to the tags to add to the service entry span.
// The value MAY be serialized as JSON if necessary but simple types will not be serialized.
func (op *ServiceEntrySpanOperation) SetSerializableTag(key string, value any) {
op.mu.Lock()
defer op.mu.Unlock()
op.jsonTags[key] = value
op.setSerializableTag(key, value)
}

// SetJSONTags adds the key/value pairs to the tags to add to the service entry span. Values will be serialized as JSON.
func (op *ServiceEntrySpanOperation) SetJSONTags(tags map[string]any) {
// SetSerializableTags adds the key/value pairs to the tags to add to the service entry span.
// Values MAY be serialized as JSON if necessary but simple types will not be serialized.
func (op *ServiceEntrySpanOperation) SetSerializableTags(tags map[string]any) {
op.mu.Lock()
defer op.mu.Unlock()
for k, v := range tags {
op.jsonTags[k] = v
for key, value := range tags {
op.setSerializableTag(key, value)
}
}

func (op *ServiceEntrySpanOperation) setSerializableTag(key string, value any) {
switch value.(type) {
case string, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, bool:
op.tags[key] = value
default:
op.jsonTags[key] = value
}
}

Expand Down Expand Up @@ -96,7 +107,7 @@ func (op *ServiceEntrySpanOperation) OnServiceEntrySpanTagEvent(tag ServiceEntry

// OnJSONServiceEntrySpanTagEvent is a callback that is called when a dyngo.OnData is triggered with a JSONServiceEntrySpanTag event
func (op *ServiceEntrySpanOperation) OnJSONServiceEntrySpanTagEvent(tag JSONServiceEntrySpanTag) {
op.SetJSONTag(tag.Key, tag.Value)
op.SetSerializableTag(tag.Key, tag.Value)
}

// OnServiceEntrySpanTagsBulkEvent is a callback that is called when a dyngo.OnData is triggered with a ServiceEntrySpanTagsBulk event
Expand All @@ -105,8 +116,8 @@ func (op *ServiceEntrySpanOperation) OnServiceEntrySpanTagsBulkEvent(bulk Servic
op.SetTag(v.Key, v.Value)
}

for _, v := range bulk.JSONTags {
op.SetJSONTag(v.Key, v.Value)
for _, v := range bulk.SerializableTags {
op.SetSerializableTag(v.Key, v.Value)
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/appsec/listener/waf/waf.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (waf *Feature) onFinish(op *waf.ContextOperation, _ waf.ContextRes) {
log.Debug("appsec: failed to set event span tags: %v", err)
}

op.SetJSONTags(op.Derivatives())
op.SetSerializableTags(op.Derivatives())
if stacks := op.StackTraces(); len(stacks) > 0 {
op.SetTag(stacktrace.SpanKey, stacktrace.GetSpanValue(stacks...))
}
Expand Down
19 changes: 13 additions & 6 deletions internal/appsec/waf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -967,13 +967,20 @@ func TestAttackerFingerprinting(t *testing.T) {
resp, err := srv.Client().Do(req)
require.NoError(t, err)
defer resp.Body.Close()
spans := mt.FinishedSpans()

require.Len(t, spans, 1)
require.Contains(t, spans[0].Tags(), "_dd.appsec.fp.http.header")
require.Contains(t, spans[0].Tags(), "_dd.appsec.fp.http.endpoint")
require.Contains(t, spans[0].Tags(), "_dd.appsec.fp.http.network")
require.Contains(t, spans[0].Tags(), "_dd.appsec.fp.session")
require.Len(t, mt.FinishedSpans(), 1)

tags := mt.FinishedSpans()[0].Tags()

require.Contains(t, tags, "_dd.appsec.fp.http.header")
require.Contains(t, tags, "_dd.appsec.fp.http.endpoint")
require.Contains(t, tags, "_dd.appsec.fp.http.network")
require.Contains(t, tags, "_dd.appsec.fp.session")

require.Regexp(t, `^hdr-`, tags["_dd.appsec.fp.http.header"])
require.Regexp(t, `^http-`, tags["_dd.appsec.fp.http.endpoint"])
require.Regexp(t, `^ssn-`, tags["_dd.appsec.fp.session"])
require.Regexp(t, `^net-`, tags["_dd.appsec.fp.http.network"])
}

func init() {
Expand Down

0 comments on commit ef90025

Please sign in to comment.