From 8476b0f23c49b8a4a5a250b507a293dfe309453f Mon Sep 17 00:00:00 2001 From: aayush-ap Date: Wed, 28 Jun 2023 10:22:02 +0530 Subject: [PATCH 1/7] Initial changes for detect all api endpoints. --- v3/integrations/nrecho-v3/nrecho.go | 11 ++++- v3/integrations/nrecho-v4/nrecho.go | 9 +++- v3/integrations/nrgin/nrgin.go | 8 ++++ v3/integrations/nrgorilla/nrgorilla.go | 19 +++++++++ v3/integrations/nrhttprouter/nrhttprouter.go | 45 ++++++++++---------- v3/newrelic/instrumentation.go | 12 +++--- v3/newrelic/secure_agent.go | 10 +---- 7 files changed, 75 insertions(+), 39 deletions(-) diff --git a/v3/integrations/nrecho-v3/nrecho.go b/v3/integrations/nrecho-v3/nrecho.go index ad5f862b8..4b46bbf50 100644 --- a/v3/integrations/nrecho-v3/nrecho.go +++ b/v3/integrations/nrecho-v3/nrecho.go @@ -51,9 +51,7 @@ func transactionName(c echo.Context) string { // e := echo.New() // // Add the nrecho middleware before other middlewares or routes: // e.Use(nrecho.Middleware(app)) -// func Middleware(app *newrelic.Application) func(echo.HandlerFunc) echo.HandlerFunc { - if nil == app { return func(next echo.HandlerFunc) echo.HandlerFunc { return next @@ -93,3 +91,12 @@ func Middleware(app *newrelic.Application) func(echo.HandlerFunc) echo.HandlerFu } } } + +func WrapRouter(engine *echo.Echo) { + if engine != nil { + router := engine.Routes() + for _, r := range router { + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method) + } + } +} diff --git a/v3/integrations/nrecho-v4/nrecho.go b/v3/integrations/nrecho-v4/nrecho.go index 4c3b8cd18..c6e1511fb 100644 --- a/v3/integrations/nrecho-v4/nrecho.go +++ b/v3/integrations/nrecho-v4/nrecho.go @@ -71,7 +71,6 @@ func WithSkipper(skipper Skipper) ConfigOption { // e := echo.New() // // Add the nrecho middleware before other middlewares or routes: // e.Use(nrecho.MiddlewareWithConfig(nrecho.Config{App: app})) -// func Middleware(app *newrelic.Application, opts ...ConfigOption) func(echo.HandlerFunc) echo.HandlerFunc { if app == nil { return func(next echo.HandlerFunc) echo.HandlerFunc { @@ -131,3 +130,11 @@ func Middleware(app *newrelic.Application, opts ...ConfigOption) func(echo.Handl } } } +func WrapRouter(engine *echo.Echo) { + if engine != nil { + router := engine.Routes() + for _, r := range router { + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method) + } + } +} diff --git a/v3/integrations/nrgin/nrgin.go b/v3/integrations/nrgin/nrgin.go index 88ef11b24..954a752da 100644 --- a/v3/integrations/nrgin/nrgin.go +++ b/v3/integrations/nrgin/nrgin.go @@ -144,6 +144,14 @@ func MiddlewareHandlerTxnNames(app *newrelic.Application) gin.HandlerFunc { return middleware(app, false) } +func WrapRouter(engine *gin.Engine) { + if engine != nil { + router := engine.Routes() + for _, r := range router { + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method) + } + } +} func middleware(app *newrelic.Application, useNewNames bool) gin.HandlerFunc { return func(c *gin.Context) { if app != nil { diff --git a/v3/integrations/nrgorilla/nrgorilla.go b/v3/integrations/nrgorilla/nrgorilla.go index dd2088a25..872161e21 100644 --- a/v3/integrations/nrgorilla/nrgorilla.go +++ b/v3/integrations/nrgorilla/nrgorilla.go @@ -111,3 +111,22 @@ func Middleware(app *newrelic.Application) mux.MiddlewareFunc { }) } } +func WrapRouter(router *mux.Router) { + if router != nil { + router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { + path, err1 := route.GetPathTemplate() + if err1 != nil { + return nil + } + methods, _ := route.GetMethods() + if len(methods) == 0 { + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, "*") + } else { + for _, method := range methods { + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method) + } + } + return nil + }) + } +} diff --git a/v3/integrations/nrhttprouter/nrhttprouter.go b/v3/integrations/nrhttprouter/nrhttprouter.go index 75cb73ff4..66854ab96 100644 --- a/v3/integrations/nrhttprouter/nrhttprouter.go +++ b/v3/integrations/nrhttprouter/nrhttprouter.go @@ -8,33 +8,33 @@ // httprouter.Router. Use an *nrhttprouter.Router in place of your // *httprouter.Router. Example: // -// package main +// package main // -// import ( -// "fmt" -// "net/http" -// "os" +// import ( +// "fmt" +// "net/http" +// "os" // -// "github.com/julienschmidt/httprouter" -// newrelic "github.com/newrelic/go-agent/v3/newrelic" -// "github.com/newrelic/go-agent/v3/integrations/nrhttprouter" -// ) +// "github.com/julienschmidt/httprouter" +// newrelic "github.com/newrelic/go-agent/v3/newrelic" +// "github.com/newrelic/go-agent/v3/integrations/nrhttprouter" +// ) // -// func main() { -// cfg := newrelic.NewConfig("httprouter App", os.Getenv("NEW_RELIC_LICENSE_KEY")) -// app, _ := newrelic.NewApplication(cfg) +// func main() { +// cfg := newrelic.NewConfig("httprouter App", os.Getenv("NEW_RELIC_LICENSE_KEY")) +// app, _ := newrelic.NewApplication(cfg) // -// // Create the Router replacement: -// router := nrhttprouter.New(app) +// // Create the Router replacement: +// router := nrhttprouter.New(app) // -// router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { -// w.Write([]byte("welcome\n")) -// }) -// router.GET("/hello/:name", (w http.ResponseWriter, r *http.Request, ps httprouter.Params) { -// w.Write([]byte(fmt.Sprintf("hello %s\n", ps.ByName("name")))) -// }) -// http.ListenAndServe(":8000", router) -// } +// router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { +// w.Write([]byte("welcome\n")) +// }) +// router.GET("/hello/:name", (w http.ResponseWriter, r *http.Request, ps httprouter.Params) { +// w.Write([]byte(fmt.Sprintf("hello %s\n", ps.ByName("name")))) +// }) +// http.ListenAndServe(":8000", router) +// } // // Runnable example: https://github.com/newrelic/go-agent/tree/master/v3/integrations/nrhttprouter/example/main.go package nrhttprouter @@ -84,6 +84,7 @@ func (r *Router) handle(method string, path string, original httprouter.Handle) } } r.Router.Handle(method, path, handle) + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method) } // DELETE replaces httprouter.Router.DELETE. diff --git a/v3/newrelic/instrumentation.go b/v3/newrelic/instrumentation.go index a118aef9f..f31c16b31 100644 --- a/v3/newrelic/instrumentation.go +++ b/v3/newrelic/instrumentation.go @@ -12,11 +12,11 @@ import ( // WrapHandle instruments http.Handler handlers with Transactions. To // instrument this code: // -// http.Handle("/foo", myHandler) +// http.Handle("/foo", myHandler) // // Perform this replacement: // -// http.Handle(newrelic.WrapHandle(app, "/foo", myHandler)) +// http.Handle(newrelic.WrapHandle(app, "/foo", myHandler)) // // WrapHandle adds the Transaction to the request's context. Access it using // FromContext to add attributes, create segments, or notice errors: @@ -41,7 +41,7 @@ func WrapHandle(app *Application, pattern string, handler http.Handler, options // (but only if we know we're collecting CLM for this transaction and the user didn't already // specify a different code location explicitly). cache := NewCachedCodeLocation() - + secureAgent.SendEvent("API_END_POINTS", pattern, "*") return pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var tOptions *traceOptSet var txnOptionList []TraceOption @@ -111,15 +111,15 @@ func WrapHandleFunc(app *Application, pattern string, handler func(http.Response return p, func(w http.ResponseWriter, r *http.Request) { h.ServeHTTP(w, r) } } -// // WrapListen wraps an HTTP endpoint reference passed to functions like http.ListenAndServe, // which causes security scanning to be done for that incoming endpoint when vulnerability // scanning is enabled. It returns the endpoint string, so you can replace a call like // -// http.ListenAndServe(":8000", nil) +// http.ListenAndServe(":8000", nil) +// // with -// http.ListenAndServe(newrelic.WrapListen(":8000"), nil) // +// http.ListenAndServe(newrelic.WrapListen(":8000"), nil) func WrapListen(endpoint string) string { secureAgent.SendEvent("APP_INFO", endpoint) return endpoint diff --git a/v3/newrelic/secure_agent.go b/v3/newrelic/secure_agent.go index 0b6225185..f58724c31 100644 --- a/v3/newrelic/secure_agent.go +++ b/v3/newrelic/secure_agent.go @@ -4,18 +4,15 @@ import ( "net/http" ) -// // secureAgent is a global interface point for the nrsecureagent's hooks into the go agent. // The default value for this is a noOpSecurityAgent value, which has null definitions for // the methods. The Go compiler is expected to optimize away all the securityAgent method // calls in this case, effectively removing the hooks from the running agent. // // If the nrsecureagent integration was initialized, it will register a real securityAgent -// value in the securityAgent varialble instead, thus "activating" the hooks. -// +// value in the securityAgent variable instead, thus "activating" the hooks. var secureAgent securityAgent = noOpSecurityAgent{} -// // GetSecurityAgentInterface returns the securityAgent value // which provides the working interface to the installed // security agent (or to a no-op interface if none were @@ -23,10 +20,9 @@ var secureAgent securityAgent = noOpSecurityAgent{} // // Packages which need to make calls to secureAgent's methods // may obtain the secureAgent value by calling this function. -// This avoids exposing the variable itself so it's not +// This avoids exposing the variable itself, so it's not // writable externally and also sets up for the future if this // ends up not being a global variable later. -// func GetSecurityAgentInterface() securityAgent { return secureAgent } @@ -86,11 +82,9 @@ func (t noOpSecurityAgent) DistributedTraceHeaders(hdrs *http.Request, secureAge func (t noOpSecurityAgent) SendExitEvent(secureAgentevent any, err error) { } -// // IsSecurityAgentPresent returns true if there's an actual security agent hooked in to the // Go APM agent, whether or not it's enabled or operating in any particular mode. It returns // false only if the hook-in interface for those functions is a No-Op will null functionality. -// func IsSecurityAgentPresent() bool { _, isNoOp := secureAgent.(noOpSecurityAgent) return !isNoOp From d71c0a1d76195344f813448e77e11dc4c02610bb Mon Sep 17 00:00:00 2001 From: Aayush garg Date: Wed, 7 Feb 2024 21:55:27 +0530 Subject: [PATCH 2/7] Added api detection for fasthttp --- v3/integrations/nrfasthttp/instrumentation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v3/integrations/nrfasthttp/instrumentation.go b/v3/integrations/nrfasthttp/instrumentation.go index abefb8460..41d621edd 100644 --- a/v3/integrations/nrfasthttp/instrumentation.go +++ b/v3/integrations/nrfasthttp/instrumentation.go @@ -50,7 +50,7 @@ func WrapHandle(app *newrelic.Application, pattern string, handler fasthttp.Requ if app == nil { return pattern, handler } - + secureAgent.SendEvent("API_END_POINTS", pattern, "*") // add the wrapped function to the trace options as the source code reference point // (but only if we know we're collecting CLM for this transaction and the user didn't already // specify a different code location explicitly). From 1cd514f45ffbd5d11a68e47d3b2965a82401ca99 Mon Sep 17 00:00:00 2001 From: Aayush garg Date: Mon, 19 Feb 2024 10:59:47 +0530 Subject: [PATCH 3/7] Added functionality get handler function name --- v3/integrations/nrecho-v3/nrecho.go | 2 +- v3/integrations/nrecho-v4/nrecho.go | 2 +- v3/integrations/nrfasthttp/instrumentation.go | 2 +- v3/integrations/nrgin/nrgin.go | 2 +- v3/integrations/nrgorilla/nrgorilla.go | 4 ++-- v3/integrations/nrhttprouter/nrhttprouter.go | 2 +- v3/internal/utilities.go | 16 ++++++++++++++++ v3/newrelic/instrumentation.go | 4 +++- 8 files changed, 26 insertions(+), 8 deletions(-) diff --git a/v3/integrations/nrecho-v3/nrecho.go b/v3/integrations/nrecho-v3/nrecho.go index 4b46bbf50..ad01b871e 100644 --- a/v3/integrations/nrecho-v3/nrecho.go +++ b/v3/integrations/nrecho-v3/nrecho.go @@ -96,7 +96,7 @@ func WrapRouter(engine *echo.Echo) { if engine != nil { router := engine.Routes() for _, r := range router { - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method) + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method, r.Name) } } } diff --git a/v3/integrations/nrecho-v4/nrecho.go b/v3/integrations/nrecho-v4/nrecho.go index c6e1511fb..0b5b9fe87 100644 --- a/v3/integrations/nrecho-v4/nrecho.go +++ b/v3/integrations/nrecho-v4/nrecho.go @@ -134,7 +134,7 @@ func WrapRouter(engine *echo.Echo) { if engine != nil { router := engine.Routes() for _, r := range router { - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method) + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method, r.Name) } } } diff --git a/v3/integrations/nrfasthttp/instrumentation.go b/v3/integrations/nrfasthttp/instrumentation.go index 41d621edd..92e7990ee 100644 --- a/v3/integrations/nrfasthttp/instrumentation.go +++ b/v3/integrations/nrfasthttp/instrumentation.go @@ -50,7 +50,7 @@ func WrapHandle(app *newrelic.Application, pattern string, handler fasthttp.Requ if app == nil { return pattern, handler } - secureAgent.SendEvent("API_END_POINTS", pattern, "*") + secureAgent.SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) // add the wrapped function to the trace options as the source code reference point // (but only if we know we're collecting CLM for this transaction and the user didn't already // specify a different code location explicitly). diff --git a/v3/integrations/nrgin/nrgin.go b/v3/integrations/nrgin/nrgin.go index 954a752da..5c4b46401 100644 --- a/v3/integrations/nrgin/nrgin.go +++ b/v3/integrations/nrgin/nrgin.go @@ -148,7 +148,7 @@ func WrapRouter(engine *gin.Engine) { if engine != nil { router := engine.Routes() for _, r := range router { - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method) + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method, internal.HandlerName(r.HandlerFunc)) } } } diff --git a/v3/integrations/nrgorilla/nrgorilla.go b/v3/integrations/nrgorilla/nrgorilla.go index 872161e21..418f2d2d6 100644 --- a/v3/integrations/nrgorilla/nrgorilla.go +++ b/v3/integrations/nrgorilla/nrgorilla.go @@ -120,10 +120,10 @@ func WrapRouter(router *mux.Router) { } methods, _ := route.GetMethods() if len(methods) == 0 { - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, "*") + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, "*", internal.HandlerName(route.GetHandler())) } else { for _, method := range methods { - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method) + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method, internal.HandlerName(route.GetHandler())) } } return nil diff --git a/v3/integrations/nrhttprouter/nrhttprouter.go b/v3/integrations/nrhttprouter/nrhttprouter.go index 66854ab96..4babe08b8 100644 --- a/v3/integrations/nrhttprouter/nrhttprouter.go +++ b/v3/integrations/nrhttprouter/nrhttprouter.go @@ -84,7 +84,7 @@ func (r *Router) handle(method string, path string, original httprouter.Handle) } } r.Router.Handle(method, path, handle) - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method) + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method, internal.HandlerName(original)) } // DELETE replaces httprouter.Router.DELETE. diff --git a/v3/internal/utilities.go b/v3/internal/utilities.go index e6c78e5ca..d57538b9a 100644 --- a/v3/internal/utilities.go +++ b/v3/internal/utilities.go @@ -7,6 +7,8 @@ import ( "bytes" "encoding/json" "fmt" + "reflect" + "runtime" "time" ) @@ -26,3 +28,17 @@ func CompactJSONString(js string) string { } return buf.String() } + +// HandlerName return name of a function. +func HandlerName(h interface{}) string { + if h == nil { + return "" + } + t := reflect.ValueOf(h).Type() + if t.Kind() == reflect.Func { + if pointer := runtime.FuncForPC(reflect.ValueOf(h).Pointer()); pointer != nil { + return pointer.Name() + } + } + return "" +} diff --git a/v3/newrelic/instrumentation.go b/v3/newrelic/instrumentation.go index cd42e7de5..6e38eec1b 100644 --- a/v3/newrelic/instrumentation.go +++ b/v3/newrelic/instrumentation.go @@ -5,6 +5,8 @@ package newrelic import ( "net/http" + + "github.com/newrelic/go-agent/v3/internal" ) // instrumentation.go contains helpers built on the lower level api. @@ -41,7 +43,7 @@ func WrapHandle(app *Application, pattern string, handler http.Handler, options // (but only if we know we're collecting CLM for this transaction and the user didn't already // specify a different code location explicitly). cache := NewCachedCodeLocation() - secureAgent.SendEvent("API_END_POINTS", pattern, "*") + secureAgent.SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) return pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var tOptions *traceOptSet var txnOptionList []TraceOption From 90f295878f0cd61895970a3001c61b55e194521d Mon Sep 17 00:00:00 2001 From: Aayush garg Date: Mon, 18 Mar 2024 17:31:19 +0530 Subject: [PATCH 4/7] minor fix --- v3/integrations/nrfasthttp/instrumentation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v3/integrations/nrfasthttp/instrumentation.go b/v3/integrations/nrfasthttp/instrumentation.go index 92e7990ee..a8949d57d 100644 --- a/v3/integrations/nrfasthttp/instrumentation.go +++ b/v3/integrations/nrfasthttp/instrumentation.go @@ -50,7 +50,7 @@ func WrapHandle(app *newrelic.Application, pattern string, handler fasthttp.Requ if app == nil { return pattern, handler } - secureAgent.SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) // add the wrapped function to the trace options as the source code reference point // (but only if we know we're collecting CLM for this transaction and the user didn't already // specify a different code location explicitly). From 5295ca744ab78761a0498db14d8dea8edb68308a Mon Sep 17 00:00:00 2001 From: Aayush garg Date: Wed, 20 Mar 2024 13:28:40 +0530 Subject: [PATCH 5/7] Added document for wrapRouter --- v3/integrations/nrecho-v3/nrecho.go | 13 ++++++++++++- v3/integrations/nrecho-v4/nrecho.go | 14 +++++++++++++- v3/integrations/nrgin/nrgin.go | 11 +++++++++++ v3/integrations/nrgorilla/nrgorilla.go | 14 +++++++++++++- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/v3/integrations/nrecho-v3/nrecho.go b/v3/integrations/nrecho-v3/nrecho.go index ad01b871e..b6793a4bd 100644 --- a/v3/integrations/nrecho-v3/nrecho.go +++ b/v3/integrations/nrecho-v3/nrecho.go @@ -92,8 +92,19 @@ func Middleware(app *newrelic.Application) func(echo.HandlerFunc) echo.HandlerFu } } +// WrapRouter extract api endpoints from the echo instance passed to it +// which is used to detect application URL mapping(api-endpoints) for provable security. +// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// e := echo.New() +// .... +// .... +// .... +// +// nrecho.WrapRouter(e) +// + func WrapRouter(engine *echo.Echo) { - if engine != nil { + if engine != nil && newrelic.IsSecurityAgentPresent() { router := engine.Routes() for _, r := range router { newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method, r.Name) diff --git a/v3/integrations/nrecho-v4/nrecho.go b/v3/integrations/nrecho-v4/nrecho.go index 0b5b9fe87..c8327afa4 100644 --- a/v3/integrations/nrecho-v4/nrecho.go +++ b/v3/integrations/nrecho-v4/nrecho.go @@ -130,8 +130,20 @@ func Middleware(app *newrelic.Application, opts ...ConfigOption) func(echo.Handl } } } + +// WrapRouter extract api endpoints from the echo instance passed to it +// which is used to detect application URL mapping(api-endpoints) for provable security. +// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// e := echo.New() +// .... +// .... +// .... +// +// nrecho.WrapRouter(e) +// + func WrapRouter(engine *echo.Echo) { - if engine != nil { + if engine != nil && newrelic.IsSecurityAgentPresent() { router := engine.Routes() for _, r := range router { newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method, r.Name) diff --git a/v3/integrations/nrgin/nrgin.go b/v3/integrations/nrgin/nrgin.go index 5c4b46401..d5c8a4dd0 100644 --- a/v3/integrations/nrgin/nrgin.go +++ b/v3/integrations/nrgin/nrgin.go @@ -144,6 +144,17 @@ func MiddlewareHandlerTxnNames(app *newrelic.Application) gin.HandlerFunc { return middleware(app, false) } +// WrapRouter extract api endpoints from the router instance passed to it +// which is used to detect application URL mapping(api-endpoints) for provable security. +// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// router := gin.Default() +// .... +// .... +// .... +// +// nrgin.WrapRouter(router) +// + func WrapRouter(engine *gin.Engine) { if engine != nil { router := engine.Routes() diff --git a/v3/integrations/nrgorilla/nrgorilla.go b/v3/integrations/nrgorilla/nrgorilla.go index 418f2d2d6..53e10c72e 100644 --- a/v3/integrations/nrgorilla/nrgorilla.go +++ b/v3/integrations/nrgorilla/nrgorilla.go @@ -111,8 +111,20 @@ func Middleware(app *newrelic.Application) mux.MiddlewareFunc { }) } } + +// WrapRouter extract api endpoints from the router object passed to it +// which is used to detect application URL mapping(api-endpoints) for provable security. +// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// r := mux.NewRouter() +// .... +// .... +// .... +// +// nrgorilla.WrapRouter(router) +// + func WrapRouter(router *mux.Router) { - if router != nil { + if router != nil && newrelic.IsSecurityAgentPresent() { router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { path, err1 := route.GetPathTemplate() if err1 != nil { From 97147762bb0872c500de4c5332d610de37297031 Mon Sep 17 00:00:00 2001 From: Aayush garg Date: Tue, 26 Mar 2024 16:38:23 +0530 Subject: [PATCH 6/7] update security agent version --- v3/integrations/nrsecurityagent/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v3/integrations/nrsecurityagent/go.mod b/v3/integrations/nrsecurityagent/go.mod index a02f77032..5bf053dcd 100644 --- a/v3/integrations/nrsecurityagent/go.mod +++ b/v3/integrations/nrsecurityagent/go.mod @@ -3,7 +3,7 @@ module github.com/newrelic/go-agent/v3/integrations/nrsecurityagent go 1.19 require ( - github.com/newrelic/csec-go-agent v0.7.0 + github.com/newrelic/csec-go-agent v1.1.0 github.com/newrelic/go-agent/v3 v3.29.0 github.com/newrelic/go-agent/v3/integrations/nrsqlite3 v1.2.0 gopkg.in/yaml.v2 v2.4.0 From 25526a6f6c700c96423372a8b7ab4e98e5d6f7b4 Mon Sep 17 00:00:00 2001 From: Aayush garg Date: Fri, 29 Mar 2024 20:14:24 +0530 Subject: [PATCH 7/7] Added IsSecurityAgentPresent check --- v3/integrations/nrecho-v3/nrecho.go | 5 +++-- v3/integrations/nrecho-v4/nrecho.go | 5 +++-- v3/integrations/nrfasthttp/instrumentation.go | 4 +++- v3/integrations/nrgin/nrgin.go | 7 ++++--- v3/integrations/nrgorilla/nrgorilla.go | 5 +++-- v3/integrations/nrhttprouter/nrhttprouter.go | 4 +++- v3/newrelic/instrumentation.go | 6 +++++- 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/v3/integrations/nrecho-v3/nrecho.go b/v3/integrations/nrecho-v3/nrecho.go index b6793a4bd..8125265b6 100644 --- a/v3/integrations/nrecho-v3/nrecho.go +++ b/v3/integrations/nrecho-v3/nrecho.go @@ -92,9 +92,10 @@ func Middleware(app *newrelic.Application) func(echo.HandlerFunc) echo.HandlerFu } } -// WrapRouter extract api endpoints from the echo instance passed to it +// WrapRouter extracts API endpoints from the echo instance passed to it // which is used to detect application URL mapping(api-endpoints) for provable security. -// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// In this version of the integration, this wrapper is only necessary if you are using the New Relic security agent integration [https://github.com/newrelic/go-agent/tree/master/v3/integrations/nrsecurityagent], +// but it may be enhanced to provide additional functionality in future releases. // e := echo.New() // .... // .... diff --git a/v3/integrations/nrecho-v4/nrecho.go b/v3/integrations/nrecho-v4/nrecho.go index c8327afa4..d768c7a76 100644 --- a/v3/integrations/nrecho-v4/nrecho.go +++ b/v3/integrations/nrecho-v4/nrecho.go @@ -131,9 +131,10 @@ func Middleware(app *newrelic.Application, opts ...ConfigOption) func(echo.Handl } } -// WrapRouter extract api endpoints from the echo instance passed to it +// WrapRouter extracts API endpoints from the echo instance passed to it // which is used to detect application URL mapping(api-endpoints) for provable security. -// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// In this version of the integration, this wrapper is only necessary if you are using the New Relic security agent integration [https://github.com/newrelic/go-agent/tree/master/v3/integrations/nrsecurityagent], +// but it may be enhanced to provide additional functionality in future releases. // e := echo.New() // .... // .... diff --git a/v3/integrations/nrfasthttp/instrumentation.go b/v3/integrations/nrfasthttp/instrumentation.go index a8949d57d..f05a8b770 100644 --- a/v3/integrations/nrfasthttp/instrumentation.go +++ b/v3/integrations/nrfasthttp/instrumentation.go @@ -50,7 +50,9 @@ func WrapHandle(app *newrelic.Application, pattern string, handler fasthttp.Requ if app == nil { return pattern, handler } - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) + if newrelic.IsSecurityAgentPresent() { + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) + } // add the wrapped function to the trace options as the source code reference point // (but only if we know we're collecting CLM for this transaction and the user didn't already // specify a different code location explicitly). diff --git a/v3/integrations/nrgin/nrgin.go b/v3/integrations/nrgin/nrgin.go index d5c8a4dd0..e2943466b 100644 --- a/v3/integrations/nrgin/nrgin.go +++ b/v3/integrations/nrgin/nrgin.go @@ -144,9 +144,10 @@ func MiddlewareHandlerTxnNames(app *newrelic.Application) gin.HandlerFunc { return middleware(app, false) } -// WrapRouter extract api endpoints from the router instance passed to it +// WrapRouter extracts API endpoints from the router instance passed to it // which is used to detect application URL mapping(api-endpoints) for provable security. -// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// In this version of the integration, this wrapper is only necessary if you are using the New Relic security agent integration [https://github.com/newrelic/go-agent/tree/master/v3/integrations/nrsecurityagent], +// but it may be enhanced to provide additional functionality in future releases. // router := gin.Default() // .... // .... @@ -156,7 +157,7 @@ func MiddlewareHandlerTxnNames(app *newrelic.Application) gin.HandlerFunc { // func WrapRouter(engine *gin.Engine) { - if engine != nil { + if engine != nil && newrelic.IsSecurityAgentPresent() { router := engine.Routes() for _, r := range router { newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", r.Path, r.Method, internal.HandlerName(r.HandlerFunc)) diff --git a/v3/integrations/nrgorilla/nrgorilla.go b/v3/integrations/nrgorilla/nrgorilla.go index 53e10c72e..a8425d0a3 100644 --- a/v3/integrations/nrgorilla/nrgorilla.go +++ b/v3/integrations/nrgorilla/nrgorilla.go @@ -112,9 +112,10 @@ func Middleware(app *newrelic.Application) mux.MiddlewareFunc { } } -// WrapRouter extract api endpoints from the router object passed to it +// WrapRouter extracts API endpoints from the router object passed to it // which is used to detect application URL mapping(api-endpoints) for provable security. -// Skip if you are not using [nrsecurityagent](https://pkg.go.dev/github.com/newrelic/go-agent/v3/integrations/nrsecurityagent). +// In this version of the integration, this wrapper is only necessary if you are using the New Relic security agent integration [https://github.com/newrelic/go-agent/tree/master/v3/integrations/nrsecurityagent], +// but it may be enhanced to provide additional functionality in future releases. // r := mux.NewRouter() // .... // .... diff --git a/v3/integrations/nrhttprouter/nrhttprouter.go b/v3/integrations/nrhttprouter/nrhttprouter.go index 4babe08b8..d1df356eb 100644 --- a/v3/integrations/nrhttprouter/nrhttprouter.go +++ b/v3/integrations/nrhttprouter/nrhttprouter.go @@ -84,7 +84,9 @@ func (r *Router) handle(method string, path string, original httprouter.Handle) } } r.Router.Handle(method, path, handle) - newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method, internal.HandlerName(original)) + if newrelic.IsSecurityAgentPresent() { + newrelic.GetSecurityAgentInterface().SendEvent("API_END_POINTS", path, method, internal.HandlerName(original)) + } } // DELETE replaces httprouter.Router.DELETE. diff --git a/v3/newrelic/instrumentation.go b/v3/newrelic/instrumentation.go index 6e38eec1b..b58db6ccc 100644 --- a/v3/newrelic/instrumentation.go +++ b/v3/newrelic/instrumentation.go @@ -43,7 +43,11 @@ func WrapHandle(app *Application, pattern string, handler http.Handler, options // (but only if we know we're collecting CLM for this transaction and the user didn't already // specify a different code location explicitly). cache := NewCachedCodeLocation() - secureAgent.SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) + + if IsSecurityAgentPresent() { + secureAgent.SendEvent("API_END_POINTS", pattern, "*", internal.HandlerName(handler)) + } + return pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var tOptions *traceOptSet var txnOptionList []TraceOption