Skip to content

Commit

Permalink
internal/appsec: refactor dyngo listeners (#2374)
Browse files Browse the repository at this point in the history
Co-authored-by: Dmytro Yurchenko <88330911+ddyurchenko@users.noreply.github.com>
  • Loading branch information
RomainMuller and ddyurchenko authored Dec 1, 2023
1 parent 3a9f7f1 commit 3e15c99
Show file tree
Hide file tree
Showing 40 changed files with 926 additions and 1,215 deletions.
4 changes: 2 additions & 2 deletions appsec/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ 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/appsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/sharedsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
)

Expand Down
2 changes: 1 addition & 1 deletion contrib/gin-gonic/gin/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"net/http"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec"

"github.com/gin-gonic/gin"
)
Expand Down
2 changes: 1 addition & 1 deletion contrib/go-chi/chi.v5/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"net/http"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec"

"github.com/go-chi/chi/v5"
)
Expand Down
2 changes: 1 addition & 1 deletion contrib/go-chi/chi/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"net/http"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec"

"github.com/go-chi/chi"
)
Expand Down
33 changes: 17 additions & 16 deletions contrib/google.golang.org/grpc/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (

"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/dyngo/instrumentation"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/grpcsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/sharedsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/grpcsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/trace"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/trace/grpctrace"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/trace/httptrace"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"

"github.com/DataDog/appsec-internal-go/netip"
Expand All @@ -26,7 +27,7 @@ import (

// UnaryHandler wrapper to use when AppSec is enabled to monitor its execution.
func appsecUnaryHandlerMiddleware(span ddtrace.Span, handler grpc.UnaryHandler) grpc.UnaryHandler {
instrumentation.SetAppSecEnabledTags(span)
trace.SetAppSecEnabledTags(span)
return func(ctx context.Context, req interface{}) (interface{}, error) {
var err error
var blocked bool
Expand All @@ -41,12 +42,12 @@ func appsecUnaryHandlerMiddleware(span ddtrace.Span, handler grpc.UnaryHandler)
defer func() {
events := op.Finish(grpcsec.HandlerOperationRes{})
if blocked {
op.AddTag(instrumentation.BlockedRequestTag, true)
op.AddTag(trace.BlockedRequestTag, true)
}
grpcsec.SetRequestMetadataTags(span, md)
instrumentation.SetTags(span, op.Tags())
grpctrace.SetRequestMetadataTags(span, md)
trace.SetTags(span, op.Tags())
if len(events) > 0 {
grpcsec.SetSecurityEventsTags(span, events)
grpctrace.SetSecurityEventsTags(span, events)
}
}()

Expand All @@ -64,14 +65,14 @@ func appsecUnaryHandlerMiddleware(span ddtrace.Span, handler grpc.UnaryHandler)

// StreamHandler wrapper to use when AppSec is enabled to monitor its execution.
func appsecStreamHandlerMiddleware(span ddtrace.Span, handler grpc.StreamHandler) grpc.StreamHandler {
instrumentation.SetAppSecEnabledTags(span)
trace.SetAppSecEnabledTags(span)
return func(srv interface{}, stream grpc.ServerStream) error {
var err error
var blocked bool
ctx := stream.Context()
md, _ := metadata.FromIncomingContext(ctx)
clientIP := setClientIP(ctx, span, md)
grpcsec.SetRequestMetadataTags(span, md)
grpctrace.SetRequestMetadataTags(span, md)

ctx, op := grpcsec.StartHandlerOperation(ctx, grpcsec.HandlerOperationArgs{Metadata: md, ClientIP: clientIP}, nil, dyngo.NewDataListener(func(a *sharedsec.Action) {
code, e := a.GRPC()(md)
Expand All @@ -86,11 +87,11 @@ func appsecStreamHandlerMiddleware(span ddtrace.Span, handler grpc.StreamHandler
defer func() {
events := op.Finish(grpcsec.HandlerOperationRes{})
if blocked {
op.AddTag(instrumentation.BlockedRequestTag, true)
op.AddTag(trace.BlockedRequestTag, true)
}
instrumentation.SetTags(span, op.Tags())
trace.SetTags(span, op.Tags())
if len(events) > 0 {
grpcsec.SetSecurityEventsTags(span, events)
grpctrace.SetSecurityEventsTags(span, events)
}
}()

Expand Down Expand Up @@ -131,10 +132,10 @@ func setClientIP(ctx context.Context, span ddtrace.Span, md metadata.MD) netip.A
if p, ok := peer.FromContext(ctx); ok {
remoteAddr = p.Addr.String()
}
ipTags, clientIP := httpsec.ClientIPTags(md, false, remoteAddr)
ipTags, clientIP := httptrace.ClientIPTags(md, false, remoteAddr)
log.Debug("appsec: http client ip detection returned `%s` given the http headers `%v`", clientIP, md)
if len(ipTags) > 0 {
instrumentation.SetStringTags(span, ipTags)
trace.SetTags(span, ipTags)
}
return clientIP
}
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/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/trace/httptrace"
"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, _ = httpsec.ClientIPTags(r.Header, true, r.RemoteAddr)
ipTags, _ = httptrace.ClientIPTags(r.Header, true, r.RemoteAddr)
}
nopts := make([]ddtrace.StartSpanOption, 0, len(opts)+1+len(ipTags))
nopts = append(nopts,
Expand Down
2 changes: 1 addition & 1 deletion contrib/labstack/echo.v4/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"net/http"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec"

"github.com/labstack/echo/v4"
)
Expand Down
2 changes: 1 addition & 1 deletion contrib/net/http/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,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/appsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/instrumentation/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec"
"gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry"
)

Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.19
require (
cloud.google.com/go/pubsub v1.33.0
github.com/99designs/gqlgen v0.17.36
github.com/DataDog/appsec-internal-go v1.0.2
github.com/DataDog/appsec-internal-go v1.1.0
github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0
github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1
github.com/DataDog/datadog-go/v5 v5.3.0
Expand Down Expand Up @@ -112,6 +112,8 @@ require (
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.2 // indirect
github.com/DataDog/datadog-agent/pkg/util/log v0.49.0 // indirect
github.com/DataDog/datadog-agent/pkg/util/scrubber v0.49.0 // indirect
github.com/DataDog/go-tuf v1.0.2-0.5.2 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
Expand All @@ -137,6 +139,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
Expand Down
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -624,12 +624,16 @@ github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9s
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/appsec-internal-go v1.0.2 h1:Z+YWPlkQN+324zIk+BzKlPA1/6guKgGmYbON1/xU7gM=
github.com/DataDog/appsec-internal-go v1.0.2/go.mod h1:+Y+4klVWKPOnZx6XESG7QHydOaUGEXyH2j/vSg9JiNM=
github.com/DataDog/appsec-internal-go v1.1.0 h1:bGRfjfUWxgKYtPhjiQw0gG7NiHABEdlBhXFjAsT0gZI=
github.com/DataDog/appsec-internal-go v1.1.0/go.mod h1:PkBD/ntZ2hVq1CxGnewj1FbqaPj7vIa4ooBQfkI8FKQ=
github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0 h1:bUMSNsw1iofWiju9yc1f+kBd33E3hMJtq9GuU602Iy8=
github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0/go.mod h1:HzySONXnAgSmIQfL6gOv9hWprKJkx8CicuXuUbmgWfo=
github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1 h1:5nE6N3JSs2IG3xzMthNFhXfOaXlrsdgqmJ73lndFf8c=
github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1/go.mod h1:Vc+snp0Bey4MrrJyiV2tVxxJb6BmLomPvN1RgAvjGaQ=
github.com/DataDog/datadog-agent/pkg/util/log v0.49.0 h1:cyOCabSFaOKGGkpYv985xkAdUjvhtL2zfjd0pigUJX4=
github.com/DataDog/datadog-agent/pkg/util/log v0.49.0/go.mod h1:h0DfsKCkiQYZzVKCpODobZia0OkHAGN98sTSlqoA7so=
github.com/DataDog/datadog-agent/pkg/util/scrubber v0.49.0 h1:bYkTMqlKZMHaoDJ8oy8WWh3hklh5xzaV9tyQgofktb0=
github.com/DataDog/datadog-agent/pkg/util/scrubber v0.49.0/go.mod h1:EOGgNrSPskIxY3+KgCl+yEggMjrGqrA2oL5va+/p2jM=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/datadog-go/v5 v5.3.0 h1:2q2qjFOb3RwAZNU+ez27ZVDwErJv5/VpbBPprz7Z+s8=
github.com/DataDog/datadog-go/v5 v5.3.0/go.mod h1:XRDJk1pTc00gm+ZDiBKsjh7oOOtJfYfglVCmFb8C2+Q=
Expand Down Expand Up @@ -845,6 +849,8 @@ github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs=
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo=
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
Expand Down
8 changes: 4 additions & 4 deletions internal/appsec/appsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"fmt"
"sync"

"github.com/DataDog/appsec-internal-go/limiter"
waf "github.com/DataDog/go-libddwaf/v2"
"gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"

waf "github.com/DataDog/go-libddwaf/v2"
)

// Enabled returns true when AppSec is up and running. Meaning that the appsec build tag is enabled, the env var
Expand Down Expand Up @@ -119,7 +119,7 @@ func setActiveAppSec(a *appsec) {

type appsec struct {
cfg *Config
limiter *TokenTicker
limiter *limiter.TokenTicker
wafHandle *wafHandle
started bool
}
Expand All @@ -144,7 +144,7 @@ func (a *appsec) start() error {
log.Error("appsec: non-critical error while loading libddwaf: %v", err)
}

a.limiter = NewTokenTicker(int64(a.cfg.traceRateLimit), int64(a.cfg.traceRateLimit))
a.limiter = limiter.NewTokenTicker(a.cfg.traceRateLimit, a.cfg.traceRateLimit)
a.limiter.Start()
// Register the WAF operation event listener
if err := a.swapWAF(a.cfg.rulesManager.latest); err != nil {
Expand Down
10 changes: 5 additions & 5 deletions internal/appsec/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type Config struct {
// Maximum WAF execution time
wafTimeout time.Duration
// AppSec trace rate limit (traces per second).
traceRateLimit uint
traceRateLimit int64
// Obfuscator configuration parameters
obfuscator ObfuscatorConfig
// rc is the remote configuration client used to receive product configuration updates. Nil if rc is disabled (default)
Expand Down Expand Up @@ -126,22 +126,22 @@ func readWAFTimeoutConfig() (timeout time.Duration) {
return parsed
}

func readRateLimitConfig() (rate uint) {
func readRateLimitConfig() (rate int64) {
rate = defaultTraceRate
value := os.Getenv(traceRateLimitEnvVar)
if value == "" {
return rate
}
parsed, err := strconv.ParseUint(value, 10, 0)
parsed, err := strconv.ParseInt(value, 10, 64)
if err != nil {
logEnvVarParsingError(traceRateLimitEnvVar, value, err, rate)
return
}
if rate == 0 {
if rate <= 0 {
logUnexpectedEnvVarValue(traceRateLimitEnvVar, parsed, "expecting a value strictly greater than 0", rate)
return
}
return uint(parsed)
return parsed
}

func readObfuscatorConfig() ObfuscatorConfig {
Expand Down
Loading

0 comments on commit 3e15c99

Please sign in to comment.