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

contrib/{echo,gorilla}: add AppSec response-status test #1177

Merged
merged 8 commits into from Feb 25, 2022
21 changes: 21 additions & 0 deletions contrib/gorilla/mux/mux_test.go
Expand Up @@ -384,4 +384,25 @@ func TestAppSec(t *testing.T) {
require.True(t, strings.Contains(event, "myPathParam2"))
require.True(t, strings.Contains(event, "server.request.path_params"))
})

t.Run("response-status", func(t *testing.T) {
mt := mocktracer.Start()
defer mt.Stop()

req, err := http.NewRequest("POST", srv.URL+"/etc/", nil)
if err != nil {
panic(err)
}
res, err := srv.Client().Do(req)
require.NoError(t, err)
require.Equal(t, 404, res.StatusCode)

finished := mt.FinishedSpans()
require.Len(t, finished, 1)
event := finished[0].Tag("_dd.appsec.json").(string)
require.NotNil(t, event)
require.True(t, strings.Contains(event, "server.response.status"))
require.True(t, strings.Contains(event, "nfd-000-001"))

Hellzy marked this conversation as resolved.
Show resolved Hide resolved
})
}
41 changes: 17 additions & 24 deletions contrib/labstack/echo.v4/appsec.go
Expand Up @@ -14,30 +14,23 @@ import (
"github.com/labstack/echo/v4"
)

func withAppSec(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
req := c.Request()
span, ok := tracer.SpanFromContext(req.Context())
if !ok {
return next(c)
}
httpsec.SetAppSecTags(span)
params := make(map[string]string)
for _, n := range c.ParamNames() {
params[n] = c.Param(n)
}
args := httpsec.MakeHandlerOperationArgs(req, params)
op := httpsec.StartOperation(args, nil)
defer func() {
events := op.Finish(httpsec.HandlerOperationRes{Status: c.Response().Status})
if len(events) > 0 {
remoteIP, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
remoteIP = req.RemoteAddr
}
httpsec.SetSecurityEventTags(span, events, remoteIP, args.Headers, c.Response().Writer.Header())
func useAppSec(c echo.Context, span tracer.Span) func() {
req := c.Request()
httpsec.SetAppSecTags(span)
params := make(map[string]string)
for _, n := range c.ParamNames() {
params[n] = c.Param(n)
}
args := httpsec.MakeHandlerOperationArgs(req, params)
op := httpsec.StartOperation(args, nil)
return func() {
events := op.Finish(httpsec.HandlerOperationRes{Status: c.Response().Status})
if len(events) > 0 {
remoteIP, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
remoteIP = req.RemoteAddr
}
}()
return next(c)
httpsec.SetSecurityEventTags(span, events, remoteIP, args.Headers, c.Response().Writer.Header())
}
}
}
10 changes: 7 additions & 3 deletions contrib/labstack/echo.v4/echotrace.go
Expand Up @@ -20,15 +20,13 @@ import (

// Middleware returns echo middleware which will trace incoming requests.
func Middleware(opts ...Option) echo.MiddlewareFunc {
appsecEnabled := appsec.Enabled()
cfg := new(config)
defaults(cfg)
for _, fn := range opts {
fn(cfg)
}
return func(next echo.HandlerFunc) echo.HandlerFunc {
if appsec.Enabled() {
next = withAppSec(next)
}
return func(c echo.Context) error {
request := c.Request()
resource := request.Method + " " + c.Path()
Expand Down Expand Up @@ -57,6 +55,12 @@ func Middleware(opts ...Option) echo.MiddlewareFunc {
// pass the span through the request context
c.SetRequest(request.WithContext(ctx))
// serve the request to the next middleware

Hellzy marked this conversation as resolved.
Show resolved Hide resolved
if appsecEnabled {
afterMiddleware := useAppSec(c, span)
defer afterMiddleware()
}

Hellzy marked this conversation as resolved.
Show resolved Hide resolved
err := next(c)
if err != nil {
finishOpts = append(finishOpts, tracer.WithError(err))
Expand Down
21 changes: 21 additions & 0 deletions contrib/labstack/echo.v4/echotrace_test.go
Expand Up @@ -367,5 +367,26 @@ func TestAppSec(t *testing.T) {
require.False(t, strings.Contains(event, "myPathParam3"))
require.True(t, strings.Contains(event, "server.request.path_params"))
})

t.Run("response-status", func(t *testing.T) {
mt := mocktracer.Start()
defer mt.Stop()

req, err := http.NewRequest("POST", srv.URL+"/etc/", nil)
if err != nil {
panic(err)
}
res, err := srv.Client().Do(req)
require.NoError(t, err)
require.Equal(t, 404, res.StatusCode)

finished := mt.FinishedSpans()
require.Len(t, finished, 1)
event := finished[0].Tag("_dd.appsec.json").(string)
require.NotNil(t, event)
require.True(t, strings.Contains(event, "server.response.status"))
require.True(t, strings.Contains(event, "nfd-000-001"))

Hellzy marked this conversation as resolved.
Show resolved Hide resolved
})
})
}