diff --git a/contrib/gin-gonic/gin/appsec.go b/contrib/gin-gonic/gin/appsec.go new file mode 100644 index 0000000000..a3a16cf404 --- /dev/null +++ b/contrib/gin-gonic/gin/appsec.go @@ -0,0 +1,39 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package gin + +import ( + "github.com/gin-gonic/gin" + "net" + + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec" +) + +func useAppSec(c *gin.Context) { + req := c.Request + span, ok := tracer.SpanFromContext(req.Context()) + if ok { + httpsec.SetAppSecTags(span) + params := make(map[string]string) + for _, p := range c.Params { + params[p.Key] = p.Value + } + args := httpsec.MakeHandlerOperationArgs(req, params) + op := httpsec.StartOperation(args, nil) + defer func() { + events := op.Finish(httpsec.HandlerOperationRes{Status: c.Writer.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.Writer.Header()) + } + }() + c.Next() + } +} diff --git a/contrib/gin-gonic/gin/gintrace.go b/contrib/gin-gonic/gin/gintrace.go index e1342965b1..2d48b8f238 100644 --- a/contrib/gin-gonic/gin/gintrace.go +++ b/contrib/gin-gonic/gin/gintrace.go @@ -8,6 +8,7 @@ package gin // import "gopkg.in/DataDog/dd-trace-go.v1/contrib/gin-gonic/gin" import ( "fmt" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec" "math" "net/http" "strconv" @@ -53,6 +54,11 @@ func Middleware(service string, opts ...Option) gin.HandlerFunc { // pass the span through the request context c.Request = c.Request.WithContext(ctx) + // Use AppSec if enabled by user + if appsec.Enabled() { + useAppSec(c) + } + // serve the request to the next middleware c.Next()