Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Eliott Bouhana <[email protected]>
  • Loading branch information
eliottness committed Sep 13, 2024
1 parent e5b9a43 commit b8a8ed4
Show file tree
Hide file tree
Showing 20 changed files with 234 additions and 379 deletions.
4 changes: 2 additions & 2 deletions contrib/internal/httptrace/httptrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/trace/httptrace"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/namingschema"
)

Expand All @@ -34,7 +34,7 @@ func StartRequestSpan(r *http.Request, opts ...ddtrace.StartSpanOption) (tracer.

var ipTags map[string]string
if cfg.traceClientIP {
ipTags, _ = httptrace.ClientIPTags(r.Header, true, r.RemoteAddr)
ipTags, _ = httpsec.ClientIPTags(r.Header, true, r.RemoteAddr)
}
nopts := make([]ddtrace.StartSpanOption, 0, len(opts)+1+len(ipTags))
nopts = append(nopts,
Expand Down
4 changes: 2 additions & 2 deletions contrib/net/http/roundtripper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/mocktracer"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses"
"gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -687,7 +687,7 @@ func TestAppsec(t *testing.T) {

require.Contains(t, serviceSpan.Tags(), "_dd.appsec.json")
appsecJSON := serviceSpan.Tag("_dd.appsec.json")
require.Contains(t, appsecJSON, httpsec.ServerIoNetURLAddr)
require.Contains(t, appsecJSON, addresses.ServerIoNetURLAddr)

require.Contains(t, serviceSpan.Tags(), "_dd.stack")
require.NotContains(t, serviceSpan.Tags(), "error.message")
Expand Down
50 changes: 0 additions & 50 deletions internal/appsec/_testlib/mockspan.go

This file was deleted.

20 changes: 0 additions & 20 deletions internal/appsec/_testlib/require.go

This file was deleted.

87 changes: 10 additions & 77 deletions internal/appsec/emitter/httpsec/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,8 @@ import (
"net/http"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/types"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/trace"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/trace/httptrace"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
"gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace"

"github.com/DataDog/appsec-internal-go/netip"
)

const monitorBodyErrorLog = `
Expand Down Expand Up @@ -61,89 +52,31 @@ func WrapHandler(handler http.Handler, span ddtrace.Span, pathParams map[string]
opts.ResponseHeaderCopier = defaultWrapHandlerConfig.ResponseHeaderCopier
}

trace.SetAppSecEnabledTags(span)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.Clone()
ipTags, clientIP := httptrace.ClientIPTags(r.Header, true, r.RemoteAddr)
log.Debug("appsec: http client ip detection returned `%s` given the http headers `%v`", clientIP, r.Header)
trace.SetTags(span, ipTags)

var bypassHandler http.Handler
var blocking bool
var stackTrace *stacktrace.Event
args := MakeHandlerOperationArgs(r, clientIP, pathParams)
ctx, op := StartOperation(r.Context(), args, func(op *types.Operation) {
dyngo.OnData(op, func(a *sharedsec.HTTPAction) {
blocking = true
bypassHandler = a.Handler
})
dyngo.OnData(op, func(a *sharedsec.StackTraceAction) {
stackTrace = &a.Event
})
})
op, action, ctx := StartOperation(r.Context(), HandlerOperationArgs{r, pathParams})
r = r.WithContext(ctx)

defer func() {
events := op.Finish(MakeHandlerOperationRes(w, opts.ResponseHeaderCopier))
op.Finish(HandlerOperationRes{w, opts.ResponseHeaderCopier}, span)

// Execute the onBlock functions to make sure blocking works properly
// in case we are instrumenting the Gin framework
if blocking {
op.SetTag(trace.BlockedRequestTag, true)
if action != nil {
for _, f := range opts.OnBlock {
f()
}
}

// Add stacktraces to the span, if any
if stackTrace != nil {
stacktrace.AddToSpan(span, stackTrace)
}

if bypassHandler != nil {
bypassHandler.ServeHTTP(w, r)
}

// Add the request headers span tags out of args.Headers instead of r.Header as it was normalized and some
// extra headers have been added such as the Host header which is removed from the original Go request headers
// map
setRequestHeadersTags(span, args.Headers)
setResponseHeadersTags(span, opts.ResponseHeaderCopier(w))
trace.SetTags(span, op.Tags())
if len(events) > 0 {
httptrace.SetSecurityEventsTags(span, events)
if action.Handler != nil {
action.Handler.ServeHTTP(w, r)
}
}
}()

if bypassHandler != nil {
handler = bypassHandler
bypassHandler = nil
if action != nil && action.Handler != nil {
handler = action.Handler
action.Handler = nil
}

handler.ServeHTTP(w, r)
})
}

// MakeHandlerOperationArgs creates the HandlerOperationArgs value.
func MakeHandlerOperationArgs(r *http.Request, clientIP netip.Addr, pathParams map[string]string) types.HandlerOperationArgs {
cookies := makeCookies(r) // TODO(Julio-Guerra): avoid actively parsing the cookies thanks to dynamic instrumentation
headers := headersRemoveCookies(r.Header)
headers["host"] = []string{r.Host}
return types.HandlerOperationArgs{
Method: r.Method,
RequestURI: r.RequestURI,
Headers: headers,
Cookies: cookies,
Query: r.URL.Query(), // TODO(Julio-Guerra): avoid actively parsing the query values thanks to dynamic instrumentation
PathParams: pathParams,
ClientIP: clientIP,
}
}

// MakeHandlerOperationRes creates the HandlerOperationRes value.
func MakeHandlerOperationRes(w http.ResponseWriter, responseHeadersCopier func(http.ResponseWriter) http.Header) types.HandlerOperationRes {
var status int
if mw, ok := w.(interface{ Status() int }); ok {
status = mw.Status()
}
return types.HandlerOperationRes{Status: status, Headers: headersRemoveCookies(responseHeadersCopier(w))}
}
15 changes: 0 additions & 15 deletions internal/appsec/emitter/httpsec/init.go

This file was deleted.

7 changes: 3 additions & 4 deletions internal/appsec/emitter/httpsec/roundtripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import (

"gopkg.in/DataDog/dd-trace-go.v1/appsec/events"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/types"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
)

var badInputContextOnce sync.Once

func ProtectRoundTrip(ctx context.Context, url string) error {
opArgs := types.RoundTripOperationArgs{
opArgs := RoundTripOperationArgs{
URL: url,
}

Expand All @@ -32,7 +31,7 @@ func ProtectRoundTrip(ctx context.Context, url string) error {
return nil
}

op := &types.RoundTripOperation{
op := &RoundTripOperation{
Operation: dyngo.NewOperation(parent),
}

Expand All @@ -43,7 +42,7 @@ func ProtectRoundTrip(ctx context.Context, url string) error {
})

dyngo.StartOperation(op, opArgs)
dyngo.FinishOperation(op, types.RoundTripOperationRes{})
dyngo.FinishOperation(op, RoundTripOperationRes{})

if err != nil {
log.Debug("appsec: outgoing http request blocked by the WAF on URL: %s", url)
Expand Down
28 changes: 0 additions & 28 deletions internal/appsec/emitter/httpsec/tags.go

This file was deleted.

Loading

0 comments on commit b8a8ed4

Please sign in to comment.