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
20 changes: 20 additions & 0 deletions contrib/gorilla/mux/mux_test.go
Expand Up @@ -384,4 +384,24 @@ 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"))
})
}
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())
}
}
}
8 changes: 5 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,10 @@ 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
if appsecEnabled {
afterMiddleware := useAppSec(c, span)
defer afterMiddleware()
}
err := next(c)
if err != nil {
finishOpts = append(finishOpts, tracer.WithError(err))
Expand Down
20 changes: 20 additions & 0 deletions contrib/labstack/echo.v4/echotrace_test.go
Expand Up @@ -367,5 +367,25 @@ 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"))
})
})
}